dspic33f different interrupt priority levels for freertos api calling ISR

Hi is it possible to use different interrupt priority levels for the interrupt service routines? All ISR must be able to call freertos api (e.g. queues)? What must be changed in the kernel? best regards Dani

dspic33f different interrupt priority levels for freertos api calling ISR

According to the documentation – in the current implementation any interrupt that calls FreeRTOS functions must run at the lowest interrupt priority level. Any other interrupt can run at any priority level.

dspic33f different interrupt priority levels for freertos api calling ISR

Hi Dave thank you for the fast response. How can the kernel be modified to overcome this limitation? best regards Dani

dspic33f different interrupt priority levels for freertos api calling ISR

I would have to re-familiarise myself with the architecture, when you support so many it becomes a bit of a blur, but basically: When you enter a critical section you have to disable interrupts only up to a certain priority level, rather than globally, so when you are inside an interrupt you can enter critical sections without stopping other interrupts from nesting. When a context switch is required in an interrupt you have to hold it pending until the interrupt nesting has unwound. That means you will have to create your own interrupt entry and exit code, rather than using the compiler generated code. You can look at the PIC32 port as a reference, albeit for a completely dissimilar architecture, the principals are the same. The PIC32 supports a full interrupt nesting model. Regards.

dspic33f different interrupt priority levels for freertos api calling ISR

If I understand you correct, I can call API from a higher interrupt priority level as long as portENDSWITCHINGISR is never called with pdTRUE?

dspic33f different interrupt priority levels for freertos api calling ISR

I don’t think so, the problem is that I don’t think the port doesn’t implement critical sections in interrupt routines, because interrupt that call FreeRTOS do not nest. Interrupt nesting requires that the ISR critical section block off all interrupts that might interface with FreeRTOS. This could be fixed also.

dspic33f different interrupt priority levels for freertos api calling ISR

looks like I’m not the only one 😉 http://www.freertos.org/FreeRTOSSupportForumArchive/May2011/freertosFreeRTOSqueueissue4548926.html Unfortunately I need nesting. All the ISRs basically only use xQueueReceiveFromISR, xQueueSendToBackFromISR, uxQueueMessagesWaitingFromISR. There is only one interrupt routine that is running every 125us which is critical. So I could add critical section around RTOS API calls on the lower priority interrupt routines, tick timer does not need extra sections?

dspic33f different interrupt priority levels for freertos api calling ISR

I disabled all lower priority interrupt routines and test the critical ISR with higher priority level. Looks like this is not working 🙁

dspic33f different interrupt priority levels for freertos api calling ISR

There is no way to call a FreeRTOS function from a higher than configKERNELINTERRUPTPRIORITY interrupt, but all you need to do is to modify configKERNELINTERRUPTPRIORITY in FreeRTOSConfig.c to some level (I use 5). If you want to stick with the current supported port then you also need to change the line MOV #32, W0 in the appropriate portasm file in Source/portable/MPLAB (in your case portasmdsPIC.s )to MOV #PRIO<<5 where PRIO is your new configKERNELINTERRUPTPRIORITY setting and as a side note make sure that you have the symbol MPLABDSPICPORT in your project settings when using a dsPIC. (edit) I forgot, you also need to change port.c line #if configKERNELINTERRUPT_PRIORITY != 1 to your new priority If you are feeling a little adventurous, you can instead use my port.c file, no changes, no asm file and as a bonus get hardware stack checking! Please see http://interactive.freertos.org/entries/28123677-FreeRTOS-V7-5-3-port-for-ALL-16-bit-pics-with-hardware-stack-checking-SPLIM- mike

dspic33f different interrupt priority levels for freertos api calling ISR

Hi Mike thank you for your reply. Now I’m totally confused. See text vom RTOS page below, claiming all must be running at configKERNELINTERRUPTPRIORITY. So you use 5 and place tick timer on a much lower interrupt priority level (e.g. 1) and the interrupt service routines something between 2 and 5? best regards Dani “For ports that only implement configKERNELINTERRUPTPRIORITY configKERNELINTERRUPTPRIORITY sets the interrupt priority used by the RTOS kernel itself. Interrupts that call API functions must also execute at this priority. Interrupts that do not call API functions can execute at higher priorities and therefore never have their execution delayed by the RTOS kernel activity (within the limits of the hardware itself).”

dspic33f different interrupt priority levels for freertos api calling ISR

Mike’s port is a different port – or at least – a greatly modified port. Note he has posted a link to his code in the FreeRTOS Interactive site. Regards.

dspic33f different interrupt priority levels for freertos api calling ISR

