PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

I’m using the PIC32MZ processor, Harmony 1.02 with it’s version of FreeRTOS (8.x), compiler XC32 v1.34, MPLAB 2.26. I’ve adapted the FreeRTOS dual CDC USB demo code for the USB and CDC tasks, mostly without changes. The Harmony configurator generates interrupt assembly code in the systeminterrupta.S file. The assembly code as-is seems to be pretty close to that recommended for FreeRTOS interrupt assembly wrappers. For example: .extern IntHandlerUSBInstance0 .section .vector_132,code, keep .equ __vector_dispatch_132, IntVectorUSBInstance0 .global __vector_dispatch_132 .set nomicromips .set noreorder .set nomips16 .set noat .ent IntVectorUSBInstance0 IntVectorUSBInstance0: portSAVE_CONTEXT la s6, IntHandlerUSBInstance0 jalr s6 nop portRESTORE_CONTEXT .end IntVectorUSBInstance0 The wrapper calls the C handler function as recommended, which then calls a Harmony-provided USB driver, void IntHandlerUSBInstance0(void) { USBDEVICETasks_ISR(sysObj.usbDevObject0); } When I use the assembly wrapper, the …TasksISR() proceeds as expected and proceeds all the way into a callback function APPUSBDeviceEventHandler(). One of the states finishes up with the standard interrupt-ending call to a semaphore operation followed by the context switch function as follows: xSemaphoreGiveFromISR(appCDCData->xSemaphoreBlockUsbConfigure, &xHigherPriorityTaskWoken1); portENDSWITCHINGISR( xHigherPriorityTaskWoken1 ); break; This brings us back to the …TasksISR(). (But it is NOT the last instruction in the Harmony ISR – there are a couple more which seems to be a no-no in the PIC32MX port docs.) When I view the call stack, I see that the higher priority task (a CDC-related task) seems to awake right there, while the interrupt is still running, and proceeds to a spot where it happens to call portENTERCRITICAL(). This generates an Assert() error, since this is not supposed to be called from an ISR. Oddly, if I chuck the assembly wrapper and just use an ISR macro, it all works. (BTW, there is also a system timer ISR that uses the mhc-generated assembly wrapper.) void __ISR(USBVECTOR, ipl4) IntHandlerUSBInstance0(void) { USBDEVICETasksISR(sysObj.usbDevObject0); } Any comments on what is happening here? Is the assembly code at fault? I’ve tried various things such as declaring the ISR wrapper in the compiler instead, and “.extern”-ing it in the assembly file, to no avail. Thanks for your consideration, Paul

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

I see that the higher priority task (a CDC-related task) seems to awake right there, while the interrupt is still running, and proceeds to a spot where it happens to call portENTER_CRITICAL().
Are you sure? I dont think a task can run if an interrupt is running, unless the task code is being called from the interrupt handling code so it is still running in the interrupt.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

I’m pretty sure that task code ends up running in the middle of the interrupt. The call stack at the assert() instant shows a couple levels deep of ISR calls, then the callback function (which should end the ISR) and then about 8 levels deep of generic Harmony task code, ending with the portEnterCritical() call. This, of course, should not be, unless Microchip coded it this way in Harmony. Which I don’t believe. Paul

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

The PIC32 port does not need to portENDSWITCHINGISR() call to be at the end of the interrupt provided that:
  • the SW0 software interrupt used for the yield has the lowest possible interrupt priority.
  • Also I think on the MIPS core it is important to ensure the lowest interrupt priority does not become enabled in the interrupt controller during the execution of other interrupts (can’t quite remember if this is the case or not). The FreeRTOS ASM code will re-enable interrupts above the priority of the currently running interrupt only – make sure no other code is re-enabling all interrupts.
