cancel
Showing results for 
Search instead for 
Did you mean: 

STM32MP135 LIN master on Linux: How to send the 13 bit break signal?

ac1dg
Associate

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:

ac1dg_0-1733905399822.png

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!

1 REPLY 1
ac1dg
Associate

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;
}