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