UART break at first

Bencium
Posts: 1
Joined: Fri May 20, 2022 5:29 pm

Re: UART break at first

Postby Bencium » Fri May 20, 2022 8:48 pm

Hi sorry to bump this thread.

I have joined the forum as am interested in implementing some Lin communication on an ESP to control some ambient light lin devices on my car and I have found this thread to very interesting.
Phatpaul, I was wondering if you are sharing your LIn driver including the headers. It seems to me something very complex for my skills level and it would be a great starting point to have a working driver as an start point.

Will it work as well in an ESP8266?

Thanks a lot in advance
Best regards

phatpaul
Posts: 110
Joined: Fri Aug 24, 2018 1:14 pm

Re: UART break at first

Postby phatpaul » Fri Jun 03, 2022 6:15 pm

Well, a recent update to esp-idf has broken my LIN break method. In 3.3.5 it works, then in 3.3.6, the break is not long enough.

From the release notes:
https://github.com/espressif/esp-idf/re ... tag/v3.3.6

Perhaps something in one of these changes broke my LIN solution:

Freemodbus: Fixed rs485 rts de-assert fail when tx delayed (#6728)
Freemodbus: Added the MB_PORT_TASK_AFFINITY kconfig option for modbus tasks (#6700)
UART: Fixed uart module reset issue (#1202)
UART: Added config to support placing UART ISR in IRAM
UART: Fixed a typo in the error message of invalid rx_thresh_xoff

@Bencium I can share my example project, but I'll need a little time to prepare it. Do you need LIN master or slave for your application? If the lights you want to control are already commanded by a master (i.e. part of your car) then I'm not sure how you can override that.

FlorianR
Posts: 28
Joined: Fri Mar 12, 2021 2:00 pm

Re: UART break at first

Postby FlorianR » Fri Jun 03, 2022 7:33 pm

Hi I had the same problem and "fixed" it. After lots of trial and error I added a second wait_for_tx_done after the first one. And now it "works" again for some reason. I am not happy with the solution, but after spending two days to understand how to add a brake at-front into the library I gave up. The break-at-end is so complicated embedded that I can not get it to send the break before the data....
Best regards and I hope the quick fix fix helps. I wish I could understand the UART code better and contribute something with more value.

phatpaul
Posts: 110
Joined: Fri Aug 24, 2018 1:14 pm

Re: UART break at first

Postby phatpaul » Mon Jun 06, 2022 2:29 pm

@FlorianR thanks! You saved me a bunch of time. (I had just reverted to 3.3.5 until I had time to bisect the problem.)

I also don't know why this works, but since this whole break-at-first method is a hack anyway, your solution fits perfectly.

To be clear, here's the modified

Code: Select all

void LIN_driver_start_frame(uint8_t pid)
{
    uint32_t baudrate;
    uint8_t master_tx_buf[2];
    master_tx_buf[0] = 0x55; // sync byte
    master_tx_buf[1] = pid;

    uint8_t dummy = 0;

    uart_flush_input(lin_uart_num);    // since we are the master, clear out rx buff before starting a frame
    xQueueReset(lin_uart_event_queue); // clear the q for slave rx uart breaks
    /* Send break character */
    // this method sucks b/c it must send a dummy char before the break
    // Note: if use this, then +1 to LIN_IN_HEADER_SIZE for dummy byte.
    //uart_write_bytes_with_break(lin_uart_num, (char *)&dummy, 1, LIN_BREAK_LEN);

    // this method really sucks because of a blocking delay!
    //uart_set_line_inverse(param_ptr_config->uart_port_num, UART_INVERSE_TXD);
    //ets_delay_us(677);
    //uart_set_line_inverse(param_ptr_config->uart_port_num, UART_INVERSE_DISABLE);

    //uart_hal_tx_break(&(uart_context[uart_num].hal), 0); - not available in IDF 3x

    // Temporarily change baudrate to slightly lower and send a 0 byte
    // to get the right baudrate, we want 9 bits (1 start + 8 data) to take the time of 13 bits (one break)
    uart_get_baudrate(lin_uart_num, &baudrate);
#define LIN_BREAK_BAUDRATE(BAUD) ((BAUD * 9) / 13)
    uart_set_baudrate(lin_uart_num, LIN_BREAK_BAUDRATE(baudrate));
    uart_write_bytes(lin_uart_num, (char *)&dummy, 1); // send a zero byte.  This call must be blocking.
    uart_wait_tx_done(lin_uart_num, 2);                // shouldn't be necessary??
    uart_wait_tx_done(lin_uart_num, 2);                // add 2nd uart_wait_tx_done per https://esp32.com/viewtopic.php?p=98456#p98456
    uart_set_baudrate(lin_uart_num, baudrate);         // set baudrate back to normal after break is sent
    // we have to fake a break detect for the slave, since it doesn't detect it with this method.
    uart_event_t event = {.type = UART_BREAK};
    xQueueSend(lin_uart_event_queue, (void *)&event, 0);

    // Now send the sync and PID bytes
    uart_write_bytes(lin_uart_num, (char *)master_tx_buf, sizeof(master_tx_buf));
}

Who is online

Users browsing this forum: No registered users and 80 guests