Microchip PIC32 MZ RTOS port
with a MIPS M14K core
[RTOS Ports]

Introduction

The PIC32MZ and PIC32MZ EF RTOS ports

This page presents the FreeRTOS port and demo application for the PIC32MZ and PIC32MZ EF 32bit microcontrollers from Microchip, which have a MIPS M14K core.

The FreeRTOS PIC32MZ port:


RTOS on PIC32 starter kit
PIC32MZ Starter Kit

The demo application

The demo application is pre-configured to use the MPLAB X IDE and the MPLAB XC32 GCC based compiler. Three build configurations are provided; PIC32MZ2048_SK which targets the standard PIC32MZ Starter Kit, and PIC32MZ2048EF_SK_SOFT_FLOAT and PIC32MZ2048EF_SK_HARD_FLOAT - both of which target the PIC32 Embedded Connectivity with FPU (EF) Starter Kit.

The demo project can be configuration to build either a simple blinky demo or a comprehensive test and demo application. The comprehensive application demonstrates and tests the interrupt nesting behaviour. Build instructions are provided on this page.



IMPORTANT! Notes on using the PIC32 MZ RTOS port

Please read all the following points before using this RTOS port.

  1. Source Code Organization
  2. The Demo Application
  3. Configuration and Usage Details
See also the FAQ My application does not run, what could be wrong?


Source Code Organization

The FreeRTOS download contains the source code and demo application projects for all the RTOS ports, so most of the files it contains are not relevant to the PIC32MZ demo. See the Source Code Organization section for a description of the downloaded files, and information on creating a new project.

The MPLAB X project that builds the PIC32MZ RTOS demo is located in the FreeRTOS/Demo/PIC32MZ_MPLAB directory.


The Demo Application


Functionality

The constant mainCREATE_SIMPLE_BLINKY_DEMO_ONLY, which is defined at the top of main.c, is used to switch between a simple 'blinky' style starter project and a more comprehensive test and demo application.


When mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1

When mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 main() calls main_blinky(). main_blinky() creates a very simple example that uses two tasks, one queue, and one software timer.


When mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0

When mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0 main() calls main_full(). main_full() creates a very comprehensive test and demo application that creates numerous RTOS tasks and software timers.


Building and debugging the demo application with MPLAB X

These instructions assume you have MPLAB X and the MPLAB XC32 compiler correctly installed on your host computer.
  1. Open the project from within the MPLAB X IDE (the location of the project is detailed in the Source Code Organization section near the top of this page).

  2. Connect the debug USB connector of the PIC32MZ Starter Kit to your host computer (the computer running MPLAB X).

  3. From the MPLAB X 'Debug' menu, select 'Debug Project'. The project should build without an errors or warnings, and the resultant binary programmed into the PIC32 flash memory.



Configuration and Usage Details

RTOS port specific configuration

Configuration items specific to this demo are contained in FreeRTOS/Demo/PIC32MZ_MPLAB/FreeRTOSConfig.h. The constants defined in that file can be edited to suit your application. In particular -

Each port #defines 'BaseType_t' to equal the most efficient data type for that processor. This port defines BaseType_t to be of type long.

Note that vPortEndScheduler() has not been implemented.


Interrupt service routines

Interrupt service routines that cannot nest have no special requirements and can be written as per the compiler documentation. However interrupts written in this manner will utilise the stack of whichever task was interrupted, rather than the system stack, necessitating that adequate stack space be allocated to each created task. It is therefore not recommended to write interrupt service routines in this manner.

Interrupts service routines that can nest require a simple assembly wrapper, as demonstrated below. It is recommended that all interrupts be written in this manner.

The T5 interrupt (the interrupt for the timer that is used to demonstrate a task being unblocked from an interrupt) within the PIC32MZ demo can be used as an example - the assembly code wrapper for which is replicated in Listing 1, and the C handler for which is replicated in Listing 2.



/* Prototype to be included in a C file to ensure the vector is
correctly installed.  Note that because this ISR uses the FreeRTOS
assembly wrapper the IPL setting in the following prototype has no
effect.  The interrupt priority is set using the Microchip provided
library functions. */
void __attribute__( (interrupt(ipl3), vector(_TIMER_5_VECTOR)))
                                                    vT5InterruptWrapper( void );


/* Header file in which portSAVE_CONTEXT and portRESTORE_CONTEXT are defined. */
#include "ISR_Support.h"

/* Ensure correct instructions is used. */
.set	nomips16
.set 	noreorder

/* Interrupt entry point. */
vT5InterruptWrapper:

  /* Save the current task context.  This line MUST be included! */
  portSAVE_CONTEXT

  /* Call the C function to handle the interrupt. */
  jal vT5InterruptHandler
  nop

  /* Restore the context of the next task to execute.  This line
  MUST be included! */
  portRESTORE_CONTEXT

  .end  vT5InterruptWrapper
Listing 1: Assembly code wrapper for handling an interrupt that can cause a context switch


Some notes on the assembly file wrapper:

Second, the C function called by the assembly file wrapper:



void vT5InterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    /* Give the semaphore.  If giving the semaphore causes the task to leave the
    Blocked state, and the priority of the task is higher than the priority of
    the interrupted task, then xHigherPriorityTaskWoken will be set to pdTRUE
    inside the xSemaphoreGiveFromISR() function.  xHigherPriorityTaskWoken is
    later passed into portEND_SWITCHING_ISR(), where a context switch is
    requested if it is pdTRUE.  The context switch ensures the interrupt returns
    directly to the unblocked task. */
    xSemaphoreGiveFromISR( xBlockSemaphore, &xHigherPriorityTaskWoken );

    /* Clear the interrupt */
    IFS0CLR = _IFS0_T5IF_MASK;

    /* See comment above the call to xSemaphoreGiveFromISR(). */
    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
Listing 2: The C portion of an ISR that can cause a context switch


Some notes on the C function:


Critical sections

Exiting a critical section will always set the interrupt priority such that all interrupts are enabled, no matter what its level when the critical section was entered. FreeRTOS API functions themselves will use critical sections.


Execution context

In line with the conventions documented in the XC32 compiler manual, the RTOS kernel assumes all access to the K0 and K1 registers will be atomic. Code generated by the XC32 compiler conforms to this convention so if you are writing application purely in C then this is of no concern. Care must be taken however if any hand written assembly code is used to ensure that that too conforms to the same convention.


Shadow registers

The interrupt shadow registers are not used and are therefore available for use by the host application. Shadow registers should not be used within an interrupt service routine that causes a context switch.


Software interrupts

The RTOS kernel makes use of the MIPS software interrupt 0. This interrupt is therefore not available for use by the application.


Memory allocation

Source/Portable/MemMang/heap_4.c is included in the PIC32 demo application project to provide the memory allocation required by the RTOS kernel. Please refer to the Memory Management section of the API documentation for full information.