Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

1 Introduction

RTduino is an Arduino ecosystem compatibility layer for RT-Thread, initiated by the core developers of the RT-Thread community. Its aim is to make the RT-Thread community’s software package ecosystem richer and lower the learning threshold for the RT-Thread operating system and the chips compatible with it. Users can easily use RT-Thread and specific chips through Arduino functions and programming methods. They can also directly use libraries from the Arduino community (such as I2C sensor drivers, algorithm libraries, etc.) in RT-Thread projects, greatly enhancing the RT-Thread community ecosystem. The project is maintained by the core developer of the RT-Thread community, Man Jian Ting.
This package can run in the RT-Thread Studio IDE and Keil compilation environment. Since Arduino libraries are developed based on the GCC environment, it is highly recommended to use the RT-Thread Studio IDE.

1.1 Supported RT-Thread BSPs for Arduino Ecosystem Compatibility Layer

BSP Name Remarks
STM32L475 Pandora Heterogeneous pin layout, but rich peripherals
STM32F072 Nucleo Standard Arduino UNO pin layout
STM32F401 Nucleo Standard Arduino UNO pin layout
STM32F469 Discovery Standard Arduino UNO pin layout
STM32F103 BluePill Heterogeneous pin layout
ES32F3696 Heterogeneous pin layout

Note: RTduino can also run directly on any RT-Thread BSP without specific adaptation. Please refer to Chapter 5 – RTduino Simplified Mode.

2 How to Use This Compatibility Layer

This package requires adaptation to a specific BSP before it can be used. The adaptation method is straightforward. This section uses the STM32L475 Pandora development board and RT-Studio development environment as an example to explain how to use this compatibility layer.

2.1 Reference Materials

  • 2022 RT-Thread Global Developer Conference Report Video

2.2 Creating and Importing Projects

Please go to the RT-Thread official repository on GitHub to download the latest source code. For some users experiencing slow downloads from GitHub, you can search for keywords like “GitHub acceleration” on Baidu or Bilibili to solve this issue.

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

After downloading, please unzip it, open RT-Studio IDE, select File -> Import, and choose RT-Thread BSP Project into Workspace to import the BSP project into Studio.

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Path selection: you just downloaded and unzipped the RT-Thread source code. Taking the STM32L475 Pandora board as an example:rt-thread\bsp\stm32\stm32l475-atk-pandora. You can name the project whatever you like, for exampleSTM32:

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Click Finish, and after a moment, the project import will be completed.

After successful import, double-click RT-Thread Settings to enter the RT-Thread project configuration interface. Click the << button to enter the detailed configuration page:

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Click Hardware, select Support Arduino, just click once, and other dependencies will be handled automatically. Then click the hammer button to compile. RT-Thread Studio will automatically save your current configuration, download the RTduino software package along with the dependency packages, and compile the entire project automatically.

In summary, you only need to select Support Arduino and click the hammer button, then wait for the compilation to succeed.

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Thus, the RTduino software package installation is complete, and this BSP project is now capable of being compatible with the Arduino ecosystem.

2.3 RTduino Folder Directory Structure

RTduino software package contains two main folders: core and libraries.

  • The core folder mainly provides all built-in API functions of Arduino, such as analogWrite, analogRead functions, etc. Detailed introductions to these functions can be found on the official Arduino website.

  • The libraries folder is where the Arduino libraries are located. Among them:

  • The buildin folder contains some built-in libraries of Arduino, such as the Servo driver library, Wire I2C driver library, etc.;

  • The user folder is the user folder, which is very important for users. It is empty by default, and users can drag the downloaded Arduino libraries into this folder. This operation will be elaborated in the next chapter.

2.4 Where are the classic setup and loop functions of Arduino?

For Arduino, the most classic are the setup and loop functions. These two functions are located in the arduino_main.cpp file in the applications folder under the BSP directory. Taking the Pandora board as an example, these two functions are located in:
bsp/stm32/stm32l475-atk-pandora/applications/arduino_main.cpp file. After enabling the RTduino software package, you can find it directly in the Applications group of the project.

2.5 Let’s blink an LED!

#include <Arduino.h>

