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
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.
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
…but as Richard said, interrupts must not call taskENTER_CRITICAL(). This goes for all ports.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.