Using STM32 UART Ports in Linux Print

 

Unless you have somehow reconfigured Linux to run the console on some interface other than the serial UART (USART6), the serial device driver is already enabled in your kernel configuration and Linux makes use of STM32 USART6 for the serial console and the high-level shell. This application note explains how to enable additional UART ports in Linux.

First thing you need to do is enable additional UART interfaces in the kernel configuration. To do so, start the kernel configuration GUI (make kmenuconfig from the project directory) and proceed to the following menu: System Type -> STM32 I/O interfaces. In there, enable those UART ports you require in your specific application, for instance:

Do not enable any UART interfaces except for those that you plan to use in your application. For one thing, unless an UART interface is actually required, you want to keep it in reset in order to save some power. Another consideration is that UART signals may conflict with other I/O interfaces on the STM32F7 pins. More on that right below.

Allocation of the STM32 pins to specific I/O interfaces is defined in linux/arch/arm/mach-stm32/iomux.c. When you have enabled UART interfaces that you require in your application, make sure that there is appropriate code in iomux.c that routes the UART signals to those STM32 pins that you have allocated for UART in your design. For example, for USART3 there is the following code defined in iomux.c:

#if defined(CONFIG_STM32_USART3)
gpio_dsc.port = 2;
gpio_dsc.pin = 10;
stm32f2_gpio_config(&gpio_dsc, STM32F2_GPIO_ROLE_USART3);

gpio_dsc.port = 2;
gpio_dsc.pin = 11;
stm32f2_gpio_config(&gpio_dsc, STM32F2_GPIO_ROLE_USART3);
#endif

Note that this particular port (USART3) confilcts with the MMC function defined on the same pins. You need to disable CONFIG_ARMMMCI in the kernel configuration.

There must be a device node in the target root file system for each UART port to allow accessing it using standard Linux interfaces. The device nodes for serial ports are conventionally referred to as /dev/ttySn. Note also that that ttyS0 corresponds to USART1, ttyS1 to USART2 and so on. Make sure there is a device node for your UART interface in your <project>.initramfs file:

nod /dev/ttyS0 0666 0 0 c 4 64
nod /dev/ttyS1 0666 0 0 c 4 65
nod /dev/ttyS2 0666 0 0 c 4 66
...

Each device node for the UART ports must have a unique minor number, the count starts with 64 for USART1 (/dev/ttyS0). All UART ports share a single major number (4).

Having updated your project configuration as described above, build the bootable Linux image (<project>.uImage) by running make in the project directory. The procedure described here explains how to install Linux image (uImage) to the target.

When you boot the newly installed Linux image on the target, there will be a message in the kernel bootstrap print-out indicating that additional UARTs interfaces are available:

stm32serial.2: ttyS2 at MMIO 0x40004800 (irq = 39) is a STM32 USART Port
stm32serial.5: ttyS5 at MMIO 0x40011400 (irq = 71) is a STM32 USART Port

Typically, UART ports are used to connect various equipment such as modems, sensors, additional computers and so on. In Linux, serial ports are accessed from C-level user space code using the stadard POSIX APIs. These APIs are extensively defined in various materials available in the Internet. For instance, try googling for something like this "How to access serial ports in C".

As a simple test, the following command can be used to send a file to USART3:

~ # cat test.file > /dev/ttyS2
~ #