PIC32 taskENTER_CRITICAL question
I’m using taskENTER_CRITICAL and taskLEAVE_CRITCAL but have been having problems on PIC32.
I have two questions:-
i) ulStatus = _CP0_GET_STATUS();
ulStatus |= ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT );
_CP0_SET_STATUS( ulStatus );
is used to take the CP0 status register and modify the IPL bits with configMAX_SYSCALL_INTERRUPT_PRIORITY.
Maybe I’m wrong, but if my task is at ipl2 and MAX_SYSCALL is at ipl4 this will result in a new value of 6. As the PIC32 doc says that…. "This field is the encoded (0..63) value of the current IPL." e.g. the task in example above with ipl2 executing a crit sec will write ipl6 to status. No interrupt <=6 will preempt this crit sec when the intent was for interrupts <=4.
ii) It appears taskENTER_CRITICAL and taskLEAVE_CRITCAL are non-atomic. It would appear possible for another process to preempt/interleave and affect the STATUS register bits and then return to have _CP0_SET_STATUS write incorrect bits back from the saved ulStatus. e.g. bit 0. Is this likely to cause problems?
I have been getting problems ( processor exceptions of differing types) using the above macro’s when locking a int variable prior to incrementing whereas using asm("di") asm("ei") seems to fix the problem.
Regards Graham
PIC32 taskENTER_CRITICAL question
I’m a bit confused by the question. A task does not run at an IPL level – interrupt priorities and task priorities are two separate things, and tasks do not run in interrupts. Also taskENTER_CRITICAL() and taskEXIT_CRITICAL() should not be called from an interrupt service routine.
Also check that interrupts that are running with an IPL above that specified by configMAX_SYSCALL_INTERRUPT_PRIORITY do not call FreeRTOS API functions.
Regards.
PIC32 taskENTER_CRITICAL question
Yes sorry I used the word ‘task’ in the loosest sense.
If an interupt is say at ipl2 and it uses taskENTER_CRITICAL and configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 4 then the result as far as I can see will be 6. i.e. No interrupt other than 7 will pre-empt the interrupt. And as I mentioned, it’s non atomic, which worried me a little.
However, I didn’t know that thsse critical tasks macros shouldn’t be used within an interrupt. I can’t see that entioned in the doc?
All my interrupts are running at or below configMAX_SYSCALL_INTERRUPT_PRIORITY and are all called using the FreeRTOS wrapper. I’m not using any xxxISR calls in the interrupts that are giving me problems.
As I mentioned I’m using asm("di") and asm("ei"), running code for days and I’ve had no problems. Using the critical macros causes _exceptions errors within seconds. But then again, I was using them within interrupts!!
The code is a Circular Buffer implementation that allows seperate tasks (again loose term – could be an intteruot or FreeRTOS task) to read / write, hence the lock required to update the header data.
Anyway, my current code is fine using di/ei and is pretty efficient for a very short lock that I require.
Thanks
PIC32 taskENTER_CRITICAL question
…but as Richard said, interrupts must not call taskENTER_CRITICAL(). This goes for all ports.