How to create and run the first FreeRTOS application on the VisionSOM-RT
From SomLabs Wiki
How to create and run the first FreeRTOS application on the VisionSOM-RT
This article describes how to create and run first FreeRTOS application on the VisionSOM-RT module with the NXP i.MX RT1052 microcontroller. The application will be executed from the external QSPI Flash memory.
Contents
Requirements
Hardware
- VisionSOM-RT module (https://somlabs.com/product/visionsom-rt-sls12rx/)
- VisionCB-RT-STD Carrier Board (https://somlabs.com/product/visioncb-rt-std/)
- Segger J-Link interface (https://www.segger.com/products/debug-probes/j-link/)
Software
- MCUXpresso IDE – this tutorial was prepared for the version 10.3.0
- Drivers for FTDI – may be required for the Windows systems
- Any terminal application, for example Termite
- The MCUXpresso comes with the SEGGER drivers, however on some systems a driver update may be required: https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack
- SDK – the SDK needs to be generated for the i.MX RT1052 microcontroller and should contain the FreeRTOS system. More information: https://mcuxpresso.nxp.com/en/welcome
Importing the SDK
The created SDK needs to be imported to the MCUXpresso IDE. We can do it by selecting the import archive option in the Installed SDKs window, or by simple drag-and drop the archive file to this window.
Generating a new project
The MCUXpresso contains a project creator tool that allows to configure a new project with the software componenst available in the imported SDKs. The project creator is available in the File menu (File→New→Project…).
The project appropriate type is the New C/C++ Project.
Next, a target microcontroller should be selected.
In the next window we can set the name of the project, select the device package and the required software components and drivers. The project requires the FreeRTOS system and the following drivers:
- clock
- common
- gpio
- iomuxc
- lpuart
- xip-board
- xip-device
In the next window we can configure the C library and the compiler options. This window also contains the available memories, so we need to define the Flash memory (Location 0x60000000, Size 0x1000000, Driver MIMXRT1050_SFDP_QSPI.cfx). The remaining parameters in this window may be configured with their default values.
After this step the project files should be created, but before we can compile it two more steps are required for proper QSPI Flash configuration. First of all we need to update the sources in the xip directory in order to support the QSPI flash. The updated version for this memory can be found on the NXP Community site in the QSPI_xip.zip archive.
The blog post:
The direct link to the archive:
https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/blog/355/4/QSPI_xip.zip
We can simply remove all sources from the xip directory and put there the ones from the QSPI_xip.zip archive.
After that we also need to set the BOARD_FLASH_SIZE symbol, that is required in the xip/fsl_flexspi_nor_boot.h file. This symbol is already defined in the board/board.h file. It should be set according to the QSPI Flash size, which in our case is 0x1000000 (16MB).
#define BOARD_FLASH_SIZE (0x1000000)
Now we are able to build the project using the Build tool.
Configuring SEGGER tools
By default the installed SEGGER drivers support the external HyperFlash memories. In order to program the on-board QSPI Flash, the configuration files should be modified. The changes should be done in the JlinkDevices.xml file which can be found in the directories:
/opt/SEGGER/Jlink (Linux hosts)
C:\Program Files (x86)\SEGGER\JLink_V640 (Windows hosts – the driver version may be different)
In this file there is a section with the NXP iMXRT105x microcontroller family configuration, where each of the entries has a Loader value:
Devices/NXP/iMXRT105x/NXP_iMXRT105x_HyperFlash.elf
This value needs to be changed to:
Devices/NXP/iMXRT105x/NXP_iMXRT105x_QSPI.elf
The detailed information can be found on the SEGGER wiki page for the iMXRT1050 microcontrollers:
https://wiki.segger.com/I.MXRT1050
Running the example code
Now we have everything that is required to program the QSPI Flash memory and run the example. In order to do this we need to select the Debug using SEGGER J-Link probes option from the J-Link menu and choose the detected debug probe.
After the programming is done we will see the debug view of the MCUXpresso IDE.
Configuring the GPIO
In our example we will use the blue LED (IO10) connected to the GPIO1_IO08 (GPIO_AD_B0_08) pin. We will configure it using the Pins configuration tool.
In the configurator window we can select the proper pin and configure it as the GPIO output with Pull-down. We also need to create a label for it. In this example we will call it LED.
When the configuration is done, we need to generate the source code using the Update project option.
After clicking OK, the source code for GPIO configuration will be generated in the board directory in or project.
We can do the same with the clock configuration, by opening the clock configuration tool and enabling 24MHz crystal input. This way we will create a default configuration for all clocks in the microcontroller. The Update project option will generate the source code in the board directory.
Configuring the LPUART
For the example we also need the LPUART port to communicate with the PC. On the VisionCB-RT-STD Carrier Board two microcontroller pins are connected to the FTDI USB-UART interface – GPIO_AD_B0_12 (LPUART1_TX) and GPIO_AD_B0_13 (LPUART1_RX). We can configure them using the pin configuration tool.
We will also change the UART_CLK_ROOT clock frequency from 4MHz to 24MHz by changing its clock source to the OSC_CLK (external crystal oscillator). It will guarantee more accuracy during bit clock generation.
Now we need to configure the LPUART1 peripheral. Again we can do it using the configuration tool for peripherals.
In the configurator window we can select the configured peripherals and change their configuration. In the example we will use the default settings of the serial port (baud rate 115200, 8 data bits, 1 stop bit, no parity). The update option will generate the source code for us.
FreeRTOS example
Now, when we have prepared the project and created all configurations, we can write a simple FreeRTOS example with two tasks: one for blinking LED and the second one for writing a string to the serial port. The source code of the example looks as follows:
#include <stdio.h> #include "board.h" #include "peripherals.h" #include "pin_mux.h" #include "clock_config.h" #include "MIMXRT1052.h" #include "fsl_gpio.h" #include "fsl_lpuart.h" #include "FreeRTOS.h" #include "task.h" TaskHandle_t ledTaskHandle; TaskHandle_t uartTaskHandle; void ledTask(void* param) { const TickType_t delayMs = 1000 / portTICK_PERIOD_MS; while(1) { GPIO_PinWrite(GPIO1, 8, 1); vTaskDelay(delayMs); GPIO_PinWrite(GPIO1, 8, 0); vTaskDelay(delayMs); } } void uartTask(void* param) { const TickType_t delayMs = 1000 / portTICK_PERIOD_MS; char text[32] = {0}; uint8_t i = 0; while(1) { sprintf(text, "HELLO TASK %d\r\n", i++); LPUART_WriteBlocking(LPUART1, (uint8_t*)text, strlen(text)); vTaskDelay(delayMs); } } void main(void) { BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitBootPeripherals(); xTaskCreate(ledTask, "LED_TASK", 128, NULL, 1, &ledTaskHandle); xTaskCreate(uartTask, "UART_TASK", 128, NULL, 1, &uartTaskHandle); vTaskStartScheduler(); }
It can be copied directly to the main.c file in the project.
Importing project
The configured project can be also imported directly to the MCUXpresso IDE. The project archive can be downloaded from this website and imported from the File→Import… menu.
In the import wizard we need to choose General→Existing Projects into Workspace.
Then in the next window we can choose the Select archive file option and browse to the downloaded zip archive.
After clicking Finish button the project sources will be copied to the active workspace. The SDK needs to be imported separately in order to compile and run the example.