Ok. Also with regard to the critical section temporarily disabling interrupts Richard mentioned it’s also much better to not keep the task spin-waiting on the queue because each xQueueReceive
call enters and exits a critical section. Means this increases the time where interrupts are disabled.
In fact, in all the UART drivers I wrote, I had a simple circular buffer with one readahead and onw writetoend pointer, and the ISR would fill the buffer without OS interference, just inform the task (ideally via task notifications) that new characters come in, the task can then read all characters accumulated as Hartmut suggested.
I also tried using my own queue, just a buffer array with an index.
Which is working fine without FreeRTOS and it was what I’m using.
I had the same issue…
In that case, DO emply tracealyzer. There appear to be external (to the UART control flow) threads of execution that interfere with what you are doing.
I agree with @RAc that there must be something else going on.
At least when using the more optimized variant with your own circular buffer and just signaling data availability to a task (as recommended using a task notification or a semaphore) and flushing all available data in the task when woken up. This should easily work with your MCU running at 120 MHz. And I think also the simple byte-by-byte transfer with a queue or stream buffer should work reliably.
Is there really no other fast firing interrupt enabled and the SysTick interrupt prio is set to default (lowest) ? Interrupt nesting is also enabled ?
Interrupt nesting is enabled by setting different priorities on NVIC.
I did not change anything on the SysTick priorities.
With the same MCU. I have attempted to read bytes from USART while core works at 12MHz and it was working fine without any issues.
That was without FreeRTOS.
The bytes are placed into the queue byte-byte. I read them also byte-byte and place them into an array for further processing.
That piece of code worked at 12MHz core, baudrate 115200. without FreeRTOS.
The only thing I can think of to help you would be to ask you for your implementations of the critical section API. Other than that, Tracealyzer is your friend…
Which section exactly?
That’s what I’d expected. I’m using an even lower CPU clock in an FreeRTOS application and also handle a USART and other peripherals reliably.
This brings us back to the question what’s going on here Strange…
NVIC prio grouping is disabled, too ? Using NVIC_SetPriorityGrouping(0);
BTW besides the good FreeRTOS documentation there is a good article here
what are your port’s custom implementations of EnterCriticalSection and LeaveCriticalSection (or what those are called)?
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */
if( uxCriticalNesting == 1 )
{
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
}
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
Do you use the FPU and the ‘CM4F’ port or the normal ‘CM3’ port ?
The normal CM3 port. My chip does not have FPU
so what do portDisableInterrupts and portEnableInterrupts resolve to?..
This is, in fact, basically what a Queue or StreamBuffer does. The Queue code has some complications in that it allows multiple tasks to be waiting for data from the Queue (which StreamBuffers omit, allowing them to be a bit more efficient).
Yes, you can perhaps make yourself slightly more efficient knowing the exact use case for the buffer, but the Stream Buffers themselves are fairly efficient.
The one advantage of the “roll your own” method is that, if you don’t put a task notify in the ISR, you can put it above the SYSCALL limit so it isn’t blocked by a critical section, then it can software signal a lower priority ISR to send the notification if needed.
Is it? A stream buffer possibly, but if the queue is being used as “put one character at a time,” the control flow is significantly less efficient, isn’t it?
If I understand correctly, in my current setup.
The USART has priority 5. That means the kernel can take priority over USART. But I can’t have a higher priority than 5 (lower number) if I use RTOS API fucntions.
You’re right
Me and many others found this post pretty good
No matter what priority the ISR has, if it uses FreeRTOS APIs, it will get blocked by critical sections. So you need to make sure that you code doesn’t use excessively long critical sections.
From everything that has been described, this seems to be what is happening.
That is why I hav suggested having the system just stop on the overrun, and look at the stack trace to see what was interrupted when that happens to see if this is just after a critical section ends, and then look closely at that critical section to figure out why it can take so long.