Programming Arduino in OpenWrt: the manual of STM32 development in WRTnode2R

From WRTnode Wiki
Jump to: navigation, search
This page is a translated version of the page 在OpenWrt中使用Arduino函数:WRTnode2R的STM32开发指南 and the translation is 100% complete.

Other languages:


WRTnode2R Dual-core dual system is the biggest feature of WRTnode2R: MTK7688 + STM32F103T8U6 and their corresponding operating system OpenWrt +RT-Thread
WRTnode2R not only has OpenWrt also introduced MCU mainly consider two points:

  1. Perfect OpenWrt available resources, such as: analog acquisition, capture timer, PWM input, and additional PWM output, and other more GPIO output
  2. Have reliable "hard" real-time capability, we can not know the precise millisecond delay bearer in Linux, and the MCU is just good at this task.Thus,We want to use the OpenWrt brought about by the Linux a wide range of existing software resources and multimedia, artificial intelligence applications capabilities.At the same time, the STM32 core provides a more low-level development capabilities and more reliable physical interaction capabilities, we hope that the combination of the two in the field of robotics applications to provide a wider range of applications.

In OpenWrt system call Arduino function: The STM32 system customization

After the introduction of dual-core dual-system characteristics, STM32 resources and API organized into a new topic.
Based on our experience of the development of Linux+MCU framework, we designed the following framework:
On WRTnode2R mainboard, STM32 and 7688 via SPI bus occupies 7688 of CS1 pin. In WRTnode2R standerd shield on, it leads the STM32 debug JTAG pins, serial, I2C GPIO pins and all other unused. Specific pin layout, please refer to:WRTnode2R pin map and pin map of WRTnode2R standerd shield

Try msh on WRTnode

STM32 running on the real time operating system RT-Thread,Benefit from the RTT in a friendly msh command line debugging components, our factory firmware implemented the RTT spi slave device driver, and the msh input and output ports are mapped to the spi bus.At the same time,We provide the software by 7688 and STM32 SPI bus communication(Including spiS0 device driver, spi-bridge communication software and flash-stm32 firmware upgrade program)
msh command line

  • Login to WRTnode2R.
  • Upgrade stm32

This document describes the latest version of the firmware stm32, it is recommended that you update the firmware stm32

$ flash-stm32

As shown above, stm32 has completed the upgrade and then automatically restart. Use the spi-bridge command to open msh terminal,then press the 'tab' key and the 'enter' key to list all available commands.

  • For example, run the ps command.


  • Use the 'exit' commad exit msh terminal.

You can also execute a single command mode, Format: spi-bridge write [cmd]. if stm32 being executed before the instructions, resulting in the write buffer is full, then this command will block until it can be executed.
spi-bridge read command to read the results of the execution, but blocked until there is data to be read.
Note:As the 7688 chip SPI bus particularity stage temporarily unable to provide the user with a standard user interface SPI CS1, so the user can only communicate temporarily via spi-bridge.

$ spi-bridge write list_timer
$ spi-bridge read

Arduino compatible functions:maple

The STM32 has been ported well Maple firmware library. Maple firmware library provides an interface compatible with Arduino code. Users only need to do a little work you can make a simple code for the Arduino transplant to stm32.
Note:Because the Arduino application engineering are C ++, but rtt system is compiled with c compiler, so the transplant project will need to do a little work. Our existing project has been to all interfaces of maple library adds a layer of c language packages, so that users can directly call in c code, so the user can choose to Arduino application using C language code refactoring, or add a layer of application code C language package for RTT call.

With spi-bridge to control the STM32 IO

The current version already provides command that msh call Maple GPIO library, where we provide a reference routines.
IO control command is relatively simple, similar to the arduino, the current statement can be used include pinMode/digitalRead/digitalWrite/togglePin/analogRead/pmwWrite

extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = {
    PMAP_ROW(GPIOA,   0, TIMER2,  1, ADC1,    0), /* D0/PA0 */
    PMAP_ROW(GPIOA,   1, TIMER2,  2, ADC1,    1), /* D1/PA1 */
    PMAP_ROW(GPIOA,   8, TIMER1,  1, NULL, ADCx), /* D2/PA8 */
    PMAP_ROW(GPIOB,   2,   NULL,  0, NULL, ADCx), /* D3/PB2 */
    PMAP_ROW(GPIOA,   3, TIMER2,  4, ADC1,    3), /* D4/PA3 */
    PMAP_ROW(GPIOB,   0, TIMER3,  3, ADC1,    8), /* D5/PB0 */
    PMAP_ROW(GPIOA,  11, TIMER1,  4, NULL, ADCx), /* D6/PA11 */
    PMAP_ROW(GPIOA,  12,   NULL,  0, NULL, ADCx), /* D7/PA12 */
    PMAP_ROW(GPIOB,   5,   NULL,  0, NULL, ADCx), /* D8/PB5 */
    PMAP_ROW(GPIOA,  10, TIMER1,  3, NULL, ADCx), /* D9/PA10 */
    PMAP_ROW(GPIOA,   9, TIMER1,  2, NULL, ADCx), /* D10/PA9 */
    PMAP_ROW(GPIOB,   6, TIMER4,  1, NULL, ADCx), /* D11/PB6 */
    PMAP_ROW(GPIOB,   7, TIMER4,  2, NULL, ADCx), /* D12/PB7 */
    PMAP_ROW(GPIOB,   1, TIMER3,  4, ADC1,    9), /* D13/PB1 */
    PMAP_ROW(GPIOA,   2, TIMER2,  3, ADC1,    2), /* D14/PA2 */
    PMAP_ROW(GPIOA,   4,   NULL,  0, NULL, ADCx), /* D15/PA4 */
    PMAP_ROW(GPIOA,   5,   NULL,  0, NULL, ADCx), /* D16/PA5 */
    PMAP_ROW(GPIOA,   6,   NULL,  0, NULL, ADCx), /* D17/PA6 */
    PMAP_ROW(GPIOA,   7,   NULL,  0, NULL, ADCx), /* D18/PA7 */
   Note:/* D0/PA0 */ /* D5/PB0 */ and so on,Dxx represents xx pin,Pxx is the corresponding chip pins.

For example,the following operation is the 3-pin (D3), corresponding to the PB2 on the WRTnode2R standerd shield。
As pwm pins 0, 1, 2, 4, 5, 6, 9, 10, 11, 12, 13, 14
As ADC pins 0, 1, 4, 5, 13, 14
D15-D18 pin is used as spi
Complete definition in github website:

root@OpenWrt:~# spi-bridge

RT-Thread shell commands:
reset            - reset to bootloader.
pwmWrite         - pwmWrite pinNum duty_cycle.
analogRead       - analogRead pinNum.
togglePin        - togglePin pinNum.
digitalWrite     - digitalWrite pinNum 0x1/0x0.
digitalRead      -digitalRead pinNum.
pinMode          - pinMode pinNum mode.
list_device      - list device in system
list_timer       - list timer in system
list_mempool     - list memory pool in system
list_mutex       - list mutex in system
list_event       - list even in system
list_sem         - list semaphore in system
list_thread      - list thread
version          - show RT-Thread version information
help             - RT-Thread shell help.
free             - Show the memory usage in the system.
time             -Execute command with time.
ps               - List threads in the system.
msh >
msh > pinMode 3 OUTPUT       //pinMode: The first argument is the pin 3, and the second parameter sets the pin 3 status OUTPUT; pinMode no return value, then press the enter key.
msh > digitalWrite 3 HIGH   //digitalWrit: The first argument is the pin 3;  and the second parameter setting pin 3 to a high level;
msh > digitalWrite 3 LOW    //digitalWrit: The first argument is the pin 3;  and The second parameter setting pin 3 to a low level;

pinMode: set pin attributes (input or output), the format command

pinMode pinNum mode

"mode" can be numeric or the following keywords


Complete definition in github website:
digitalWrite: set the pin high and low, the command format is as follows:

digitalWrite pinNum HIGH/LOW

pwmWrite: the command format is as follows:

pwmWrite pinNum duty_cycle

duty_cycle ranges from 0 to 65535, the duty cycle is duty_cycle/65535
Set the pin PWM mode:

$ pinMode 0 PWM

Here I use a logic analyzer to observe the PWM waveform on the pin

First, the duty cycle is set to 50%, run the following command

$ pwmWrite 0 32768

Logic analyzer to capture the waveform as follows:

You can see the PWM waveform that the frequency is 550Hz and the duty cycle is 50%
Run the following command again

$ pwmWrite 0 10000

Logic analyzer to capture the waveform as follows:

You can see the generated waveform duty cycle of 15.62%, in line with 10000/65535.
You can see that with the continuous improvement on the STM32 system, now we can take advantage of openwrt the spi-bridge carried the GPIO control.

Arduino function call in scripting programming language

With 0,1,2,6 (PA0、PA1、PA8、PA11) pins do marquees

spi-bridge write "pinMode 0 0"
spi-bridge write "pinMode 1 0"
spi-bridge write "pinMode 2 0"
spi-bridge write "pinMode 6 0"
while true
  spi-bridge write "digitalWrite 0 1"
  sleep 1
  spi-bridge write "digitalWrite 0 0"
  spi-bridge write "digitalWrite 1 1"
  sleep 1
  spi-bridge write "digitalWrite 1 0"
  spi-bridge write "digitalWrite 2 1"
  sleep 1
  spi-bridge write "digitalWrite 2 0"
  spi-bridge write "digitalWrite 6 1"
  sleep 1
  spi-bridge write "digitalWrite 6 0"

Operating results are as follows:

Download and compile the code

All of the code of STM32 are open source, any user can download. Are also welcome to submit code to the code base.
Github repo:
Some users want to be able to use msh on usart1, instead of by 7688 spi, so we provide a branch for mapping MSH to usart1.code libraries as follows:
Ideally, we will be updated simultaneously two branch code, but if there is some conflict, in order to master the main branch.
When we use rtthread of rtt mainline code does a small part of the changes, and has proposed a pull request to the RTT, but rtt in choosing whether to merge there will be some delay, so we recommend downloading our fork out rtt code we will also actively rebase Rtt mainline code.
Compile Process:
Installing python scons gcc-arm-none-eabi(4.8 or above),then execute the following code:

$ mkdir wrtnode2r-stm32
$ cd wrtnode2r-stm32
$ git clone  wrtnode2r_stm32
$ git clone rtt
$ cd wrtnode2r_stm32
Setting gcc path:
$ vi 
$ scons

After successful compilation, the resulting rt thread.bin is stm32 firmware.

Updating firmware

In the stm32 of WRTnode2R/en, we preset a bootloader in the first 4K of stm32 so we could update firmware of stm32 online in mt7688, which provide by a 7688 tools named flash-stm32.
Using flash-stm32 like:

root@OpenWrt:~# flash-stm32 URL

URL argument could be the file url from internet or the local file.
We recommended to update the new firmware:

root@OpenWrt:~# flash-stm32

As shown, stm32 updating finished, after that stm32 will reboot automatically.

If user want to do stm32 development by yourself, use tools like stlink to deleop/debug/reflash. Here's what we must know:

  1. User-developed code to redirect to the interrupt vector table location 0x08001000.
  2. User Codes, the position to be downloaded to 0x08001000.
  3. If the user completely abandoned the code we provide, but also want to support online update firmware, you need to realize 7688 control stm32 reset function in the user code.(In we provide in the code, has achieved the reset command, so based on the code we provide for development, do not need to complete this step)

Parts of the document from Very grateful for the support of disorder and