vPortEnterCritical and vPortExitCritical

mikej42 wrote on Wednesday, June 17, 2009:

Hello. I have a product running on Ateml atsam7s256 processor, and IAR EWARM 5.30.
I am havong a problem not apparently seeing SPI interrupts occasionally.
I have put some debug in to vPortEnterCritical and vPortExitCritical to try and see thelongest time the interrupts are masked, and it comes up with a time of around 1ms. These long masks always seem to occur while processing xTaskResumeAll, usually from a queue send or receive.
Putting some more debuging seems to indicate the the taskYIELD() just before the end of xTaskResumeAll is executed immediately, even though we are in the middle of portENTER_CRITICAL and portEXIT_CRITICAL, as though this does not stop an ‘SWI 0’.

Is this supposed to happen like this, or is my understanding lacking? Any help or pointer around here gratefully received.

Regards Mike

rtel wrote on Wednesday, June 17, 2009:

Yes it is supposed to happen like this, and no instrumenting the enter/exit critical functions will not give you the maximum time the critical section is valid for - this is because of exactly the behaviour you see with the SWI 0. 

Each task keeps its own interrupt status flags so you can switch to a task that has interrupts enabled from a critical section.  The measurement you are taking could be entering a critical section - running several other tasks that have interrupts enabled - then exiting the critical section, so not be a measure of how long the interrupts were disabled for at all.

The kernel is designed to work this way, and its not an error or mistake, but a way of ensuring a task can commence running again from a known state.


mikej42 wrote on Wednesday, June 17, 2009:

Thanks Richard. I had forgotten that the interrupt status is restored during the task switch.
I have definite symptoms of missing an SPI interrupt. Do you have any way to determine the maximum duration of masking interrupts?


incrediball wrote on Sunday, June 21, 2009:

What speed is your SPI running at and are you needing interrupts on each byte? Relative to the highest possible SPI speed, the interrupt latency under FreeRTOS will be a problem. However if you want to do high speed SPI then the only sensible way to do this is using the PDC. It takes care of the data transfer for you and is much faster than getting the ARM to interrupt and feed the SPI every byte.

One other thing to consider: the SPI module has a bug which Atmel have never recognised as such (it’s more of a “this behaviour is by design” issue). If the SPI module runs out of data to transmit, it will release the chip select. Many devices do not like having their chip select released in the middle of a transfer and disregard the rest of the data when the chip select is reasserted. So, if you are not already doing this, consider doing the chip select yourself, i.e. set the pin up as a regular output and hold it in the asserted state until the data transfer is complete. This is necessary even if you are using the PDC since even that is sometimes not able to feed data to the SPI module fast enough.