Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

The “APM32 Core” series summarizes user experiences with APM32 series products, all of which are reprinted from the 21ic forum’s Extreme Sea Semiconductor area. The full text has not been modified in any way and is prohibited from being reprinted without the original author’s authorization.

Introduction

Recently, I have been working with the APM32F407IG board and found that the official provided two RTOS demos, FreeRTOS and RT-thread. I thought, given the rich resources of APM32F4, could it also run ThreadX RTOS? So I decided to give it a try, and this article documents the process of porting ThreadX RTOS on APM32F4 for your reference.

1 Introduction to ThreadX

When it comes to RTOS, many may think of FreeRTOS and our domestic RT-Thread, both of which are well-known due to their commercial-free nature and rich components. However, ThreadX RTOS might be relatively lesser-known, yet in some industries, it is quite renowned because it has been used in space applications. Below is a brief introduction to ThreadX.

ThreadX, officially known as Azure RTOS ThreadX (here is its official website: https://learn.microsoft.com/en-us/azure/rtos/threadx/). It is specifically designed for deeply embedded real-time IoT applications. Azure RTOS ThreadX offers advanced scheduling, communication, synchronization, timers, memory management, and interrupt management capabilities. Additionally, Azure RTOS ThreadX includes many advanced features, such as a picokernel™ architecture, preemption-threshold™ scheduling, event-chaining™, execution analysis, performance metrics, and system event tracing. Azure RTOS ThreadX is very easy to use and is suitable for extremely demanding embedded applications. It has been deployed billions of times across various products, including consumer devices, medical electronics, and industrial control devices. (Excerpted from its official website)

So why is it considered powerful? The above content is just an introduction to its applications; the real strength of this RTOS lies in its various safety certifications. Below are the safety certifications it has passed:

1. Medical – FDA510(k), IEC-62304 Class C, IEC-60601, ISO-14971

2. Industrial – UL-1998, IEC-61508 SIL 4

3. Transport/Railway – EN50128 SIL 4, BS50128, 49CFR236, IEC-61508

4. Aerospace – DO-178B, ED-12B, DO-278

5. Automotive – IEC-61508 ASIL D

6. Nuclear applications – IEC-61508

7. Home appliances – UL/IEC 60730/60335

In fact, it was previously a paid closed-source software. After being acquired by Microsoft, it was made open-source, and for educational assessment purposes, we are not restricted. The strength of this RTOS can be verified on their official website; I won’t elaborate further here.

2 Obtaining the Source Code

Before porting, we need to prepare some source code:

1. The project template for APM32F407, which can be obtained from their official website: https://geehy.com/support/apm32?id=311

2. ThreadX source code, which can be obtained from their open-source repository: https://github.com/azure-rtos/threadx

It should be noted that since we are using the MDK environment, we need to use MDK version 5.30 or above.

3 File Movement and Copying

After preparing the two source codes, we need to perform some file movement and copying to complete the preliminary preparation for our project creation.

1. Copy the ThreadX source code to the APM32F4xx_SDK\Middlewares folder for subsequent project file usage.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

2. Then create a copy of the \Examples\SysTick example and rename it to “ThreadX_Template”. This will serve as our base template, and we will build the APM32F4 ThreadX demo on this template.

3. Copy the “\ports\cortex_m4\ac5\example_build\tx_initialize_low_level.s” file from the ThreadX source code to our example source directory “ThreadX_Template\ThreadX_Template\Source” and rename it to “tx_initialize_low_level_ac5.s” because we will modify this file later. Here, we create a copy for subsequent modifications.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

4 Adding Source Code

Here, we choose to add the corresponding source files to the MDK project of the ThreadX_Template we just copied. Open the MDK project, and under the existing directory, add the “ThreadX/ports” and “ThreadX/common” structures, and we add the corresponding source files.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

4.1 ThreadX/port Structure

In this structure, we add the .s files used by the AC5 compiler.

1. All .s files under “threadx-6.2.0_rel\ports\cortex_m4\ac5\src”.

2. Add the “tx_initialize_low_level_ac5.s” file we just copied.

The final added files are as follows:

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

4.2 ThreadX/common Structure

In this structure, we add the core files of ThreadX, i.e., the .c files under “threadx-6.2.0_rel\common\src”.

4.3 Application Structure

In the original Application structure, we add the thread file we will create shortly: tx_application_entry.c. We will modify this file’s content later.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

5 Tab Settings

5.1 Compiler Settings

Since we are using the AC5 related support files, we choose to use the AC5 compiler and check “Use MicroLIB” to use printf.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

5.2 C/C++ Tab

In the settings under the “C/C++” tab, add the header file paths in the header file settings.

1. “..\..\..\..\..\Middlewares\threadx-6.2.0_rel\ports\cortex_m4\ac5\inc”

2. “..\..\..\..\..\Middlewares\threadx-6.2.0_rel\common\inc”

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

5.3 Assembly Header File Inclusion

In the settings under the “Asm” tab, the following settings need to be completed:

1. Add the header file path in the header file settings: “..\..\..\..\..\Middlewares\threadx-6.2.0_rel\ports\cortex_m4\ac5\inc”.

2. Fill in “–cpreproc” in the Misc Controls column to resolve compilation errors for the .s files.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

6 Modify Source Files

Since ThreadX needs to take over some interrupts, and we need to create some threads using ThreadX, we need to edit the source code in our project.

6.1 tx_initialize_low_level_ac5.s

This file is used by ThreadX RTOS to complete the low-level initialization of the processor, including:

1. Setting the interrupt vector table

2. Setting the locator (Systick) for generating clock ticks

3. Saving the system stack pointer for use by the interrupt program

4. Finding the first available address in RAM to pass to the tx_application_define function, which is the value of the first_unused_memory pointer

5. Since version 6 of ThreadX and later, this file takes over the original processor startup file.

For my case, I still want to use the original processor startup file “startup_apm32f40x.s”, so I need to make some modifications to the “tx_initialize_low_level_ac5.s” file.

1. Comment out the unused labels and manually add the _Vectors and __initial_sp labels, which correspond to the interrupt vector table and stack pointer initial value exported from the APM32F4 startup file:

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

2. Set the clock frequency (168Mhz) and clock tick (1ms), which will be used to initialize the Systick timer:

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

3. Comment out the stack setting code (the stack environment has already been set in the APM32 startup file):

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

4. Comment out the interrupt vector table defined by ThreadX (use the vector table defined in the APM32F4 startup file):

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

5. Comment out the reset handler defined by ThreadX (use the reset handler in the APM32F4 startup file):

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

6. Modify the ThreadX low-level initialization function:

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

7. Comment out the unused functions:

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

After completing the above operations, we have modified the tx_initialize_low_level_ac5.s file.

6.2 apm32f4xx_int.c

Since ThreadX takes over some interrupts, some interrupts in apm32f4xx_int.c must be masked (or deleted) to avoid duplicate definition errors from the compiler.

Specifically, mask the PendSV_Handler and SysTick_Handler functions.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

6.3 tx_application_entry.c

In this file, we create two threads and run them, which requires knowledge of ThreadX. I won’t elaborate further; here is the source code directly.

————————————————————

#include <stdio.h>

#include “Board.h”

#include “tx_api.h”

#include “main.h”

#define TX_APPLICATION1_PRIO 3

#define TX_APPLICATION1_STACK_SIZE 1024

static TX_THREAD tx_application1;

uint8_t tx_application1_stack[TX_APPLICATION1_STACK_SIZE];

#define TX_APPLICATION2_PRIO 2

#define TX_APPLICATION2_STACK_SIZE 1024

static TX_THREAD tx_application2;

uint8_t tx_application2_stack[TX_APPLICATION2_STACK_SIZE];

void my_tx_application1_entry(ULONG thread_input)

{

/* Enter into a forever loop. */

while(1)

{

printf(“ThreadX 1 application running…\r\n”);

APM_MINI_LEDToggle(LED2);

/* Sleep for 1500 ticks. */

tx_thread_sleep(1500);

}

}

void my_tx_application2_entry(ULONG thread_input)

{

/* Enter into a forever loop. */

while(1)

{

printf(“ThreadX 2 application running…\r\n”);

APM_MINI_LEDToggle(LED3);

/* Sleep for 1000 ticks. */

tx_thread_sleep(1000);

}

}

void tx_application_define(void *first_unused_memory)

{

/* Create thread */

tx_thread_create(&tx_application1, “thread 1”, my_tx_application1_entry, 0, &tx_application1_stack[0], TX_APPLICATION1_STACK_SIZE, TX_APPLICATION1_PRIO, TX_APPLICATION1_PRIO, TX_NO_TIME_SLICE, TX_AUTO_START);

tx_thread_create(&tx_application2, “thread 2”, my_tx_application2_entry, 0, &tx_application2_stack[0], TX_APPLICATION2_STACK_SIZE, TX_APPLICATION2_PRIO, TX_APPLICATION2_PRIO, TX_NO_TIME_SLICE, TX_AUTO_START);

}

————————————————————

6.4 main.cWe need to initialize the corresponding peripherals (LED, USART) in the main function before starting ThreadX. Since printf is used in tx_application_entry.c, we also need to redirect printf. Additionally, we will remove some operations from the previous SysTick project; I won’t elaborate further; here is the source code directly.

————————————————————

/* Includes */

#include “main.h”

#include “Board.h”

#include <stdio.h>

#include “tx_api.h”

/** @addtogroup Examples

@{

*/

/** @addtogroup SysTick_TimeBase

@{

*/

/** @addtogroup SysTick_TimeBase_Macros Macros

@{

*/

/** printf using USART1 */

#define DEBUG_USART USART1

/**@} end of group SysTick_TimeBase_Macros*/

/** @defgroup SysTick_TimeBase_Functions Functions

@{

*/

/*!

* [url=home.php?mod=space&uid=247401]@brief[/url] Main program

*

* @param None

*

* @retval None

*/

int main(void)

{

USART_Config_T usartConfigStruct;

usartConfigStruct.baudRate = 115200;

usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;

usartConfigStruct.mode = USART_MODE_TX;

usartConfigStruct.parity = USART_PARITY_NONE;

usartConfigStruct.stopBits = USART_STOP_BIT_1;

usartConfigStruct.wordLength = USART_WORD_LEN_8B;

APM_MINI_COMInit(COM1, &usartConfigStruct);

APM_MINI_LEDInit(LED2);

APM_MINI_LEDInit(LED3);

printf(“ThreadX RTOS on APM32F407 IG MINI Board\r\n”);

tx_kernel_enter();

while (1)

{

}

}

/*!

* [url=home.php?mod=space&uid=247401]@brief[/url] Redirect C Library function printf to serial port.

* After Redirection, you can use printf function.

*

* @param ch: The characters that need to be sent.

*

* @param *f: pointer to a FILE that can record all information

* needed to control a stream

*

* @retval The characters that need to be sent.

*/

int fputc(int ch, FILE *f)

{

/** send a byte of data to the serial port */

USART_TxData(DEBUG_USART,(uint8_t)ch);

/** wait for the data to be sent */

while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);

return (ch);

}

————————————————————

7 Compilation and Download

Finally, we compile the project, and the compilation results are as follows.

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

Then, after downloading the program to the board, LED2 and LED3 blink, and if connected to the serial port, the following information can be seen:

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

Note: The article’s author has provided the project files in the original post; please visit the original 21ic forum to download if needed.

Original link: https://bbs.21ic.com/icview-3271244-1-1.html

Or click below to read the original article

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide 0756 6299999

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

[email protected]

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

www.geehy.com

Porting Azure RTOS ThreadX on APM32F4: A Comprehensive Guide

Guangdong Province, Zhuhai City, Xiangzhou District, Guangwan Street No. 83, Building 01

Leave a Comment

×