recently i tried to use FreeRTOS for my Microchip’s dsPIC33EP128GM310 microcontroller. In particular, I started from and adapted the Github demo project proposed by Microchip (/microchip-pic-avr-examples/pic24-dspic33-freertos-demo)
For simplicity’s sake at the moment I’m just running a dummy LED-blinking task. However, if I set an optimization level higher than 0 (i.e. none) in MPLABX IDE the code stops working and the MCU keeps resetting. In particular, it crashes during the first tick-timer ISR. And after the successive reboot the MCU “IOPUWR” flag is asserted (defined in the manual as “An illegal opcode detection, an illegal address mode or Uninitialized W register used as an Address Pointer caused a Reset”).
I noticed there are already similar threads in forums, where the issue seems to be caused by a reset/mismanagement of the stack pointer. However, it’s not clear to me how to solve the problem. Do you have any clue?
The project uses FreeRTOS v.9.0.0. I tried first with MPLABX IDE v.5.45 + XC16 v.1.61, and then with MPLABX IDE v.6.05 + XC16 v.2.00 (as suggested by Microchip). The behavior is the same.
There are some differences in the files.
In port.c and portasm_dspic.S they added the case (enabled) for the dsPIC33E family (see pictures).
In portmacro.h the line #define portTICK_TYPE_IS_ATOMIC 1 has been removed (even though I’m actually using a 16-bit timer for the tick timing) and placed in FreeRTOS.h as a standalone macro (set to 0 by default).
The file portasm_PIC24.S is identical (and not used, I would say).
From your description, I don’t think the changes will be the cause. The context switch code itself is written in assembler, so also won’t get impacted by the optimiser, although the code calling it could. Does the dsPIC code work in the MPLAB simulator? If so, I may be able to try to replicate this, but aren’t in a position to do that right now.
Try stepping through the code in the debugger to see how far execution gets before it crashes. For example, can you see that the code ever reaches the call to vTaskStartScheduler(). If it does, put a break point in your highest priority task (which could be the timer task, depending on the setting of configUSE_TIMERS and configTIMER_TASK_PRIORITY) to see if the first task ever starts executing. If it does, then continue getting further into the code to see if the tick interrupts and taskYIELD calls execute before it crashes. That will help narrow down where to look.