2024-12-11 12:32 AM
Hi,
I am trying to write a LIN master for STM32MP135 running a Yocto Linux. Currently, I am struggling with the break signal. According to the LIN specification, it has to be at least 13 (up to 20) bits long. The device I am trying to talk to is using 9600 baud and the break signal is 1340μs there:
A LIN tranceiver is connected to USART1 on my board. How can I send the correct break signal on USART1 on Linux?
Thank you in advance!
2025-02-11 4:51 AM - edited 2025-02-11 4:52 AM
I found a solution: Using mmap, you can map the registers into userspace and change the bits for LINEN there. This is only possible, if the port for the serial is already opened in your main program. Here is an example code in C:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdint.h>
#define USART1_BASE 0x4C000000
#define PAGE_SIZE 4096
int main() {
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
perror("open");
return 1;
}
// Map USART1 registers
void *map = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, USART1_BASE);
if (map == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
volatile uint32_t *usart = (volatile uint32_t *)map;
// USART_CR1 (offset 0x00)
volatile uint32_t *cr1 = &usart[0];
// USART_CR2 (offset 0x04)
volatile uint32_t *cr2 = &usart[1];
// 1. Clear UEN bit in CR1
*cr1 &= ~(1 << 0);
// 2. Set LINEN bit in CR2
*cr2 |= (1 << 14);
// 3. Set UEN bit in CR1 again
*cr1 |= (1 << 0);
// Cleanup
munmap(map, PAGE_SIZE);
close(fd);
return 0;
}