1 Introduction
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
2.1 Reference Materials
-
2022 RT-Thread Global Developer Conference Report Video
2.2 Creating and Importing Projects
rt-thread\bsp\stm32\stm32l475-atk-pandora
. You can name the project whatever you like, for exampleSTM32
: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:
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.
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?
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)
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).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:
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
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)
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 --->
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
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:
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:
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:
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
For the complete list, please check GitHub
END
Love me, just give me a thumbs up
Click “Read the Original Text” to enter this project
Leave a Comment
Your email address will not be published. Required fields are marked *