STM32MP1 - kernels + Linux = perfect microcontroller

By the nature of my activity, I am engaged in the development of various devices: measuring, controlling, controlling, etc. The vast majority of the device is divided into 2 parts:

  1. High-resource microcontroller and not requiring hard real-time graphical user interface (GUI).
  2. Consuming few resources and working in hard real-time hardware of the device.

And as a rule, the transition to a new series of microcontrollers was determined by the improvement of the GUI: more colors, higher resolution, more complex design elements. At one time, the idea was to use some kind of Raspberry board as a graphical interface.

But with the advent of STM's new line of STM32MP1 microcontrollers, my torment ended and that's what happened so far.

Perfect controller


An ideal controller for me should have the following characteristics:

  • have decent graphics capabilities, such as simple support for various graphic formats, support for vector fonts
  • large amount of memory for graphics
  • USB keyboard and mouse support
  • Ethernet support
  • a large number of hardware timers
  • PWM generation
  • a large number of GPIO
  • 16 bit ADC

It is these requirements that are needed to build various devices with a decent graphical user interface.

And so I was very happy to see a new series from STM: STM32MP1.

First meeting


To familiarize with the new chip, the STM32MP157C-DK2 board was purchased. Here's one (photo from an Internet): The



demo board is built on a STM32MP157CAC chip, which includes:

  • 2 cores A7, 650 MHz each
  • 1 core M4, 208 MHz

Memory


The very first difference that catches your eye is the lack of flash memory on the chip. For the A7 core, which is essentially a microprocessor, this is a normal situation and the code is always executed from DRAM. Microcontrollers based on M4 usually include flash memory in which executable code is stored.

In this crystal, the M4 kernel has only RAM and the code is executed from it (from the datasheet):

708 Kbytes of internal SRAM: 256 Kbytes of
AXI SYSRAM + 384 Kbytes of AHB SRAM +
64 Kbytes of AHB SRAM in Backup domain
and 4 Kbytes of SRAM in Backup domain

The A7 core has a built-in DDR controller (from a datasheet):
The STM32MP157C / F devices embed a controller for external SDRAM which support the
following devices:

  • LPDDR2 or LPDDR3, 16- or 32-bit data, up to 1 Gbyte, up to 533 MHz clock.
  • DDR3 or DDR3L, 16- or 32-bit data, up to 1 Gbyte, up to 533 MHz clock.

On the one hand, the memory of the M4 kernel seems to be less than that of the version in flash memory, but on the other hand, RAM memory runs at the core frequency. Flash memory cannot do this, and there you have to use a frequency divider.

Workplace organization


Since Linux is needed to work with the board, I had to install an additional hard drive in my computer and deploy Ubuntu 16.04 on it. This OS is recommended by STM.

Engineering & Production mode


The board can start in one of two modes (determined by dip switch). In Engineering mode, the M4 core works separately. In Production mode, the M4 core runs under the control of the A7 core. I did not use Engineering mode, I worked only in Production mode. In this mode, you don’t have to worry about tuning the core clock. Timing is configured during the boot process at maximum values. I checked several registers in the debugger, deduced some of the frequencies on the MCO and looked at the oscilloscope. A7 operates at a frequency of 650 MHz, M4 at a frequency of 208 MHz.

Kernel M4. Download and run programs


Since the M4 core is running A7, it means running OpenSTLinux. The Linux remoteproc framework (RPROC) is used to control the M4 core. This framework allows you to enable and disable the kernel, download and debug software (ELF files).

To load the program into the M4 kernel, use the following command:

echo -n <firmware_name.elf>> / sys / class / remoteproc / remoteproc0 / firmware

To start the program:

echo start> / sys / class / remoteproc / remoteproc0 / state

To stop:

echo stop> / sys / class / remoteproc / remoteprocX / state

Kernel M4. SW4STM32


The above mentioned commands have been tried, everything works :) But to work, you need some kind of normal IDE. STM recommends using AC6 SW4STM32 software for this. At the same time, the OpenSTM32 website has a very cool title:
With System Workbench for Linux, Embedded Linux on the STM32MP1 family of MPUs from ST was never as simple to build and maintain, even for newcomers in the Linux world.
And, if you install System Workbench for Linux in System Workbench for STM32 you can seamlessly develop and debug asymmetric applications running partly on Linux, partly on the Cortex-M4.
That is, you can write code for both the m4 core and A7. But this is a paid version. And the free one, which is available for download, allows you to write and debug code only for the M4 core.

IDE SW4STM32 has been downloaded, installed and tried. Everything works, the process of writing and compiling is no different from the version on Windows.
The only difference is code loading and debugging, because Ethenet and SSH connection are used to write software. For debugging and stopping by points, the built-in ST LINK board is used.

Kernel A7. Cross compiler


To compile programs on a PC, STM offers a cross-compiler. The process of loading and running the cross-compiler script is described in detail in the STM32MP1 wiki, link below. Everything was done according to the instructions, everything works as it should. :)

Running the cross-compiler for the ecosystem v1.1.0:

source SDK / environment-setup-cortexa7t2hf-neon-vfpv4-openstlinux_weston-linux-gnueabi
well, then the
make command
and the source code, according to makefile, will be compiled into ARM codes :)

Kernel A7. Download and run programs


To load the program into the demo board, use the command:

scp gtk_hello_world root@192.168.1.18: / usr / local

This command downloads the gtk_hello_world file to the / usr / local section, which is located on the board with IP address: 192.168.1.18. Root - the password that is on the board by default.

Inter-core data exchange


Most of the time was spent understanding the mechanism of data exchange between the cores. In the examples that are supplied by STM, there are several options for implementing such an exchange. You can work directly with the driver from OpenSTLinux or use the virtual UART mechanism. I decided to make sharing via virtual ports as simpler.

On the Linux side, it looks like this:

Open the device:

fd = open ("/ dev / ttyRPMSG0", O_RDWR);

Then we write to it or read:

write (fd, "LED_Toggle \ r \ 0", 10);
len = read (fd, buf, sizeof (buf));

Everything is quite simple, but there is a small nuance. For the ttyRPMSG0 device to appear, you need the M4 core to access the A7 core in this form:

these are the lines of the M4 core code:

VIRT_UART_Init(&huart0); //  
VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) //      .

Reception of data from a virtual port by the M4 core:

if (VirtUart0RxMsg)
{
      //     VirtUart0ChannelBuffRx
     
      VirtUart0RxMsg = 0;
}

Writing data to the virtual port:

VIRT_UART_Transmit(&huart0, TxArray, TXCounter);

Everything works, but there is a small nuance that I can’t understand yet. Reception of data by the A7 core, which is transmitted by the M4 core, does not start unless the A7 core previously writes any data to the port.

This whole mechanism is implemented by a set of third-party OpenAMP libraries. This library should be included in the M4 kernel project and initialized accordingly.

Future plans


Install and configure Eclipse to write and debug code for A7.
Write a normal graphical demo, such as an oscilloscope from an M4 ADC.
And finally, make your controller board based on this chip. :) Wiki

Useful Links

STM32MP1
OpenSTM32
ST Community
AC6

All Articles