Nordic-RT-Thread 5.1.0 Porting Notes
Ghost_Girls contribute this tutorial from the RT-Thread Community.
Keywords: RT-Thread, v17.1.0, SoftDevice, BLE, HID, mouse, Nordic, 52840
Resources:
- nRF5x SDK v17.1.0: GitHub Link
- RT-Thread V5.1.0: GitHub Link
- ZJ-SDK-RT-Thread-nRF52840: GitHub Link
Preparing the Environment
Using the RT-Thread env
tool requires some setup. You must configure it so that the "ConEmu Here" option appears when right-clicking.
After launching env
for the first time, avoid moving the directory, as this can cause issues with executing env
commands. If any errors occur, simply delete the env
folder, extract it again, and restart the tool.
Porting Preparation
- Extract the nRF5x SDK v17.1.0 for later use as the project’s main framework.
- Extract RT-Thread V5.1.0.
From the root directory of RT-Thread (rt-thread-5.1.0), save the relevant RT-Thread folders for use later.
- Extract the
rt-thread-5.1.0\bsp\nrf5x\libraries\drivers
folder for later use, and add it to the project as needed.
- Extract the
rt-thread-5.1.0\bsp\nrf5x\nrf52840\board
folder for later use. - Extract the
rt-thread-5.1.0\bsp\nrf5x\nrf52840\applications
folder for later use.
3. Extract the ZJ-SDK-RT-Thread-nRF52840 archive.
- From the path
ZJ-SDK-RT-Thread-NORDIC-master\ZJ_Application_NRF52840\018.ble_nus\NORDIC_SDK\components\libraries\timer
, save the two files for later use.
Since the current version of RT-Thread doesn’t support restarting a timer within its callback function, directly calling app_button.c
from app_timer_rtthread.c
can cause a bug. To solve this timer "nesting" issue, you’ll need to tweak app_button.c
a bit.
Porting to Keil MDK
To integrate the RT-Thread source code and libraries into your nRF5X SDK project:
- Open the
ble_app_hids_mouse_pca10056_s140.uvprojx
project. - In the project explorer, go ahead and create four new folders. You can name them:
2. Add the RT-Thread source files to the project, and make sure to include the header file paths.
3. For the files in the RTT_Kernel folder, make sure to right-click and add the define __RT_KERNEL_SOURCE__
to the configuration. Without this, the files may fail to compile due to errors.
4. Similarly, for the files in the RTT_components folder, right-click and add the define __RT_IPC_SOURCE__
to the configuration to avoid compilation errors.
5. In the nRF_Libraries folder, add the file app_timer_rtthread.c
and remove or exclude app_timer2.c
and drv_rtc.c
to prevent conflicts.
You must replace app_timer.h
, otherwise, the project will fail to compile.
6. Press ALT + F7 to open the project settings. Remove the configurations for APP_TIMER_V2
and APP_TIMER_V2_RTC1_ENABLED
, and add __RTTHREAD__
and RTTHREAD_ENABLED
.
Before Changes:
After Changes:
7. In rtconfig.h
, add the macro definition #define RT_TIMER_TICK_PER_SECOND RT_TICK_PER_SECOND
, otherwise, app_timer_rtthread.c
will generate errors.
8. In the project manager, create a Drivers folder and add the necessary source and header files.
These files can be found in:
These files can be found in:
rt-thread-5.1.0\bsp\nrf5x\nrf52840\board
rt-thread-5.1.0\bsp\nrf5x\libraries\drivers
9. In the Application folder, add application.c
and remove or exclude main.c
to avoid conflicts.
ble_app_hids_mouse.c
serves as the modified version of main.c
. After copying it into the folder, add it to the Application folder. The following modifications need to be made:
Rename main.c
to ble_app_hids_mouse.c
and modify the main()
function to the following content:
10. Summary of Header File Load Paths:
If there are no compilation errors, you can proceed to compile and flash the program. At this point, RT-Thread should start normally. If you see printed output, it indicates that you can move on to the next step.
Debugging Error Handling
- If BLE is not enabled, there are no errors and the LED flashes. However, enabling BLE may result in a RAM error.
The printed error NRF_ERROR_NO_MEM
indicates a memory-related issue. Based on the context, it suggests that the allocated memory might be too small, and you may need to adjust the memory allocation position slightly.
RAM Modification: Change START 0x20002260
to START 0x20002270
. The size does not need to be modified.
Before Changes:
After Changes:
2. After starting BLE, the LED flashes for a short period and then stops when a connection is made from the PC. It appears that some mechanism hasn’t been initialized properly, leading to a halt. This could be related to event management, such as the NRF_SDH_DISPATCH_MODEL
, which may not be executing correctly.
Why is it halting?
- It seems that NRF_SDH_DISPATCH_MODEL
is not configured properly.
This is likely the issue, but since it’s a three-option choice, it’s uncertain which one will work.
- Has it entered sleep mode? Is it “sleeping dead”?
Bluetooth has stopped advertising, but theoretically, this shouldn’t cause the RTOS to stop functioning. I commented out the code that puts the system into sleep mode, but the issue persists, so it’s likely not a sleep-related problem.
Upon observation, the flashing lasts for about 30 seconds, and the log indicates “Fast advertising.” After that, there are no further logs for “Slow advertising.”
Based on the code analysis, it appears that the service switch has failed. This likely indicates an issue with event-related content in the SoftDevice, specifically concerning the NRF_SDH_DISPATCH_MODEL
. A useful reference article for this can be found in the FreeRTOS porting documentation:
FreeRTOS Porting Guide for 52832 with SoftDevice
Link to Article
“In the sdk_config.h
file, set NRF_SDH_DISPATCH_MODEL
to 2. This configuration modifies the way SoftDevice handles events at the application layer, where mode 2 indicates that the application actively retrieves events. In FreeRTOS, this active retrieval is implemented in the nrf_sdh_freertos.c
file we added earlier. If using mode 0, the interrupt method notifies the application layer, and nrf_sdh_freertos.c
is not needed. However, during my testing, I encountered Bluetooth disconnection issues."
Why can FreeRTOS use NRF_SDH_DISPATCH_MODEL
?
This is because the provided porting API from the official source includes relevant code that employs a polling method.
You can create a task and use a while()
loop within the task to continuously retrieve events. The relevant code is as follows:
I consulted with other engineers, and they suggested that NRF_SDH_DISPATCH_MODEL
should be set to 2 for RTOS. However, I still felt something was off. It seemed to me that event retrieval should be related to the code rather than the system's presence or absence.
By chance, I changed the value of NRF_SDH_DISPATCH_MODEL
from 2 to 0, which resolved the freeze issue, confirming that it has no relation to the system's state:
- 0: Interrupt mode (RT-Thread)
- 1: App scheduler (nRF5X SDK Demo)
- 2: Polling mode (FreeRTOS)
Which is better between interrupt mode and polling mode? It’s hard to say.
Importing MDK Project into Visual Studio + VisualGDB
It’s best to first set up a functioning project in KEIL MDK before importing it into VisualGDB. Whether the code runs first or you run first is hard to determine.
Creating a VisualGDB Project (ARMCC)
- I took the easy route and didn’t want to add files one by one; instead, I directly imported the Keil MDK project into VisualGDB.
Click on Create New Project.
- Select【Embedded Project Wizard】
- Fill in the fields for Project Name, Solution Name, and Solution Creation Path.
For the solution (VisualGDB) -> Project (ble_app_hids_mouse_pca10056_s140), select the Project Type, Compiler Type, and Project Path.
- Select the MCU option; this interface is already configured, so simply click Next.
- Next, configure the DEBUG settings. Here, choose J-Link, USB, SWD, Before Programming, and After Programming, then click Next to proceed to the next page.
- On the path mapping interface, if you’re unsure about it, just click Finish to complete the configuration.
Complete the Project Configuration (Add Any Missing Settings)
- Open the Solution Explorer on the left side, locate the filter labeled ::Device, and add the two files shown in the image to the filter.
The Keil project also included these two files, but they were lost during the project import.
2. After completing the above steps, there may still be some files that have not been imported. If the top right corner indicates that there are files not included, simply click to confirm inclusion.
3. Locate the files main.c
, app_timer2.c
, drv_rtc.c
, nrf_sdh_ble_rtt.c
, and ble_conn_params_rtt.c
. Right-click each file, go to Properties -> Keil Settings -> Excluded From Build, and set it to Yes.
4. Right-click on ble_app_hids_mouse_pca10056_s140 to open the context menu, then select Properties to enter the project configuration interface.
5. Project configuration for ble_app_hids_mouse_pca10056_s140:
- Configure Application Binary Interface:
Keil Settings -> Floating-point ABI: Hardware FP (-mfloat-abi=hard) - Configure Floating Point Unit Type:
Keil Settings -> Floating-point Unit Type: fpv4-sp-d16 (-mfpu=fpv4-sp-d16) - Configure ARM CPU Type:
Keil Settings -> ARM CPU Type: -mcpu=arm7m - Configure ARMCC CPU Type:
Keil Settings -> CPU Type for ARMCC/ARMASM: Cortex-M4.fp.sp (-cpu=Cortex-M4.fp.sp) - Add Preprocessor Definitions:
C/C++ -> Preprocessor -> Preprocessor Definitions:__RTTHREAD__;RTTHREAD_ENABLED;BOARD_PCA10056;BOARD_PCA10059;NRF52840_XXAA;CONFIG_GPIO_AS_PINRESET;FLOAT_ABI_HARD;NRF_SD_BLE_API_VERSION=7;S140;SOFTDEVICE_PRESENT;__HEAP_SIZE=8192;__STACK_SIZE=8192;
Note: Keil MDK uses commas (",") and spaces (" ") to separate macros, while VisualGDB only allows semicolons (";"). After entering the editing interface, you can press Enter to create a new line, and exiting the editing will automatically convert it to semicolons. - Configure C/C++ Language Standard:
C/C++ -> Advanced -> Language Standard for C++ Files: C99 (-c99) - Configure GNU Extensions:
C/C++ -> Advanced -> Enable GNU Language Extensions: No - Configure ROM and RAM Mapping:
Linker -> Memory Layout -> Scatter Files:..\examples\ble_peripheral\ble_app_hids_mouse\pca10056\s140\visualgdb\ble_app_hids_mouse_pca10056_s140\nrf52840_xxaa.sct
If you import directly as GCC from the start, you can obtain the template from RT-Thread:rt-thread-5.1.0\bsp\nrf5x\libraries\templates\nrfx\board\linker_scripts
Simple modifications to link.sct:
- Simple Modifications to link.lds:
- Currently, we are using ARMCC. When using GCC, memory-related print statements must reflect the starting address based on the compiler.
- At this point, the compilation should be successful, although you may encounter several warnings — this is usually not a problem.
- Important: Once the import is successful, avoid switching back to Keil MDK for editing. Doing so could trigger change detection when you restart VisualGDB.