I have two threads:
Thread 1 gets data from an I2C device and takes about 512 us per acquisition
Thread 2 calculates values from the data and activates a processor output this takes about 180 us.
Thread 2 has a higher priority than thread 1.
The timing of the processes must be accurate to 2 ms i.e. two RTC Ticks.
I run a timer and which interrupts every ms with a high priority.
The ISR of the timer gives to two separate semaphores one for thread 1 and one for thread 2.
viz:
__attribute__((section(".Tim2itcm"))) void TIM2_IRQHandler(void)
//void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim2);
// __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE); /* rjg */
osSemaphoreRelease(sampleTimerSemHandle);
osSemaphoreRelease(clockControllerSemHandle);
}
You can see I'm using the CMSIS OS wrapper but this just calls the FreeRTOS functions anyway.
When I run the system from debug the sytem works fine and I get a jitter on the data of about +/- 1ms. However when I boot the system using by power cycling I end up with a hard fault which occurs during the second semaphore call. I thought I might have a stack problem so I increased the FreeRTOS minimum to 2048 with no fix.
The question I have is:
"Is it OK to have two calls to xSemaphoreGiveFromISR for the two seperate sem's or is this a no-no?"
Best regards
Rob
Yes it is fine but you are better off calling the native api otherwise you are missing the “HigherPriorityTaskWoken” parameter which could mean a context switch doesn’t happen immediately - see the docs for xSemaphoreGiveFromISR().
I will take your advice and use the native FreeRTOS Calls. I used the CMSIS thing because STM32CubeMx creates those, but I think it’s just layer of code that adds no value and obscures the underlying good stuff.
The funny thing is the code works fine if I start it using the debugger, but as soon as I power cycle it all turns to you-know-what.
I use FreeRTOS for all my STM32 apps as it is simple to use and it just works.
I replaced the tasks and semaphores with static versions. The hard fault then occurred whilst debugging so it took me five minutes to realise I hadn’t allocated sufficient stack for the second task. The semaphore buffer was getting overwritten by stack transaction so the app was passing a bad semaphore handle to the xSemaphoreTake giving a memory alignment hard fault.
I don’t know why it worked under debug, but not under power reset when I was using the dynamic tasks and sem’s.
I am using STLink V3.0 debugger with the CubeMX Eclipse IDE.
Has anyone got any theories/ideas on this?
Another question:
Why don’t CPU manufacturers provide a stack limit register in addition to the stack pointer such that if the stack hits the limit register a dedicated hard fault - stack error is generated. I know this question is beyond the scope of FreeRTOS, but such a device would save a lot of embarrassment.
Different code can cause different error/stack overflow symptoms.
You’re better off defining configASSERT, enable FreeRTOS stack checking etc. for development.
Regarding the latter question e.g. ARM Cortex-M33 and later have stack pointer limit registers supported and used by FreeRTOS.
I think one of the microchip parts FreeRTOS supports also has a stack limit register, maybe the daPIC (?). Separately, FreeRTOS ports that support memory protection bound the stack with a memory protection region that generates a memfault if you overflow (or under flow!) the stack.