Discovery kit with STM32MP157x MPU Series
Supported boards
Since core version 1.8.0, the following boards are supported:
This port targets the Cortex-M4 coprocessor. The coprocessor is not a stand-alone microcontroller: the Arduino firmware for it must be managed by the host Linux system on the Cortex-A side. Cortex-M4 Engineering mode is not supported; only Production mode is supported.
Because operating systems may have different software configurations, especially Device Tree settings, not all Linux distributions are supported. The currently supported distributions are:
Other distributions may run Arduino firmware but are not tested. The STM32MP15 Starter Package and OpenSTLinux should select the stm32mp157c-dk2-m4-examples-sdcard boot mode, or equivalent Device Tree configuration, at boot. The stm32mp157c-dk2-sdcard boot mode is also known to work but is not guaranteed. See the ST Wiki boot-mode documentation for details.
How to use
After Verify and Upload, Arduino IDE generates a script similar to:
<Arduino build output path>/run_arduino_<sketch name>.sh
And displays a message similar to:
<Arduino build output path>/run_arduino_<sketch name>.sh generated successfully.
This file should be uploaded manually by SCP, SFTP, Kermit, or etc.
Then run "sh ./run_arduino_<sketch name>.sh start" command in the board's console.
For detailed instructions, please visit:
https://stm32duino.github.io/STM32MP1/
Upload the generated script manually to the board's Linux file system. Uploading instruction is described later in the Uploading section. Then run this command from the host Linux console, using SSH or a serial console:
sh run_arduino_<sketch name>.sh start
For example, the generated file is located under the Arduino build path, such as /tmp/arduino_build_668148/run_arduino_Blink.sh on Linux/macOS or C:/Users/%USERNAME%/AppData/Local/Temp/arduino_build_668148/run_arduino_Blink.sh on Windows.
The start command runs the Arduino firmware for the current boot only. To run it automatically after reboot, install the generated service:
sh run_arduino_<sketch name>.sh install
The generated script also supports stop, restart, uninstall, monitor, send-msg, send-file, minicom, and log. See run_arduino_gen.sh for the complete help text and script implementation.
Virtual Serial
Virtual Serial uses the OpenAMP RPMsg framework for communication between the Linux host and the Arduino coprocessor. It is available through the SerialVirtIO object and can be used like a standard Arduino Serial object.
Enable Virtual serial support in Arduino IDE > Tools. You can optionally alias the generic Serial object to SerialVirtIO. When enabled, /dev/ttyRPMSG0 is available on the Linux host.
The generated script provides monitor, minicom, send-msg, and send-file convenience commands. See the OpenAMP overview and Linux RPMsg documentation for background.
Configuration
The following definitions control the related buffers:
The recommended option is to resize VRING_NUM_BUFFS. Be cautious when resizing RPMSG_BUFFER_SIZE, which must match the Linux kernel definition. VIRTIO_BUFFER_SIZE has a minimum required size derived from the other two settings.
Since OpenSTLinux 4.0 with Linux 5.15, RPMSG_SERVICE_NAME has been renamed from rpmsg-tty-channel to rpmsg-tty. For older distributions, redefine it to rpmsg-tty-channel.
To redefine these settings, use a build_opt.h file as described in Customize build options.
Virtual Serial example
int available;
char buffer[1024];
unsigned long start_time = 0;
void setup() {
Serial.begin(); // The baud rate is ignored.
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
available = Serial.available();
while (available > 0) {
int size = min(available, Serial.availableForWrite());
Serial.readBytes(buffer, size);
Serial.write(buffer, size);
available -= size;
}
if ((millis() - start_time) > 1000) {
start_time = millis();
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
SerialVirtIO has a hard write-size limit, so write no more than Serial.availableForWrite() bytes at a time. See the implementation limit.
After loading Arduino, You can use SerialVirtIO in two ways in this example:
1- Run sh run_arduino_<sketch name>.sh minicom and type anything in the minicom console. The console will print out what you type immediately.
2- Open two Linux consoles (using SSH)
- In the first console, run
sh run_arduino_<sketch name>.sh monitor - In the second console, run
sh run_arduino_<sketch name>.sh send-msg <your message>orsh run_arduino_<sketch name>.sh send-file <your file>, the first console will print the content of the message.
Debugging
For printf-style debugging, core_debug() is recommended instead of Arduino Serial. On STM32MP1, it uses the OpenAMP trace buffer and is not bound to the speed of a hardware I/O peripheral.
Enable Core logs Enabled in Tools > Debug symbols and core logs. You can resize the log buffer by creating build_opt.h in the sketch directory:
-DVIRTIO_LOG_BUFFER_SIZE=4086
Include core_debug.h and enable SerialVirtIO.begin() because the logging feature uses OpenAMP virtio. Print logs with:
sh run_arduino_<sketch name>.sh log
Alternatively, read the Linux trace buffer directly with cat /sys/kernel/debug/remoteproc/remoteproc0/trace0. When the trace buffer overflows, old logs are overwritten. See virtio_log.h for more information.
Debugging example
#include "core_debug.h"
unsigned long time = 0;
unsigned long count = 1;
void setup() {
SerialVirtIO.begin();
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if ((millis() - time) > 1000) {
time = millis();
core_debug("%u seconds\n", count++);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
Pin mapping
The boards have Raspberry Pi HAT headers and Arduino shield headers. This port currently supports the Arduino shield headers; the HAT headers remain available to Linux applications. PWM N channels, such as TIM1_CH3N, produce an inverted duty cycle on the corresponding output.
| Feature | ST | Arduino | Arduino | ST | Feature | PWM | |
|---|---|---|---|---|---|---|---|
| SCL | PA_11 | I2C5-SCL | TIM1_CH4 | ||||
| SDA | PA_12 | I2C5-SDA | |||||
| Varef | |||||||
| NC | 13 | PE_12 | SPI4-SCK | TIM1_CH3N | |||
| 5V | 12 | PE_13 | SPI4-MISO | TIM1_CH3 | |||
| RST | 11 | PE_14 | SPI4-MOSI | TIM1_CH4 | |||
| 3.3V | 10 | PE_11 | SPI4-SS | TIM1_CH2 | |||
| 5V | 9 | PH_6 | TIM12_CH1 | ||||
| GND | 8 | PG_3 | |||||
| GND | |||||||
| Vin | 7 | PD_1 | |||||
| ADC1_IN0 | PF_14 | A0 | 6 | PE_9 | TIM1_CH1 | ||
| ADC1_IN1 | PF_13 | A1 | 5 | PD_15 | TIM4_CH4 | ||
| ADC1_IN6 | ANA_0 | A2 | 4 | PE_10 | TIM1_CH2N | ||
| ADC1_IN2 | ANA_1 | A3 | 3 | PD_14 | TIM4_CH3 | ||
| ADC1_IN13 | PC_3 | A4 | 2 | PE_1 | |||
| ADC1_IN14 | PF_12 | A5 | 1 | PE_8 | UART7-TX | TIM1_CH1N | |
| 0 | PE_7 | UART7-RX |
Additional pins are available for LEDs and buttons:
| ST | Arduino | Arduino (continued) | Comment |
|---|---|---|---|
| PA_14 | 16 / LED_GREEN | USER1_BTN / USER_BTN | Active low, LED LD5, also connected to B3 button |
| PA_13 | 17 / LED_RED | USER2_BTN | Active low, LED LD6, also connected to B4 button |
| PH_7 | 18 / LED_ORANGE / LED_BUILTIN | Active high, LED LD7 |
See the complete board variant pin definitions for the full mapping.
Uploading
The generated run_arduino_<sketch name>.sh file must be uploaded manually from the PC to the board's Linux file system before it can be executed by the board console. SCP and SFTP are convenient because the board normally runs an SSH server. C-Kermit can transfer the generated script over a serial connection; see the ST Wiki C-Kermit guide.
Linux Device Tree considerations
The Linux host and Arduino firmware cannot share a peripheral. A custom OS Device Tree must reserve the peripherals used by the Arduino firmware.
For example, Arduino uses TIM1 for the analogWrite() PWM implementation. Disable TIM1 for Linux:
&timers1 {
status = "disabled";
};
Then enable TIM1 for the coprocessor:
&m4_timers1 {
pinctrl-names = "rproc_default";
pinctrl-0 = <&timer1_pins>;
status = "okay";
};
The stm32mp157c-dk2-m4-examples.dts example is a useful starting point. See the complete peripheral pin map for the peripherals used by the Arduino firmware.
Limitations
- Ethernet and USB are not supported by the Arduino coprocessor port; use them from the Linux host.
- I2C pins on the Raspberry Pi HAT header, GPIO2 and GPIO3, are not available to the Linux host because the Discovery board shares them with the Arduino header.
- Early firmware loading from the U-Boot stage is not supported. Firmware loading is supported during the Linux boot stage through systemd, using
sh run_arduino_<sketch name>.sh install. - The EEPROM library uses RETRAM because these devices do not have non-volatile memory. Data is preserved only when VBAT is supplied and the coprocessor is woken from sleep. A cold boot can still cause data loss. See the ST Community RETRAM discussion for details.