I can’t unequivocally contradict that quote (I’ve only been using FreeRTOS for 2 weeks, but I believe they mean to say at this priority or lower). The kernel uses this priority (it actually uses a port routine) to effectively disable all interrupts at configKERNELINTERRUPTPRIORITY or lower during critical sections, which is why you can’t call a RTOS function from a higher priority interrupt – the kernel could be in a critical section. I don’t know why the initial port used interrupt level 1 in the PICS given they have 7 levels, but… I can also tell you that I have my little system running with many interrupts running below and one running above priority 5 and it woks as long as I haven’t improved it recently! (There used to be a sign outside my lab 40 years ago – If it’s working it will be improved, if it isn’t working it was improved yesterday!

dspic33f different interrupt priority levels for freertos api calling ISR

There are two separate issues with using multiple interrupt levels and allowing interrupt that access FreeRTOS to nest. First is the need to be able to have a critical section inside the interrupts. The PIC24 port could define this operation, but doesn’t due to the second issue. The second issue is task switching forced by an ISR. The method that the PIC24/dsPIC ports use, is not compatible with nesting interrupts. It should be possible to come up with an alternate port layer which does implements interrupt nesting, but it is likely to come with a cost, both in complexity and speed. Since normally interrupt that interact with FreeRTOS tend to be short and quick, having only a single level for all of them isn’t normally a problem. As to the interrupt that needs to run every 125us, does this NEED to call a FreeRTOS API function? Would it be possible to do at least most of the needed processing in the interrupt (I presume it isn’t much) using ordinary memory buffers, and using something slower (like a timer hook) to relay information to FreeRTOS. One trick that you can do is steal the interrupt vector from an unused device and manually trigger the interrupt to let your higher priority interrupt trigger something at configKERNELINTERRUPTPRIORITY that can talk to FreeRTOS.

dspic33f different interrupt priority levels for freertos api calling ISR

Richard, thank you for the details. The codec gets audio and control data (e.g. change volume) over freertos queues. It does only pull one sample out of the queue sends it to codec and pulls one sample out of the codec into the queue. Then checks the control data queue, if it is not idle, it sends that control info to the codec as well and reads the results out and places that in another queue. I understand the limitations and costs in speed that might arise. Of course this could be done without FreeRTOS calls, but honestly having such a great OS, does it make sense to do the same in two different ways? I can’t remember having used different API in an ISR than Queues so far. So I think Queues are some special case. Maybe making a special type of Queues that overcomes the limitations and can be used in higher level ISR as well would solve the problem.

dspic33f different interrupt priority levels for freertos api calling ISR

It sounds like this is the common design mistake of passing too high speed of data through the FreeRTOS queue. It sounds like the data for this ISR could be stored in regular circular buffers, and the task level just needs to make sure it keeps far enough ahead that it can block for the next timer tick rather than for space in the queue. It then processes until it again has enough data in the queue before blocking again. This means that the ISR doesn’t need to talk to FreeRTOS, and thus can have a higher priority. It sounds like enough needs to be done that you can’t just use a DMA channel to do the transfer.

dspic33f different interrupt priority levels for freertos api calling ISR

Mike, I tried your solutions 1. changed configKERNELINTERRUPTPRIORITY to 5 2. changed line to vPortYield: MOV #160, W0 3. changed #if configKERNELINTERRUPT_PRIORITY != 5 tick timer and all isr run now at configKERNELINTERRUPTPRIORITY. The scheduler never executes the tasks. _T1Interrupt routine is never called What am I missing?

dspic33f different interrupt priority levels for freertos api calling ISR

Richard, the problem is that I need to generate a local echo for the headphones in the ISR which is done sample by sample. That delay must be as low as possible as the codec already introduces some delay due to internal filters. The DSPIC has enough power to waste some cycles with frequent ISR call overhead. The problem is that there are other DMA interrupts already in the system. If using one interrupt priority level, those will block the system for too long (heavy data transfer over interface). No way to overcome this. So the most reasonable thing is to priorize the codec routine over the other isr, running into the problem of this topic :-(. I would not say that this is a common design mistake. One reason for me to use a RTOS is the speed up development and use a hardware that has enough power to support this luxury.

dspic33f different interrupt priority levels for freertos api calling ISR

Richard, taking your advice I removed the queues and added some ringbuffer for audio data and simple struct for codec control. The ISR is not completely FreeRTOS API free 🙁 It is working as it should with configKERNELINTERRUPTPRIORITY (1), but if I increase the interrupt priority level of that ISR to configKERNELINTERRUPTPRIORITY+1 (IPC15bits.DCIIP = (configKERNELINTERRUPTPRIORITY+1);) it does NOT anymore. (looks like the isr is never called) Again what am I missing?

dspic33f different interrupt priority levels for freertos api calling ISR

Ok, found it, I’m overwriting SR in the ISR, which also contains IPL, so I assume Mike his mod would work as well.

dspic33f different interrupt priority levels for freertos api calling ISR

Just to clarify – first – the instructions for changes relate to the current port. secondly – while I would like to take credit for a vastly improved port, all I did was reorganize the code into a single file, and tidied up (IMHO) the ifdefs removing the configKERNELINTERRUPTPRIORITY restriction using CPP macros. The only real change was to add SPLIM which was a few lines of code.

dspic33f different interrupt priority levels for freertos api calling ISR

swissEmbeded As in my response to Richard (not Richard Damon), my stuff did not change the semantics of the port, so it wouldn’t work differently. Having said that I’m not sure why your changing the SR register caused things to fail (at least the way you described), the correct IPL would have been restored when you exited the interrupt. You did say that the interrupt was not FreeRTOS API free, and that would cause bad things to happen it you went to (configKERNELINTERRUPTPRIORITY+1) for the reasons in previous posts. Richard Damon has brought up a point (nesting FreeRTOS calls) that I assumed worked because the PIC port instructions included instructions for changing configKERNELINTERRUPTPRIORITY. I even …. (more excuses) He is at least half correct, there is a problem. I think I haven’t seen the problem because my interrupts don’t share queues, but … Regardless, I wanted you to be very wary of using multiple interrupt levels (for now). I’m onto another project, but I need (well want) nested interrupts and I will figure it out – though it might not be tomorrow!. I have started another thread about this and hopefully Richard Damon will be kind enough to lead me through the problems (and hopefully solutions) mike

dspic33f different interrupt priority levels for freertos api calling ISR

Mike, I’m using some libs from microchip. Those libs heavily modify registers for DSP instructions, those registers needs to be reset/restored in the ISR (sr, corcon, modcon is enough). BTW I added the following traps in my main. AddressError might be helpfull. //Error traps //Oscillator Fail Error trap routine void attribute((interrupt, auto_psv)) _OscillatorFail(void) { INTCON1bits.OSCFAIL=0; for(;;); } //Address Error trap routine void attribute((interrupt, auto_psv)) _AddressError(void) { INTCON1bits.ADDRERR=0; for(;;); } //Stack Error trap routine void attribute((interrupt, auto_psv)) _StackError(void) { INTCON1bits.STKERR=0; for(;;); } //maths (Arithmetic) Error trap routine void attribute((interrupt, auto_psv)) _MathError(void) { INTCON1bits.MATHERR=0; for(;;); } Dave, Richard ^2, Mike, thank you yery much for your help.

dspic33f different interrupt priority levels for freertos api calling ISR

I thank you for your thank you, but all I’ve done so far is lead you astray! The current port doesn’t handle modcon. I wondered about that, but left it till I got to the point where I can play with the math stuff. I kinda felt that if interrupts worked then all would be ok, and if they didn’t then the math routines would disable interrupts to protect, but I checked and they don’t in fact I found a post that included this warning (from Microchip)
“When integrating with the DSP Library, you must examine the Function Profile of each function description to determine which resources are used. If a library function will be interrupted, it is your responsibility to save and restore the contents of all registers used by the function, including the state of the DO, REPEAT and special addressing hardware. Naturally this also includes saving and restoring the contents of the CORCON and Status registers.”
So, as far as I have read the problem with modcon is that it affects how a register is used, say W3. If the interrupt routine (or anything it calls) uses W3 as a pointer bad things will happen. If this is true then you need to modify the timer routine in port.c to save and reset it (and anytime you call taskYield()). I did a quick google of modcon interrupt and got some interesting results (but old) including a post in FreeRTOS https://sourceforge.net/p/freertos/discussion/382005/thread/cc40786a a couple (related) suggested they needed to initialize CORCON to 0x24 or they got an address error (I’m guessing what they really needed to do was CORCON |=0x04, though why PSV access would be disabled??? I seem to be taking an unhealthy interest in the PIC24 port, so I would appreciate your feedback on what it takes to get your stuff working. (plus I want to play with the math stuff sometime this winter) As all task switches in the port are done either through interrupts or in idle all that may be necessary is to make sure DSP users replace the timer1 interrupt. saving stuff is one thing, but more ominous is having to reset corcon and modcom and ???? mike

dspic33f different interrupt priority levels for freertos api calling ISR

First, my comment on using DMA was just a suggestion on a way to reduce processor load. It still might be possible to use the DMA, even if you need to send the data to two places, as you can setup, I believe, 2 DMA channels, for for each output device and start them up together. The key to the ring buffer idea was to make the ISR FreeRTOS free, so it would be allowed to be at a higher interrupt level, and thus not influenced by the other interrupts and be able to nest with them. If you have a requirement to absolutely minimize latency to the interrupt, this might be important. Another option would be to work to rewrite the port layer to allow nested ISRs as has been discussed. This isn’t an impossible task, but does have some interesting design issues. It also sounds like something needs to be done to fix the CORCON / modcon problem. I haven’t looked enough at the issues on that to give advice. My dsPic work didn’t need to use them so I didn’t study them enough.

dspic33f different interrupt priority levels for freertos api calling ISR

I don’t think you need it, but if you want to try it, I have a solution for fully nested interrupts. mike