void setup(void) {
    // put your setup code here, to run once:
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop(void) {
    // put your main code here, to run repeatedly:
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    Serial.println("Hello Arduino!");
    delay(100);
}

You can see that the onboard LED has started to blink, and the serial port has begun to output.

Note:

Since the main.c file of RT-Thread will also default to blink an LED, if there is only one LED on the board, the two threads will interfere with each other. However, you will find that the blinking speed of this LED has obviously increased. Because the blinking period on the main.c side is 1000ms, while the above example is 200ms.

If you are using the Pandora board, the main.c blinks a red light, while the Arduino program in the RTduino compatibility layer defaults to blinking a green light, so the two will not interfere with each other.

2.6 Specific Arduino Pin Distribution Information

Due to differences in board design and chip models for each BSP, the pin distribution varies. Therefore, you need to check the README.md file under the applications/arduino folder of the specified BSP for detailed information. For example:

Detailed description of the Arduino pin layout for the STM32L475 Pandora board | Detailed description of the Arduino pin layout for the STM32F072 Nucleo board

3 Importing and Using Arduino Libraries

3.1 Terminology Explanation

Software package: Refers to third-party extensions maintained by the RT-Thread community, part of the RT-Thread native ecosystem.

Library: Refers to third-party extensions maintained by the Arduino community, part of the Arduino native ecosystem.

Libraries and software packages are essentially the same, just different terminologies used by the two communities.

3.2 Compatibility of RTduino Compatibility Layer with Arduino Libraries

Currently, the RTduino compatibility layer can achieve 100% compatibility with Arduino pure software libraries (such as algorithm and data processing libraries), serial-related, and I2C sensor-related libraries.

For detailed support information and plans, please refer to:

https://github.com/RTduino/RTduino/discussions/26

3.3 Importing an Arduino Library into RT-Thread Project (Taking Pandora Board as an Example)

First, you need to go to the Arduino official software package classification center to find the library you want, or directly search for the library you want on GitHub, which is generally of C++ type. For example, I want a library to drive the AHT10 temperature and humidity sensor, which can be downloaded here. This section takes the Pandora board as an example, as it has the AHT10 sensor onboard.
After downloading, simply drag the zip file into the libraries\user directory under the RTduino folder. Right-click the current project and select Sync Sconscript to project, which will prompt RT-Studio to rescan and organize the project directory. During the scanning process, RT-Studio will automatically unzip the zip file and add the Arduino library to the RT-Thread project according to the Arduino IDE’s file addition logic (ignoring the examples folder and adding other folders’ .c files and .h paths to the project).
Then click the hammer button to recompile the project.

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

After the project compiles successfully, you can directly copy the example (located in the examples folder of the library) to the arduino_main.cpp file to run it. You will see that the serial port will output the current temperature and humidity, and the Arduino example can run directly on RT-Thread.

3.4 Built-in Libraries of RTduino

RTduino has two types of built-in libraries for users to use directly.

One type is the libraries that are natively built into Arduino, stored in the libraries/buildin folder. The specific libraries are shown in the following table:

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

4 How to Adapt RTduino to a Specific BSP

4.1 Creating Folders and Files

You need to create the following files and folders under the applications folder of a specific BSP:

Reference example BSP: STM32F072 Nucleo board applications folder | STM32L475 Pandora board applications folder

4.1.1 arduino_main.cpp File

This file is the entry point for Arduino programming, providing the setup and loop functions. The loop function defaults to blinking the built-in Arduino LED (LED_BUILTIN) every 200ms. If the BSP supports SPI functionality and follows the UNO pin layout, there may be a conflict between SPI and LED_BUILTIN (D13), so you can replace the blinking LED in the loop function with Serial.println("Hello Arduino\n"); (for example, on the STM32F401 Nucleo board).

4.1.2 arduino_pinout Folder

You need to create the arduino_pinout folder under the applications folder. This folder mainly contains two key files: arduino_pinout.c and arduino_pinout.h, which are crucial for the interface. As long as you complete these two files, you can achieve integration with RTduino.

Additionally, this folder also needs to contain an SConscript script file and a README document that provides the Arduino pin layout. Please refer to the example BSP above to complete the writing of these two files.

4.1.3 Writing the arduino_pinout.c File

arduino_pinout.c needs to contain a mapping table for IO numbers and functions. Since Arduino uses pin numbers 1-13 (D0-D13) and A0-A5, while regular MCU pin numbers are generally PA1 and so on, you need to map the actual MCU pin numbers to the Arduino pin numbers.

The following code snippet illustrates this:

/*
    {Arduino Pin, RT-Thread Pin [, Device Name(PWM or ADC), Channel]}
    [] means optional
    Digital pins must NOT give the device name and channel.
    Analog pins MUST give the device name and channel(ADC, PWM or DAC).
    Arduino Pin must keep in sequence.
*/
/* 按照先数字引脚后模拟引脚的顺序从0开始,一定要按序排列 */
/* 可以按照板卡实际IO情况,灵活调整功能,不一定非得按照Arduino UNO的引脚功能布局,但是建议按此布局设计 */
const pin_map_t pin_map_table[] = {
    {D0}, /* RX */
    {D1}, /* TX */
    {D2, GET_PIN(A,10)},
    {D3, GET_PIN(B,3), "pwm2", 2}, /* PWM */
    {D4, GET_PIN(B,5)},
    {D5, GET_PIN(B,4), "pwm3", 1}, /* PWM */
    {D6, GET_PIN(B,10), "pwm2", 3}, /* PWM */
    {D7, GET_PIN(A,8)},
    {D8, GET_PIN(A,9)},
    {D9, GET_PIN(C,7), "pwm3", 2}, /* PWM */
    {D10, GET_PIN(B,6), "pwm16", 1}, /* PWM */
    {D11, GET_PIN(A,7), "pwm17", 1}, /* PWM */
    {D12, GET_PIN(A,6)},
    {D13, GET_PIN(A,5)},
    {D14}, /* I2C1-SDA */
    {D15}, /* I2C1-SCL */
    {D16, GET_PIN(C,13)}, /* user button */
    {A0, GET_PIN(A,0), "adc1", 0}, /* ADC */
    {A1, GET_PIN(A,1), "adc1", 1}, /* ADC */
    {A2, GET_PIN(A,4), "adc1", 4}, /* ADC */
    {A3, GET_PIN(B,0), "adc1", 8}, /* ADC */
    {A4, GET_PIN(C,1), "adc1", 11}, /* ADC */
    {A5, GET_PIN(C,0), "adc1", 10}, /* ADC */
};

The above snippet shows the IO number and function mapping table, each line enclosed in curly braces (actually a structure) suggests a mapping relationship for an IO:

{Arduino Pin Number, RT-Thread Pin Number (obtained through GET_PIN macro), Device Name for Multiplexing (PWM, ADC or DAC), Channel Number for that Multiplexing Function}

Among them, the Arduino pin number is the first parameter and is required, D0 – Dx or A0 – Ax. Note that you must fill in the order of digital pins first and then analog pins.

The RT-Thread pin number is the second parameter, which should match what you fill in rt_pin_write. Generally, the GET_PIN macro is used to obtain it. Note: D0, D1, and I2C, SPI IO need to skip this parameter.

The last two parameters are only required for multiplexing functions; regular pins can be skipped.

4.1.4 Writing the arduino_pinout.h File

Reference example BSP: STM32L475 Pandora board applications folder

This file mainly defines various macros, including:

Digital macros for pins like D0, A0, etc. These macros must be numbered in order of digital pins first and then analog pins.

Define some hardware features that are enabled by default, as shown in the table below:

/* pins alias. Must keep in sequence */
/* 按照先数字引脚后模拟引脚的顺序从0开始,一定要按序排列 */
/* 可以按照板卡实际IO情况,灵活调整功能,不一定非得按照Arduino UNO的引脚功能布局,但是建议按此布局设计 */
#define D0   (0)
#define D1   (1)
#define D2   (2)
#define D3   (3)
#define D4   (4)
#define D5   (5)
#define D6   (6)
#define D7   (7)
#define D8   (8)
#define D9   (9)
#define D10  (10)
#define D11  (11)
#define D12  (12)
#define D13  (13)
#define D14  (14)
#define D15  (15)
#define D16  (16)
#define D17  (17)
#define D18  (18)
#define D19  (19)
#define D20  (20)
#define D21  (21)
#define D22  (22)
#define D23  (23)
#define D24  (24)
#define D25  (25)
#define D26  (26)
#define D27  (27)
#define D28  (28)
#define D29  (29)
#define D30  (30)
#define D31  (31)
#define D32  (32)
#define A0   (33)
#define A1   (34)
#define A2   (35)
#define A3   (36)
#define DAC0 (37)

#define F_CPU  80000000L /* CPU: 80MHz,定义CPU的主频 */
#define LED_BUILTIN  D22 /* Default Built-in LED,定义Arduino内置LED的引脚编号 */

#define RTDUINO_DEFAULT_IIC_BUS_NAME            "i2c4" /* 定义I2C设备名称 */
#define RTDUINO_DEFAULT_SPI_BUS_NAME            "spi2" /* 定义SPI设备名称 */
#define RTDUINO_DEFAULT_HWTIMER_DEVICE_NAME     "timer7" /* 定义高精度定时器设备名称 */
#define RTDUINO_SERIAL2_DEVICE_NAME             "uart2" /* 如果有串口2、串口3可以定义串口2、3的设备名称 */

4.2 Modifying the Kconfig File

The Kconfig file is located in the board folder of the BSP:

Reference example BSP:

STM32F072 Nucleo board Kconfig | STM32L475 Pandora board Kconfig

menu "Onboard Peripheral Drivers"
    config BSP_USING_STLINK_TO_USART
        bool "Enable STLINK TO USART (uart2)"
        select BSP_USING_UART
        select BSP_USING_UART2
        default y

    #增加 BSP_USING_ARDUINO 配置选项
    config BSP_USING_ARDUINO
        bool "Support Arduino"
        select PKG_USING_RTDUINO
        select BSP_USING_STLINK_TO_USART
        select BSP_USING_GPIO
        select BSP_USING_ADC
        select BSP_USING_ADC1
        select BSP_USING_PWM
        select BSP_USING_PWM2
        select BSP_USING_PWM2_CH2
        select BSP_USING_PWM2_CH3
        select BSP_USING_PWM3
        select BSP_USING_PWM3_CH1
        select BSP_USING_PWM3_CH2
        select BSP_USING_PWM16
        select BSP_USING_PWM16_CH1
        select BSP_USING_PWM17
        select BSP_USING_PWM17_CH1
        select BSP_USING_I2C
        select BSP_USING_I2C1
        imply RTDUINO_USING_SERVO
        imply RTDUINO_USING_WIRE
        imply RTDUINO_USING_ADAFRUIT
        default n

endmenu
You need to add the BSP_USING_ARDUINO configuration option under the Onboard Peripheral Drivers section, depending on the corresponding PWM, ADC, UART, I2C, and SPI device frameworks, to enable one-click activation of RTduino.

4.3 Writing the README Document for Arduino Pin Layout (Pinout)

Examples: Arduino pin layout documentation for STM32F072 Nucleo | Arduino pin layout documentation for STM32L475 Pandora
This document should be located in applications/arduino_pinout/README.md, mainly introducing the Arduino pin numbers and functions under this BSP, as well as precautions.

5 RTduino Simplified Mode (Quick Use, No Specific BSP Adaptation Needed)

5.1 Not Using Setup-Loop Programming Model

setup() and loop() functions are classic functions in Arduino programming. When you create a new file in the Arduino IDE, these two functions are provided by default. RTduino fully supports these two functions (see Chapter 4), but some complex or large business logic may be constrained if placed in setup-loop functions. Therefore, you can disable the setup-loop programming model in Env or RT-Thread Studio’s RT-Thread Settings:
1RT-Thread online packages  --->
2    system packages  --->
3         [*] RTduino: Arduino Ecological Compatibility Layer  --->
4              [*]   Don't use setup-loop structure  --->
Selecting this option allows users to program directly in the core/arduino_thread.c file’s arduino_entry thread function or call Arduino APIs in any .cpp file (not limited to Arduino threads, as long as it’s called in .cpp files).

5.2 How to Use RTduino Without Defining Pin Mapping Table

As we can see, the RTduino software package is not directly usable; it requires support from the RT-Thread BSP, such as the pin mapping table (arduino_pinout), etc. However, if users do not want to use Arduino pin (IO) related APIs (such as analogRead, etc.) and just want to use the RTduino software package to directly run I2C chip driver libraries, pure software algorithm libraries, etc., how can they quickly use it?
Users can directly select Simplified Mode (Enable tiny mode) in Env or RT-Thread Studio’s RT-Thread Settings. By selecting Simplified Mode, users do not need to define the pin mapping table and can directly use non-IO related functions and libraries from the Arduino libraries. Enabling Simplified Mode will automatically turn on the option of not using the setup-loop programming model mentioned in section 5.1, allowing users to use Arduino APIs in any .cpp file.
1RT-Thread online packages  --->
2    system packages  --->
3         [*] RTduino: Arduino Ecological Compatibility Layer  --->
4              -*-   Don't use setup-loop structure
5              [*]   Enable tiny mode  --->

5.3 Regular Mode (See Chapter 4) vs Simplified Mode (See Chapter 5)

The table below lists the compatibility of RTduino with Arduino APIs in two different modes:

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Note: The SPI library is currently under construction and is not available for use.

6 Important Notes

6.1 Including the Arduino.h Header File

Source files that call Arduino-related functions and macros must include the Arduino.h header file; otherwise, errors may occur:

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

6.2 Keil AC5

If using the Keil AC5 environment, you need to check the GNU extension. AC6 does not require this.

6.3 Enabling PWM Cannot Call pinMode Function, Otherwise PWM Will Fail, ADC and DAC Similarly

void setup() {
  //Declaring LED pin as output
  //pinMode(led_pin, OUTPUT); //不能设置为OUTPUT,否则PWM会失效
}
void loop() {
  //Fading the LED
  for(int i=0; i<255; i++){
    analogWrite(led_pin, i);
    delay(5);
  }
  for(int i=255; i>0; i--){
    analogWrite(led_pin, i);
    delay(5);
  }
}

Because the underlying system has set the corresponding PWM, ADC, or DAC IO to analog input or multiplexing push-pull, calling pinMode will change the IO mode to pure input/output, and the original PWM, ADC, or DAC functionality will be lost. This issue has no fix; just be aware that when calling analogRead and analogWrite, you do not need to set pinMode. Once pinMode is called, that pin will lose the functionality of analogWrite or analogRead and can only be used as a regular IO.

Arduino official documentation also suggests this:

You do not need to call pinMode() to set the pin as an output before calling analogWrite().
The analogWrite function has nothing to do with the analog pins or the analogRead function.

If users use the pinMode function on PWM, ADC, or DAC pins, warnings will also be given in the terminal:

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Of course, if users are already aware of the consequences but deliberately need to use the pinMode function to turn PWM, ADC, or DAC pins into regular IO, it is completely permissible.

6.4 Serial.begin

In many Arduino examples, the following statement is often used to initialize the serial port:

Serial.begin(9600);

This statement initializes the serial port to a default baud rate of 9600. However, in RT-Thread, the serial port initialization is actually handled by the RT-Thread driver framework, and the default baud rate is 115200. Therefore, if you call Serial.begin(9600) function, the baud rate of the serial port will be adjusted from the default 115200 to 9600. If your terminal or serial assistant still keeps the baud rate at 115200, the received data will appear garbled.

Therefore, it is recommended:

Use Serial.begin() instead of Serial.begin(9600). The no-parameter method of Serial.begin() is an RTduino extension method, which indicates to follow the RT-Thread serial configuration without reconfiguring the serial port.

7 Contribution and Maintenance

7.1 Project Repository Address

https://github.com/RTduino/RTduino

https://gitee.com/rtduino/RTduino

If you like it, please star it; this is the greatest encouragement for this open-source project. Thank you; if you want to contribute a PR, please fork it.

7.2 Thanks to the following friends for their contributions to this repository

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

For the complete list, please check GitHub

END

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive Guide

Love me, just give me a thumbs upRunning Arduino Libraries on RT-Thread: A Comprehensive Guide

Running Arduino Libraries on RT-Thread: A Comprehensive GuideClick Read the Original Text” to enter this project

Leave a Comment

Your email address will not be published. Required fields are marked *