Logging node activity in contiki and send it to a sink - c

I'm trying to build an application in contiki3.0 where several nodes broadcast their sensor data while writing it in a log and then every 3 min send the log to a sink and start a new log.
I also want the sink to acknowledge receiving the log.
I've been trying to do that for a month but I couldn't get the code to work properly, I would appreciate any help.
This is the code of the nodes:
#include "contiki-conf.h"
#include "dev/button-sensor.h"
#include "dev/light-sensor.h"
#include "dev/leds.h"
#include "net/linkaddr.h"
#include "contiki.h"
#include "lib/random.h"
#include "sys/ctimer.h"
#include "sys/etimer.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "event-post.h"
#include "simple-udp.h"
#include <limits.h>
#include <stdio.h>
#include <string.h>
#define UDP_PORT 1234
#define SEND_INTERVAL (20 * CLOCK_SECOND)
#define SEND_TIME (random_rand() % (SEND_INTERVAL))
/*---------------------------------------------------------------------------*/
static struct simple_udp_connection broadcast_connection;
static process_event_t event_data_ready;
/*---------------------------------------------------------------------------*/
PROCESS(sara, "broadcast");
PROCESS(broadcast_example_process, "BB");
AUTOSTART_PROCESSES(&sara, &broadcast_example_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(sara, ev, data)
{
static struct etimer timer;
static struct event_struct es;
PROCESS_BEGIN();
es.s_val = SHRT_MAX-2;
es.i_val = INT_MAX-2;
es.l_val = LONG_MAX-2;
/* sizeof(long long) == sizeof(long) on sensinodes - see other examples*/
es.ll_val = LONG_MAX-2;
/* and some typedef-ed unsigned variables */
es.u8_val = UCHAR_MAX-2;
es.u16_val = USHRT_MAX-2;
es.u32_val = ULONG_MAX-2;
event_data_ready = process_alloc_event();
printf("Contiki allocated event ID %d.\r\n", event_data_ready);
etimer_set(&timer, CLOCK_CONF_SECOND * 2);
while(1){
printf("Sensor process: Wait for timer event...\r\n");
/* Wait on our timer */
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
/* blip */
/* leds_toggle(LEDS_BLUE); */
/* Set the 'sensor' value before throwing the event */
printf("Sensor Process: Incrementing values...%d,%d,%d,%d,%d,%d, %d\r\n", es.s_val++, es.i_val++, es.l_val++, es.ll_val++, es.u8_val++, es.u16_val++,es.u32_val++);
/* Post our event.
* N.B. es is declared static.
* Try passing a volatile variable and observe the results... */
printf("Sensor Process: Generating 'Data Ready' event.\r\n");
process_post(&broadcast_example_process, event_data_ready, &es);
/* reset the timer so we can wait on it again */
etimer_reset(&timer);
}
SENSORS_ACTIVATE(button_sensor);
SENSORS_ACTIVATE(light_sensor);
static int counter=0;
printf("Light: \%u\n", light_sensor);
counter++;
if (counter == 4){
printf("Hello, world you have read the light 4 times \n");
}
PROCESS_END();
}
static void
receiver(struct simple_udp_connection *c,
const uip_ipaddr_t *sender_addr,
uint16_t sender_port,
const uip_ipaddr_t *receiver_addr,
uint16_t receiver_port,
const uint8_t *data,
uint16_t datalen)
{
printf("Data received on port %d from port %d with length %d\n",
receiver_port, sender_port, datalen);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(broadcast_example_process, ev, data)
{
static struct etimer periodic_timer;
static struct etimer send_timer;
uip_ipaddr_t addr;
PROCESS_BEGIN();
simple_udp_register(&broadcast_connection, UDP_PORT,
NULL, UDP_PORT,
receiver);
etimer_set(&periodic_timer, SEND_INTERVAL);
while(1) {
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
etimer_reset(&periodic_timer);
etimer_set(&send_timer, SEND_TIME);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&send_timer));
printf("Sending broadcast\n");
uip_create_linklocal_allnodes_mcast(&addr);
simple_udp_sendto(&broadcast_connection, data, sizeof(data), &addr);
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
and this is the sink code, which is a udp-sink code from Contiki examples:
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#include "net/ip/uip.h"
#include "net/rpl/rpl.h"
#include "net/linkaddr.h"
#include "net/netstack.h"
#include "dev/button-sensor.h"
#include "dev/serial-line.h"
#if CONTIKI_TARGET_Z1
#include "dev/uart0.h"
#else
#include "dev/uart1.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "collect-common.h"
#include "collect-view.h"
#define DEBUG DEBUG_PRINT
#include "net/ip/uip-debug.h"
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#define UDP_CLIENT_PORT 8775
#define UDP_SERVER_PORT 5688
static struct uip_udp_conn *server_conn;
PROCESS(udp_server_process, "UDP server process");
AUTOSTART_PROCESSES(&udp_server_process,&collect_common_process);
/*---------------------------------------------------------------------------*/
void
collect_common_set_sink(void)
{
}
/*---------------------------------------------------------------------------*/
void
collect_common_net_print(void)
{
printf("I am sink!\n");
}
/*---------------------------------------------------------------------------*/
void
collect_common_send(void)
{
/* Server never sends */
}
/*---------------------------------------------------------------------------*/
void
collect_common_net_init(void)
{
#if CONTIKI_TARGET_Z1
uart0_set_input(serial_line_input_byte);
#else
uart1_set_input(serial_line_input_byte);
#endif
serial_line_init();
PRINTF("I am sink!\n");
}
/*---------------------------------------------------------------------------*/
static void
tcpip_handler(void)
{
uint8_t *appdata;
linkaddr_t sender;
uint8_t seqno;
uint8_t hops;
if(uip_newdata()) {
appdata = (uint8_t *)uip_appdata;
sender.u8[0] = UIP_IP_BUF->srcipaddr.u8[15];
sender.u8[1] = UIP_IP_BUF->srcipaddr.u8[14];
seqno = *appdata;
hops = uip_ds6_if.cur_hop_limit - UIP_IP_BUF->ttl + 1;
collect_common_recv(&sender, seqno, hops,
appdata + 2, uip_datalen() - 2);
}
}
/*---------------------------------------------------------------------------*/
static void
print_local_addresses(void)
{
int i;
uint8_t state;
PRINTF("Server IPv6 addresses: ");
for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
state = uip_ds6_if.addr_list[i].state;
if(state == ADDR_TENTATIVE || state == ADDR_PREFERRED) {
PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr);
PRINTF("\n");
/* hack to make address "final" */
if (state == ADDR_TENTATIVE) {
uip_ds6_if.addr_list[i].state = ADDR_PREFERRED;
}
}
}
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(udp_server_process, ev, data)
{
uip_ipaddr_t ipaddr;
struct uip_ds6_addr *root_if;
PROCESS_BEGIN();
PROCESS_PAUSE();
SENSORS_ACTIVATE(button_sensor);
PRINTF("UDP server started\n");
#if UIP_CONF_ROUTER
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1);
/* uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); */
uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL);
root_if = uip_ds6_addr_lookup(&ipaddr);
if(root_if != NULL) {
rpl_dag_t *dag;
dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr);
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
rpl_set_prefix(dag, &ipaddr, 64);
PRINTF("created a new RPL dag\n");
} else {
PRINTF("failed to create a new RPL DAG\n");
}
#endif /* UIP_CONF_ROUTER */
print_local_addresses();
/* The data sink runs with a 100% duty cycle in order to ensure high
packet reception rates. */
NETSTACK_RDC.off(1);
server_conn = udp_new(NULL, UIP_HTONS(UDP_CLIENT_PORT), NULL);
udp_bind(server_conn, UIP_HTONS(UDP_SERVER_PORT));
PRINTF("Created a server connection with remote address ");
PRINT6ADDR(&server_conn->ripaddr);
PRINTF(" local/remote port %u/%u\n", UIP_HTONS(server_conn->lport),
UIP_HTONS(server_conn->rport));
while(1) {
PROCESS_YIELD();
if(ev == tcpip_event) {
tcpip_handler();
} else if (ev == sensors_event && data == &button_sensor) {
PRINTF("Initiaing global repair\n");
rpl_repair_root(RPL_DEFAULT_INSTANCE);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

Related

xQueueReceive blocks the execution of other tasks

I am developing a FreeRTOS application on a Cortex-M4 (NXP i.MX8MM) that creates 4 tasks.
The first task is waiting to receive a character on a UART. As soon as a buffer is received, it is sent to task 3 with xQueueSend.
The second task is the transmission task via the UART. It waits permanently for the reception of a buffer (sent by task 4) with xQueueReceive.
Currently, I manage to create these 4 tasks, but only the first 2 are executed. I have the impression that the second task, and particularly the xQueueReceive function, is blocking (or not executing properly) the execution of the last 2 tasks. If I comment out the xQueueReceive function, all tasks run without any problem. All configASSERT in the xQueueReceive function pass without problem.
Where do you think this can come from?
My code:
main.c
/* System includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Kernel includes */
#include "FreeRTOS.h"
#include "task.h"
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "rsc_table.h"
/* Other includes */
#include "A_version.h"
#include "A_rpmsg.h"
#include "A_ip_task.h"
#include "A_queue.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Globals
******************************************************************************/
/* Queue RPMSG -> UART RS-485 */
static QueueHandle_t rpmsg_to_uart_queue = NULL;
/* Queue RPMSG <- UART RS-485 */
static QueueHandle_t uart_to_rpmsg_queue = NULL;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
/*!
* #brief Main function
*/
int main(void)
{
uint8_t status = 1;
/* Initialize standard SDK demo application pins */
/* Board specific RDC settings */
BOARD_RdcInit();
BOARD_InitBootPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
BOARD_InitMemory();
copyResourceTable();
#ifdef MCMGR_USED
/* Initialize MCMGR before calling its API */
(void)MCMGR_Init();
#endif /* MCMGR_USED */
PRINTF("Start Appli_metier: %s\r\n", NUM_ET_DATE_VERSION_CARTE_CM);
/* Chargement des paramètres de l'UART */
F_ip_485_load_params();
/* Initialisation de l'UART */
status = F_init_ip_485();
/* Initialisation de RPMsg */
if(status != 0)
{
PRINTF("ERROR INIT UART\r\n");
} else {
status = rpmsg_init();
}
rpmsg_to_uart_queue = xQueueCreate(10, sizeof(struct Message *));
if (rpmsg_to_uart_queue != NULL)
{
vQueueAddToRegistry(rpmsg_to_uart_queue, "RPMsg to UART queue");
}
uart_to_rpmsg_queue = xQueueCreate(10, sizeof(struct Message *));
if (uart_to_rpmsg_queue != NULL)
{
vQueueAddToRegistry(uart_to_rpmsg_queue, "UART to RPMsg queue");
}
/* Lancement des taches */
if(status != 0)
{
PRINTF("ERROR INIT RPMSG\r\n");
} else {
PRINTF("Avant F_ip_485_task\r\n");
/* Lancement de la tache UART */
F_ip_485_task(rpmsg_to_uart_queue, uart_to_rpmsg_queue);
PRINTF("Avant rpmsg_task\r\n");
/* Lancement de la tache RPMSG (cote A53) */
rpmsg_task(rpmsg_to_uart_queue, uart_to_rpmsg_queue);
}
vTaskStartScheduler();
PRINTF("Failed to start FreeRTOS on core0.\n");
for (;;)
;
}
tasks 1 and 2:
#include "A_ip_task.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "board.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "fsl_debug_console.h"
#include "A_ip_485.h"
#include "A_queue.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define IP_485_RX_TASK_STACK_SIZE (256)
#define IP_485_TX_TASK_STACK_SIZE (256)
#define MAX_BUF_TRAME_ETHERNET 1520
/* Task priorities. */
#define hello_task_PRIORITY (configMAX_PRIORITIES - 1)
#define TASK_DELAY_IP_485 200
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
typedef struct _uart_struct
{
QueueHandle_t my_queue_to_uart;
QueueHandle_t my_queue_to_rpmsg;
} uart_struct;
static uart_struct my_uart_struct;
static TaskHandle_t ip_485_rx_task_handle = NULL;
static TaskHandle_t ip_485_tx_task_handle = NULL;
STRUCT_parametre_uart S_device_UART[NBR_MAX_UART];
unsigned char TUCH_ip_485_buffer[MAX_BUF_TRAME_ETHERNET];
static void F_ip_485_rx_task(void *pvParameters)
{
uart_struct * param_struct = pvParameters;
Message st_msg;
uint16_t UI_lg;
/* Block for 5µs. */
const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);
PRINTF("\r\nF_ip_485_rx_task running ...\r\n");
/* On attend la réception d'une trame sur la file */
for (;;)
{
if ((UI_lg = F_driverUART_read(UART_IP485, TUCH_ip_485_buffer, MAX_BUF_TRAME_ETHERNET)) != 0)
{
//TODO: F_traitement_RX_IP_485(TUCH_ip_485_buffer, UI_lg); /* Traitement dans MQX */
/* Remplacer par écriture dans la queue de RPMsg pour envoi vers Cortex-A53 */
st_msg.size = UI_lg;
xQueueSend(param_struct->my_queue_to_rpmsg, (void *)&st_msg, 10);
}
vTaskDelay(xDelay);
}
vTaskSuspend(NULL);
}
static void F_ip_485_tx_task(void *pvParameters)
{
uart_struct * param_struct = pvParameters;
Message rcv_msg;
/* Block for 5µs. */
const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);
PRINTF("\r\nF_ip_485_tx_task running ...\r\n");
for (;;)
{
if (xQueueReceive(param_struct->my_queue_to_uart, (void *)&rcv_msg, 0) != pdTRUE)
{
PRINTF("Failed to receive queue.\r\n");
}
else
{
/* On envoie tous les octets */
F_driverUART_IP485_write(rcv_msg.body, rcv_msg.size);
}
vTaskDelay(xDelay);
}
vTaskSuspend(NULL);
}
void F_ip_485_task(QueueHandle_t r_to_u, QueueHandle_t u_to_r)
{
my_uart_struct.my_queue_to_uart = r_to_u;
my_uart_struct.my_queue_to_rpmsg = u_to_r;
if (xTaskCreate(F_ip_485_rx_task, "IP 485 RX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &ip_485_rx_task_handle) !=
pdPASS)
{
PRINTF("Task creation failed!.\r\n");
while (1)
; }
if (xTaskCreate(F_ip_485_tx_task, "IP 485 TX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &ip_485_tx_task_handle) !=
pdPASS)
{
PRINTF("Task creation failed!.\r\n");
while (1)
;
}
}
tasks 3 and 4:
#include "A_rpmsg.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "board.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "rpmsg_lite.h"
#include "rpmsg_queue.h"
#include "rpmsg_ns.h"
#include "A_queue.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define RPMSG_LITE_SHMEM_BASE (VDEV0_VRING_BASE)
#define RPMSG_LITE_LINK_ID (RL_PLATFORM_IMX8MM_M4_USER_LINK_ID)
#define RPMSG_LITE_NS_ANNOUNCE_STRING "rpmsg-virtual-tty-channel-1"
#define RPMSG_RX_TASK_STACK_SIZE (128)
#define RPMSG_TX_TASK_STACK_SIZE (128)
#ifndef LOCAL_EPT_ADDR
#define LOCAL_EPT_ADDR (30)
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
typedef struct _rpmsg_struct
{
struct rpmsg_lite_endpoint *volatile my_ept;
volatile rpmsg_queue_handle my_queue;
struct rpmsg_lite_instance *volatile my_rpmsg;
QueueHandle_t my_queue_to_uart;
QueueHandle_t my_queue_to_rpmsg;
} rpmsg_struct;
static TaskHandle_t rpmsg_rx_task_handle = NULL;
static TaskHandle_t rpmsg_tx_task_handle = NULL;
static SemaphoreHandle_t mutex;
static rpmsg_struct my_rpmsg_struct;
static volatile uint32_t remote_addr;
static char app_rx_buf[1500]; /* Each RPMSG buffer can carry less than 512 payload */
static char app_tx_buf[1500]; /* Each RPMSG buffer can carry less than 512 payload */
static void rpmsg_rx_task(void *param)
{
rpmsg_struct * param_struct = param;
Message st_msg;
volatile uint32_t local_remote_addr;
void *rx_buf;
uint32_t len;
int32_t result;
void *tx_buf;
uint32_t size;
boolean init = false;
/* Block for 5µs. */
const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);
for (;;)
{
/* Get RPMsg rx buffer with message */
result =
rpmsg_queue_recv_nocopy(param_struct->my_rpmsg, param_struct->my_queue, (uint32_t *)&remote_addr, (char **)&rx_buf, &len, RL_BLOCK);
if (result != 0)
{
assert(false);
} else {
PRINTF("RPMsg received !\r\n");
}
/* Copy string from RPMsg rx buffer */
assert(len < sizeof(app_rx_buf));
memcpy(st_msg.body, rx_buf, len);
st_msg.size = len;
xQueueSend(param_struct->my_queue_to_uart, (void *)&st_msg, 10);
//app_rx_buf[len] = 0; /* End string by '\0' */
if ((len == 2) && (app_rx_buf[0] == 0xd) && (app_rx_buf[1] == 0xa))
PRINTF("Get New Line From Master Side\r\n");
else
PRINTF("Get Message From Master Side : \"%s\" [len : %d]\r\n", app_rx_buf, len);
if(!init) {
local_remote_addr = remote_addr;
// Release the mutex so that the creating function can finish
xSemaphoreGive(mutex);
init = true;
}
/* Release held RPMsg rx buffer */
result = rpmsg_queue_nocopy_free(param_struct->my_rpmsg, rx_buf);
if (result != 0)
{
assert(false);
}
}
vTaskSuspend(NULL);
}
static void rpmsg_tx_task(void *param)
{
rpmsg_struct * param_struct = param;
Message rcv_msg;
volatile uint32_t local_remote_addr;
void *rx_buf;
uint32_t len;
int32_t result;
void *tx_buf;
uint32_t size;
/* Block for 5µs. */
const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);
/* On attend de recevoir l'adresse de destination */
PRINTF("\r\nM4 waiting for destination address ...\r\n");
// Take the mutex
xSemaphoreTake(mutex, portMAX_DELAY);
local_remote_addr = remote_addr;
for (;;)
{
if (xQueueReceive(param_struct->my_queue_to_rpmsg, (void *)&rcv_msg, portMAX_DELAY) != pdTRUE)
{
PRINTF("Failed to receive queue.\r\n");
}
else
{
/* Get tx buffer from RPMsg */
tx_buf = rpmsg_lite_alloc_tx_buffer(param_struct->my_rpmsg, &size, RL_BLOCK);
assert(tx_buf);
/* Copy string to RPMsg tx buffer */
memcpy(tx_buf, rcv_msg.body, rcv_msg.size);
/* Echo back received message with nocopy send */
result = rpmsg_lite_send_nocopy(param_struct->my_rpmsg, param_struct->my_ept, local_remote_addr, tx_buf, rcv_msg.size);
if (result != 0)
{
assert(false);
} else {
PRINTF("RPMsg sent !\r\n");
}
}
}
vTaskSuspend(NULL);
}
uint8_t rpmsg_init(QueueHandle_t r_to_u, QueueHandle_t u_to_r)
{
uint8_t status;
#ifdef MCMGR_USED
uint32_t startupData;
/* Get the startup data */
(void)MCMGR_GetStartupData(kMCMGR_Core1, &startupData);
my_rpmsg = rpmsg_lite_remote_init((void *)startupData, RPMSG_LITE_LINK_ID, RL_NO_FLAGS);
/* Signal the other core we are ready */
(void)MCMGR_SignalReady(kMCMGR_Core1);
#else
my_rpmsg_struct.my_rpmsg = rpmsg_lite_remote_init((void *)RPMSG_LITE_SHMEM_BASE, RPMSG_LITE_LINK_ID, RL_NO_FLAGS);
#endif /* MCMGR_USED */
PRINTF("En attente du chargement du module RPMsg...\r\n");
while (0 == rpmsg_lite_is_link_up(my_rpmsg_struct.my_rpmsg))
;
my_rpmsg_struct.my_queue = rpmsg_queue_create(my_rpmsg_struct.my_rpmsg);
my_rpmsg_struct.my_ept = rpmsg_lite_create_ept(my_rpmsg_struct.my_rpmsg, LOCAL_EPT_ADDR, rpmsg_queue_rx_cb, my_rpmsg_struct.my_queue);
(void)rpmsg_ns_announce(my_rpmsg_struct.my_rpmsg, my_rpmsg_struct.my_ept, RPMSG_LITE_NS_ANNOUNCE_STRING, RL_NS_CREATE);
PRINTF("\r\nNameservice sent, ready for incoming messages...\r\n");
// Create mutex before starting tasks
mutex = xSemaphoreCreateMutex();
// Take the mutex
if(xSemaphoreTake(mutex, portMAX_DELAY) == pdTRUE)
{
status = 0;
} else {
status = -1;
}
return status;
}
void rpmsg_task(QueueHandle_t r_to_u, QueueHandle_t u_to_r)
{
my_rpmsg_struct.my_queue_to_uart = r_to_u;
my_rpmsg_struct.my_queue_to_rpmsg = u_to_r;
if (xTaskCreate(rpmsg_rx_task, "RPMSG RX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &rpmsg_rx_task_handle) !=
pdPASS)
{
PRINTF("Task creation failed!.\r\n");
while (1)
;
}
if (xTaskCreate(rpmsg_tx_task, "RPMSG TX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &rpmsg_tx_task_handle) !=
pdPASS)
{
PRINTF("Task creation failed!.\r\n");
while (1)
;
}
}

C, timer_settime, disarm timer and overwrite associated data?

I have to do for University a project about UDP, where i have to guarantee reliable communication; for packets, i want use timer_gettime() and timer_Settime() functions, because i can queue signals and i can associate to them a timer; in particular, struct sigevent has a field which union sigval where i can pass value to handler when signal arrived; I would like to take advantage of this passing to handler number of packets for which timer expired; I have a problem, and I've done a simple program to verify this; when I start timer, i can disarm it setting it_value of struct sigevent to 0; but data doesn't change; if I send 100 signal, header receives only data of first signal. This is my code:
#include <signal.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int d;
void err_exit(char* str)
{
perror(str);
exit(EXIT_FAILURE);
}
void sighandler(int sig, siginfo_t *si, void *uc)
{
(void) sig;
(void) uc;
d = si->si_value.sival_int;
}
void handle_signal(struct sigaction* sa)
{
sa->sa_flags = SA_SIGINFO;
sa->sa_sigaction = sighandler;
sigemptyset(&sa->sa_mask);
if (sigaction(SIGRTMAX,sa,NULL) == -1)
err_exit("sigaction");
}
void create_timer(struct sigevent* sev,timer_t* timer_id,int i)
{
union sigval s;
s.sival_int = i;
printf("value: %d\n",i);
sev->sigev_notify = SIGEV_SIGNAL;
sev->sigev_signo = SIGRTMAX;
sev->sigev_value = s;
timer_create(CLOCK_REALTIME,sev,timer_id);
}
void set_timer(timer_t timer_id,struct itimerspec* ts)
{
if(ts == NULL)
printf("itimerspec null\n");
if (timer_settime(timer_id, 0, ts, NULL) == -1){
printf("errno code: %d\n",errno);
err_exit("timer_settime");
}
}
void initialize_timerspec(struct itimerspec* ts)
{
ts->it_value.tv_sec = 2;
ts->it_value.tv_nsec = 5;
ts->it_interval.tv_sec = 0;
ts->it_interval.tv_nsec = 0;
}
void reset_timer(timer_t timer_id, struct itimerspec* ts)
{
ts->it_value.tv_sec = 0;
ts->it_value.tv_nsec = 0;
ts->it_interval.tv_sec = 0;
ts->it_interval.tv_nsec = 0;
if (timer_settime(timer_id, 0, ts, NULL) == -1){
printf("errno code: %d\n",errno);
err_exit("timer_settime");
}
}
int main()
{
struct sigaction sa;
struct itimerspec ts[2];
struct sigevent sev[2];
timer_t timer_id[2];
handle_signal(&sa);
create_timer(sev,timer_id,0);
initialize_timerspec(ts);
set_timer(timer_id,ts);
reset_timer(timer_id,ts);
create_timer(sev + 1,timer_id + 1,1);
initialize_timerspec(ts + 1);
set_timer(timer_id,ts + 1);
printf("id1: %ju id2: %ju\n",timer_id[0],timer_id[1]);
sleep(10);
printf("d = %d\n",d);
exit(EXIT_SUCCESS);
}
I disarm first timer, and send another signal; but handler receives data associated to first signal, because it prints 0. Is there a way to send to overwrite data, sending to handler data of second signal(in this case 1)?

Getting response in simple_udp_connection

I have a code in contiki cooja. I have 2 sending nodes and 2 receiving nodes as you can see in the picture1. the broadcast senders and receivers are as follows.
#include "contiki.h"
#include "lib/random.h"
#include "sys/etimer.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "net/ip/uip-debug.h"
#include "simple-udp.h"
#include <stdio.h>
#include <string.h>
#define SEND_INTERVAL (20 * CLOCK_SECOND)
#define SEND_TIME (random_rand() % (SEND_INTERVAL))
static struct simple_udp_connection broadcast_connection;
/*---------------------------------------------------------------------------*/
PROCESS(broadcast_example_process, "UDP broadcast example process");
AUTOSTART_PROCESSES(&broadcast_example_process);
/*---------------------------------------------------------------------------*/
static void
receiver(struct simple_udp_connection *c,
const uip_ipaddr_t *sender_addr,
uint16_t sender_port,
const uip_ipaddr_t *receiver_addr,
uint16_t receiver_port,
const uint8_t *data,
uint16_t datalen)
{
printf("Data received from ");
uip_debug_ipaddr_print(sender_addr);
printf(" on port %d from port %d with length %d: %s \n",
receiver_port, sender_port, datalen, data);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(broadcast_example_process, ev, data)
{
static struct etimer periodic_timer;
static struct etimer send_timer;
uip_ipaddr_t addr;
char message[20];
sprintf(message," hello ");
PROCESS_BEGIN();
simple_udp_register(&broadcast_connection, 1234,
NULL, 1900,
receiver);
etimer_set(&periodic_timer, SEND_INTERVAL);
while(1) {
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
etimer_reset(&periodic_timer);
etimer_set(&send_timer, SEND_TIME);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&send_timer));
printf("Sending broadcast\n");
uip_create_linklocal_allnodes_mcast(&addr);
simple_udp_sendto(&broadcast_connection, message , strlen(message) , &addr);
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
and receivers:
#include "contiki.h"
#include "lib/random.h"
#include "sys/ctimer.h"
#include "sys/etimer.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-ds6.h"
#include "simple-udp.h"
#include "net/ip/uip-debug.h"
#include <stdio.h>
#include <string.h>
#define UDP_PORT 1900
static struct simple_udp_connection broadcast_connection;
/*---------------------------------------------------------------------------*/
PROCESS(broadcast_example_process, "UDP broadcast example process");
AUTOSTART_PROCESSES(&broadcast_example_process);
/*---------------------------------------------------------------------------*/
static void
receiver(struct simple_udp_connection *c,
const uip_ipaddr_t *sender_addr,
uint16_t sender_port,
const uip_ipaddr_t *receiver_addr,
uint16_t receiver_port,
const uint8_t *data,
uint16_t datalen)
{
printf("Data received from ");
uip_debug_ipaddr_print(sender_addr);
printf(" on port %d from port %d with length %d: %s \n",
receiver_port, sender_port, datalen, data);
/* this line should work,right?*/
simple_udp_sendto(&broadcast_connection, "hello",5, sender_addr);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(broadcast_example_process, ev, data)
{
PROCESS_BEGIN();
simple_udp_register(&broadcast_connection, 1900,
NULL, 1234,
receiver);
while(1) {
PROCESS_WAIT_EVENT();
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
Now the problem is replying to the sender. I want each receiver node reply to the sender which has sent that message to it.
I don't know how to do that?
simple_udp_sendto() does not work.Can I use this function for this job? How should I use that?
You normally have an RDC function : packet_received. When an IT trigger, packet_received is called with the data in ptr. You just have to send again by reading the address of the sender.
Edit : you probably have a packet_received on the network layer, with same function. If you don't, you should implements one.

Linux kernel version mismatch

I'm trying to create a simple kernel module which makes the keyboard LEDs flashing. It works fine on Linux 3.16 (Ubuntu 14.04) but it doesn't change the LED status on 4.5 (Arch).
I can't figure out what kind of difference causes it, I didn't find anything useful in demsg. Any idea how could I find about this problem?
Code:
#include <linux/module.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include <linux/console_struct.h>
#include <linux/vt_kern.h>
#include "device.h"
#include "timer.h"
#define LEDS_ON 0x07
#define LEDS_OFF 0xFF
static int major_number;
static struct class *class;
static struct tty_driver *driver;
static unsigned long led_status = LEDS_OFF;
static void timer_callbak(void)
{
if (led_status == LEDS_OFF) {
led_status = LEDS_ON;
} else {
led_status = LEDS_OFF;
}
driver->ops->ioctl(vc_cons[fg_console].d->port.tty, KDSETLED, led_status);
}
static long device_ioctl(struct file *file, unsigned int command, unsigned long argument)
{
if (command == ON && led_status == LEDS_OFF) {
timer_init(&timer_callbak);
} else if (command == OFF && led_status == LEDS_OFF){
timer_exit();
} else if (command != OFF && command != ON) {
printk(KERN_WARNING "Invalid ioctl() command");
return -1;
}
return 0;
}
static struct file_operations operations = {
.unlocked_ioctl = device_ioctl
};
dev_t create_dev_type(void)
{
return MKDEV(major_number, 0);
}
void create_device(void)
{
major_number = register_chrdev(0, NAME, &operations);
printk("Keyboard leds registered with major_number \"%d\"", major_number);
class = class_create(THIS_MODULE, NAME);
device_create(class, NULL, create_dev_type(), NULL, NAME);
}
void device_init(void)
{
create_device();
driver = vc_cons[fg_console].d->port.tty->driver;
printk("Keyboard leds device Initialized");
}
void device_exit(void)
{
device_destroy(class, create_dev_type());
class_unregister(class);
class_destroy(class);
unregister_chrdev(major_number, NAME);
printk("Keyboard leds device exited");
}
MODULE_LICENSE("GPL");
That's how I'm trying to invoke it:
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include "src/device.h"
int main(void)
{
int fd;
if ((fd = open("/dev/keyboard_leds", O_RDWR|O_NONBLOCK)) < 0) {
perror("Open failed!");
return -1;
}
ioctl(fd, ON);
close(fd);
return 0;
}

Write timer in Linux device driver

I'm newbies with the module linux.
I try to create a counter module where the counter is increment on timer callback.
The result of the counter must be send to an other module (a memory module).
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/uaccess.h>
MODULE_AUTHOR("Helene");
MODULE_DESCRIPTION("Module memory");
MODULE_SUPPORTED_DEVICE("none");
MODULE_LICENSE("Dual BSD/GPL");
/* Global variables of the driver */
/* Buffer to store data */
char *memory_buffer;
int result;
struct file_operations memory_fops;
int memory_open(struct inode *inode, struct file *filp) {
// printk(KERN_DEBUG "Opening memory module\n");
return 0;
}
int memory_release(struct inode *inode, struct file *filp) {
// printk(KERN_DEBUG "Releasing of memory module\n");
return 0;
}
ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){
// printk(KERN_DEBUG "Reading memory module : %s\n", buf);
if (*f_pos > 0)
return 0;
if (count > strlen(memory_buffer))
count = strlen(memory_buffer);
copy_to_user(buf,memory_buffer,count);
*f_pos = *f_pos + count;
return count;
}
ssize_t memory_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos) {
// printk(KERN_DEBUG "Writing memory module : %s\n", buf);
copy_from_user(memory_buffer, buf, count);
return count;
}
static int __init memory_init(void) {
/* Registering device */
result = register_chrdev(0, "memory", &memory_fops);
if (result < 0) {
printk(KERN_DEBUG "memory: cannot obtain major number \n");
return result;
}
/* Allocating memory for the buffer */
memory_buffer = kmalloc(1, GFP_KERNEL);
if (!memory_buffer) {
result = -ENOMEM;
goto fail;
}
memset(memory_buffer, 0, 1);
printk(KERN_ALERT "Inserting memory module : %d\n", result);
return 0;
fail:
//memory_exit();
return result;
}
static void __exit memory_exit(void) {
/* Freeing the major number */
unregister_chrdev(result, "memory");
/* Freeing buffer memory */
if (memory_buffer) {
kfree(memory_buffer);
}
printk(KERN_DEBUG "Removing memory module\n");
}
struct file_operations memory_fops = {
owner: THIS_MODULE,
read: memory_read,
write: memory_write,
open: memory_open,
release: memory_release
};
module_init(memory_init);
module_exit(memory_exit);
The memory module works. My problem is when I call the function : filp_open/fp->f_op->write/filp_close on the function timer callback.
I have test these functions out of the timer callback and it's work.
Why the filp_open function (& co) don't work on timer callback function ?
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_from/to_user */
MODULE_LICENSE("GPL");
static struct timer_list my_timer;
int cptNbClic ;
int result;
struct file_operations timer_fops;
int write_file_system(struct file *fp, char * buf){
int nb;
mm_segment_t old_fs=get_fs();
set_fs(get_ds());
nb = fp->f_op->write(fp,buf ,10, &fp->f_pos);
set_fs(old_fs);
return nb;
}
void writeInMemory(void){
// printk(KERN_DEBUG "busy %d\n", busy);
int nbwrite;
char buf[3];
int fmemory;
fmemory=filp_open ("/dev/memory", O_WRONLY | O_APPEND | O_CREAT,0); //don't work on this function
if (fmemory==NULL){//verification de l'ouverture
printk(KERN_ALERT "filp_open error input memory!!.\n");
return -1;
}
sprintf(buf, "%d", cptNbClic);
printk(KERN_DEBUG "%d\n", cptNbClic);
nbwrite = write_file_system(fmemory, buf);
filp_close(fmemory, 0);
}
void my_timer_callback( unsigned long data )
{
cptNbClic++;
printk(KERN_DEBUG "cptNbClic %d\n", cptNbClic);
writeInMemory();
setup_timer(&my_timer, my_timer_callback, 0);
mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));
}
static int timer_open(struct inode *inode, struct file *filp) {
/* setup your timer to call my_timer_callback */
cptNbClic = 0;
setup_timer(&my_timer, my_timer_callback, 0);
/* setup timer interval to 200 msecs */
mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));
return 0;
}
static int timer_release(struct inode *inode, struct file *filp) {
/* Success */
printk(KERN_DEBUG "Releasing of cpt module\n");
del_timer(&my_timer);
return 0;
}
static int __init timer_init(void) {
/* Registering device */
result = register_chrdev(0, "timer", &timer_fops);
if (result < 0) {
printk(KERN_DEBUG "timer: cannot obtain major number \n");
return result;
}
printk(KERN_ALERT "Inserting timer module : %d\n", result);
return 0;
}
static void __exit timer_exit(void) {
unregister_chrdev(result, "timer");
printk(KERN_DEBUG "Removing timer module\n");
}
struct file_operations timer_fops = {
owner: THIS_MODULE,
open: timer_open,
release: timer_release
};
/* Declaration of the init and exit functions */
module_init(timer_init);
module_exit(timer_exit);
Sorry for my bad english
No need to call setup_timer function in your my_timer_callback().Already timer is setup. If you want a recurring timer then just again call mod_timer() in your handler which will updates your timer expire value and your timer happily runs again and again till del_timer() call.

Resources