We have ChibiOS running on our STM32F7 uC (=master). We have a thread on the master, that sends a UART message to the Slaves (STM32L4) every 64us.
For easier understanding, I created a minimal example of the problem:
Code: Select all
THD_WORKING_AREA(uart_thread_wa, 1024);
THD_FUNCTION(uart_thread, p) {
(void)p;
chRegSetThreadName("UART Thread");
while (true) {
msg_t msg = palWaitLineTimeout(DATA_READY, TIME_US2I(100));
palSetPad(GPIOD, 7); // GPIO for timing measurement
uint8_t uocMessage = 1; // example message
uint8_t buffer[1] = {(uint8_t)uocMessage};
size_t p_size = sizeof(buffer);
uartStartSend(&UARTD1, p_size, buffer);
palClearPad(GPIOD, 7); // GPIO for timing measurement
}
}
}
The uart thread waits for an external signal, that comes every 64us. Then, we set a GPIO for timing measurements. We send some random message to the Slaves via the UART and then reset the timing measurement pin.
Apart from that thread there's a bunch of other threads using things like the CAN, other UARTs and the ethernet stack. All of them have a lower priority.
To analyze the execution time we measure the positive pulse width of that GPIO with an oscilloscope. Issue here is that 99% of the time the width is 350 ns but in some intervals the WECT takes up to 5us (see M:4.737us in the Meas5 window), which is 10X of the original one. That is the case for more of the functions in this thread that we removed from this example, in total that adds up to a WECT that is significantly larger than our mean time and kills our realtime requirements for the system (with a WECT of maxium 64us).
The blue signal is the timing measurement from GPIO D7 and the purple signal is a histogram for the high pulse width of the blue timing signal. The high pulse width (= time, the above shown code takes) is further analyzed in the "Meas5" box. There you can see e.g. the last measured time u and the max measured time M.
According to the “Priorities and Scheduling”, only threads with a higher priority and IRQs could interrupt the UART sending.
We also tried putting chSysLock() and chSysUnlock() arround our code as well as disabling fast interrupts.
Code:
Code: Select all
THD_WORKING_AREA(uart_thread_wa, 1024);
THD_FUNCTION(uart_thread, p) {
(void)p;
chRegSetThreadName("UART Thread");
while (true) {
msg_t msg = palWaitLineTimeout(DATA_READY, TIME_US2I(100));
chSysLock();
palSetPad(GPIOD, 7); // GPIO for timing measurement
uint8_t uocMessage = 1; // example message
uint8_t buffer[1] = {(uint8_t)uocMessage};
size_t p_size = sizeof(buffer);
uartStartSend(&UARTD1, p_size, buffer);
palClearPad(GPIOD, 7); // GPIO for timing measurement
chSysUnlock();
}
}
}
Now, the average time goes down but the WECT stays at 5us.
This effect can be found multiple times in our code as soon as we do more than just calculations.
Do you have an idea what could cause that timing delta or how to investigate further?
Thanks for your help!
Best,
Julian STABL