Also ensure the system/interrupt stack is large enough. You might want to increase the size of configISRSTACKSIZE in FreeRTOSConfig.h to make sure. Regards.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Thanks, RTE. Okay, I tried increasing configISRSTACKSIZE considerably and doubling configISRSTACKSIZE to 800. Still getting the assert() error from a portEnterCritical() call (from Harmony code). Which should never be called during an interrupt, but it seems to be. I don’t know quite how to address your second bullet. There are no other calls to SYSINTEnable() in the app code. Perhaps an important clue to this is that when the mhc-generated assembly wrapper above is used, the assert() error happens. But when the __ISR() macro above is used, the code runs fine. It would seem that the only difference is the use of the assembly routines portSAVECONTEXT and portRESTORECONTEXT. Which would call into question the ISR stack size, right? But I doubled it! BTW, I find no configISRSTACKSIZE reference in the documentation, to study up on. Any more ideas?

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Does the FreeRTOS port layer exactly match the port layer in the official release, or has it been edited? The port layer includes all the files in the FreeRTOSSourceportableMPLABPIC32MZ directory. You can check this by downloading whichever version is used in Harmony from SourceForge: http://sourceforge.net/projects/freertos/files/FreeRTOS/ I’m not sure if it will make any difference, but just as a sanity check, try changing
la s6, IntHandlerUSBInstance0
jalr s6
nop
to
ja IntHandlerUSBInstance0
nop
Regards.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

I tried changing the assembly to:
ja      IntHandlerUSBInstance0
// la s6, IntHandlerUSBInstance0 // jalr s6 But this results in an unrecognized opcode. Not being a MIPS assembly-literate, I find it strange. BTW, this is PIC32MZ, not MX. I’ll check the port layer as you recommended.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

And yes, the offending instruction is preceded by .extern IntHandlerUSBInstance0

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Sorry – my bad – it should have been “jal IntHandlerUSBInstance0” not “ja IntHandlerUSBInstance0”. Regards.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Gotcha. Using “jal” will assemble properly but the result is the same assert() call. I can’t find the FreeRTOS version in the Harmony docs, though I’m sure I saw it once. The “vendor release date” is December 2014 and I see a lot of “November 10” in the port files. I’ll see if that matches anything.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

The version number should be in the comments at the top of every source file as: “FreeRTOS V[whatever] – Copyright (C) 201x Real Time Engineers Ltd.” where [whatever] is the version number. Regards.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Oh, yes. FreeRTOS 8.1.2. Shall I diff every port/ file? Or merely check the version?

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Diff the whole of every port file. Should be simple enough if you have a diff tool. Regards.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Not quite sure of this. The diff tool I have comes with MPLABX and goes one file at a time. Seems that it would be faster to just plug in the version direct from your site. The FreeRTOS dual CDC comm port PIC32MZ app that comes with Harmony works, and that uses the assembly wrapper and all the port/ files.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Status: I get the assert() error signifying a call to portEnterCritical() in ISR code if I use the macros portSAVECONTEXT and portRESTORECONTEXT in the ISR assembly wrapper recommended by FreeRTOS. No assert() error if these macros are commented out. I’ve tried raising as many stack sizes as I can think of, to no avail. configMAXSYSCALLINTERRUPT_PRIORITY is at the same level as my highest task.

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Okay, here’s the solution. Contrary to the Harmony manual, you MUST NOT #define the macro OSALUSERTOS when you are using FreeRTOS. Either the macro name or the actual usage is completely misleading. If the configurator puts it in, comment it out. And explain why, as follows. (Note: the RTOS demos in Harmony 1.02 all comment it out, but do NOT explain why.) With OSALUSERTOS defined (as 1), the osaldefinitions.h file will include the source file osalfreertos.c. YOU DO NOT WANT THIS. This was the problem with the portEnterCritical() call from an ISR, and the resultant assert() error. Without this, the macro file osalimplbasic.h file will be pulled in and interrupt safe calls will be made. And you will be happy. Real Time Engineers, please address this manual discrepancy with Microchip. This confusion is misleading and unprofessional. And will someone please explain what oral_freertos.c is for, if not for this? Paul

PIC32 assembly wrappers problem with portEND_SWITCHING_ISR()

Paul – I will certainly bring this to Microchip’s attention and let you know the conclusion.