rtc alarm running with threads

Hi,

I’ve been working on an application that activates rtc alarms every few seconds, when the alarm is activated it sends a message to a thread. This msg is used in a thread that in its turn sends messages over gnrc. However, after a while sending messages, it stops and the mcu only gets in in the rtc alarm, without returning to the thread context.

I tested a basic thread, that just puts some serial message, and a rtc alarm showing another message. The program starts running the thread but every time the rtc alarm activates i get a Riot Kernel panic: HARD FAULT HANDLER and then reboots the system.

I imagine there is a problem when both functions are supposed to run at the same time and it gets a kernel panic, or some kind of problem with the context switcher. Any thoughts on why this is happening, advice on how to workaround it, etc. would be much appreciated. Cheers,

Paula

Dear Paula,

can you share the code of your application somewhere? That might help to find the issues. I would suppose that the interrupt handler is faulty or consumes too much memory or something like this.

I think start debugging with a basic application that just prints some text whenever a message from the RTC interrupt is received is a smart idea. Now, we need to figure out what exactly triggers the kernel panic. Are you compiling your application with the DEVELHELP macro enabled? And which port are you using? Maybe you can use `make debug` to get more information.

Cheers, Oleg

Hi Oleg,

Thanks for your help. I should mention that i’m working on the 2017.07 release. This is the main functions of the code, the behavor i’m expecting is to trigger the alarm every TIME_WAITING seconds, run sale_test() and the go back to the control thread. However i get a kernel panic or run only the control_thread, without considering the rtc_alarm after a while.

char stack[THREAD_STACKSIZE_DEFAULT]; kernel_pid_t control_pid;

int sale_test(void){ DEBUG(“Send sale\n”); return 1; }

/* set interrupt event every TIME_WAITING = 10 seconds*/ static void onInterruptEvent(void *arg) { (void)arg; struct tm time; rtc_get_alarm(&time);

/* schedule next message / time.tm_sec += TIME_WAITING; / Make an interrupt */ sale_test();

rtc_clear_alarm(); rtc_set_alarm(&time, onInterruptEvent, 0); }

void *control_thread(void *arg) { (void) arg; while (1) { DEBUG(“Running thread right now\n”); xtimer_usleep(100000); } return NULL; }

int main(void) { printf(“This test will display ‘Alarm every %i seconds’\n”, TIME_WAITING);

/* initialize rtc functions */ application_init();

onInterruptEvent(NULL);

control_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, control_thread, NULL, “control”); (void) control_pid;

return 0; }

Cheers,

Paula

Hi Paula,

on which platform are you running your application?

Kaspar

Hi Kaspar,

I’m running on stm32-l1, board nucleo-152RE

Paula

Hi Paula, It is likely that the debug print in the sale_test function overflows the ISR stack. You can increase that stack size by adding CFLAGS += -DISR_STACKSIZE=1024 to your Makefile. The interrupt service routines on cortex m have a separate stack which is set to 512 bytes by default. Usually when you need to do more complex tasks you will unlock a mutex from the ISR or set a thread flag which will tell some user space thread to perform the complex tasks instead of running it inside the ISR. Having long interrupt service routines may also delay the execution of other interrupt handlers, so there are several benefits of performing tasks in user space threads.

Best regards, Joakim