Safer Interrupt Handling Demo for the
NXP LPCXpresso55S69 Development Board
Introduction
FreeRTOS ports with Memory Protection Unit (MPU) support
enable microcontroller applications to be more robust and more secure by running application tasks in unprivileged
mode. These unprivileged mode tasks have access only to their own stacks and some pre-configured memory regions.
On these MPU enabled microcontrollers, the only sections of application code that run in privileged mode are
Interrupt Service Routines (ISRs). In most applications, it is best practice to keep ISRs as short as possible
to maintain real-time responsiveness. On a microcontroller with an MPU, keeping ISRs short also makes the
application more secure as it minimizes time spent in privileged mode. This demo shows an approach to keeping
ISRs short by deferring most of the processing work to unprivileged tasks.
Source Code Organization
The FreeRTOS zip file download contains the source code for all the FreeRTOS ports, and every demo
application. That means it contains many more files than are required to use the FreeRTOS ARMv8-M
Cortex-M33 port. See the Source Code Organization page for information
on the zip file's directory structure.
The project file for this demo has the usual Eclipse project name .project and is located in the
FreeRTOS/Demo/Safe_Interrupts_M33F_NXP_LPC55S69_MCUXpresso/MCUXpresso
directory. The
FreeRTOS ARMv8-M Cortex-M33 port files compiled in this project are in the
FreeRTOS/Source/portable/GCC/ARM_CM33_NTZ/non_secure
directory.
Concept
The application creates an interrupt queue (a standard FreeRTOs Queue) to which all ISRs post requests.
These requests are handled later by an unprivileged interrupt handler task. The interrupt handler task
runs at the highest priority to ensure that interrupt requests are not delayed because of other tasks.
The ISRs unblock the high priority interrupt handler task then return directly to the interrupt handler
task instead of the previously executing task.
The design pattern can be easily extended to mimic interrupt nesting by having additional interrupt
queues and corresponding interrupt handler tasks at different priorities.
In the above example image, the UART interrupt is handled by the low priority interrupt handler and, therefore,
can be interrupted by the GPIO interrupt which is handled by the high priority interrupt handler.
The Demo Application
The project includes two demos:
- GPIO Demo
- UART Demo
GPIO Demo
The GPIO Demo consists of a task which periodically toggles the onboard RGB LED. When the user presses
the USER button on the LPC55S69-EVK, the GPIO interrupt is asserted and the corresponding interrupt handler
posts a request to the interrupt queue. The interrupt handler task handles this request and changes the
color of the LED.
void userButtonPressedHandler( void )
{
UserIrqRequest_t xIrqRequest;
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xIrqRequest.xHandlerFunction = vButtonPressedIRQHandler;
xIrqRequest.ulData = 0; /* Not used. */
xQueueSendFromISR( xUserIrqQueueHandle, &( xIrqRequest ), &( xHigherPriorityTaskWoken ) );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
User Button Pressed ISR
UART Demo
The UART Demo consists of a task which prints a command menu on the serial console and waits for user
input. When the user provides input on the serial console, the UART Rx interrupt is asserted and the
corresponding interrupt handler posts a request to the interrupt queue. The interrupt handler task handles
this request and posts the results for the requested command to the serial console.
void uartRxInterruptHandler( void )
{
UserIrqRequest_t xIrqRequest;
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xIrqRequest.xHandlerFunction = vUartDataReceivedIRQHandler;
xIrqRequest.ulData = ( uint32_t ) USART_ReadByte( USART0 );
xQueueSendFromISR( xUserIrqQueueHandle, &( xIrqRequest ), &( xHigherPriorityTaskWoken ) );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
UART Rx ISR
Building and Running the RTOS Demo Application
Launch the MCUXpresso IDE. Note that you need the MCUXpresso IDE version 10.3.1 or higher to be able to
build and run this demo.
Choose the workspace directory and click "Launch".
Open the Import Project dialog by clicking "File -> Import...".
Select "General -> Existing Projects into Workspace" and click "Next".
Click "Browse..." next to "Select root directory" and select the
FreeRTOS/Demo/Safe_Interrupts_M33F_NXP_LPC55S69_MCUXpresso
directory. A project named
FreeRTOSDemo should be visible in the Projects pane as shown below. Click "Finish".
Build the project by right-clicking on FreeRTOSDemo and selecting "Build Project".
Power up the board using the "Debug Link (P6)" micro USB port.
Select the project by clicking "FreeRTOSDemo". Go to "Debug your project"
in the Quickstart Panel and click on "Program flash action using LinkServer" in the dropdown
as shown below.
LPC-LINK2 probe should be shown in the "Probes Discovered" window. Click
"OK".
SWD Device 0 should be selected in the "SWD Configuration" window. Click
"OK".
You should see "Finished writing Flash successfully" in the logs. Click "OK".
Go to "Debug your project" in the Quickstart Panel and click "Debug using
LinkServer probes" in the dropdown as shown below to start the debug session.
RTOS Configuration and Usage Details
Also see the page that describes running
FreeRTOS on ARMv8-M cores, and the page that describes setting ARM
Cortex-M interrupt priorities for use with FreeRTOS.
- Configuration items specific to this demo are contained in
FreeRTOS/Demo/Safe_Interrupts_M33F_NXP_LPC55S69_MCUXpresso/Projects/MCUXpresso/Config/FreeRTOSConfig.h
.
The constants defined in that file can be edited to suit your application. The following configuration options
are specific to the ARM Cortex-M33 port:
configENABLE_MPU
- Enable/Disable Memory Protection Unit (MPU).
configENABLE_FPU
- Enable/Disable Floating Point Unit (FPU).
configENABLE_TRUSTZONE
- Enable/Disable TrustZone.
- This demo runs FreeRTOS on the secure side, and therefore, sets
configENABLE_TRUSTZONE
to 0 and configRUN_FREERTOS_SECURE_ONLY
to 1 in the FreeRTOSConfig.h
file. It uses
the FreeRTOS port files in the FreeRTOS/Source/portable/GCC/ARM_CM33_NTZ
directory.
Source/Portable/MemMang/heap_4.c
is included in the 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.
vPortEndScheduler()
has not been implemented.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.