Hello all,
The main issue is with LIN break/sync feature, mainly it reports "Inconsistent Sync Field" after "Receive Break" interrupt and fails to read a valid PID sent by the LIN master.
Setup
- Xplain Pro development board with SAMD21J18A
- MIKROE´s MCP2003B Click Lin transceiver
- PEAK´s PLIN-USB as the master node
The following figure shows the measurement of the LIN UART tx line with SALEAE logic analyzer. The Header seems correct, the baud in the master side is also set to 19.2kbps, as well the logic analyzers protocol analyzing baud rate
Code
#define MAIN_CLOCK_HZ 48000000 // 48MHz void uart_init(void) { /* Configure USART Tx pin as OUTPUT and assign pin mux */ PORT->Group[PORTB].DIRSET.reg = PORT_PB12; PORT->Group[PORTB].PMUX[12>>1].bit.PMUXE = PORT_PMUX_PMUXE_C_Val; PORT->Group[PORTB].PINCFG[12].reg = PORT_PINCFG_INEN | PORT_PINCFG_PMUXEN; /* Configure USART Rx pin as INPUT and assign pin mux */ PORT->Group[PORTB].DIRCLR.reg = PORT_PB13; PORT->Group[PORTB].PMUX[13>>1].bit.PMUXO = PORT_PMUX_PMUXE_C_Val; PORT->Group[PORTB].PINCFG[13].reg = PORT_PINCFG_PMUXEN | PORT_PINCFG_INEN; PM->APBCMASK.reg |= PM_APBCMASK_SERCOM4; /* Configure SERCOM4 to uses GCLK Generator 0 as source - core clock */ GCLK->CLKCTRL.reg = (U16)(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_SERCOM4_CORE); while (GCLK->STATUS.bit.SYNCBUSY); SERCOM4->USART.CTRLA.bit.SWRST = 1u; while(SERCOM4->USART.SYNCBUSY.reg); // configure CTRLA SERCOM_USART_CTRLA_Type cfga = { .bit.CMODE = 1, // 1=asynchronous mode .bit.CPOL = 0, // XCLK polarity, rising->TX, falling->RX (sync mode) .bit.DORD = 1, // 1=LSB sent first (for LIN) .bit.ENABLE = 0, // enable (disable before settings), later .bit.FORM = 4, // 0=UART 1=+PARITY 4=AUTOBAUD 5=+PARITY, 4 has break-detection & auto-baud (for LIN), see STATUS.ISF .bit.IBON = 0, // immediate STATUS.BUFOVF .bit.MODE = 1, // 0=UART+XCLK, 1=UART, 2=SPI-slave, 3=SPI-master, 4=I2C-slave, 5=I2C-master .bit.RUNSTDBY= 1, // run in standby .bit.RXPO = 1, // PAD[1], PIN_PB13 .bit.TXPO = 0, // PAD[0], PIN_PB12 .bit.SAMPA = 0, // SAMPle Adjustment to the right, 0=7/8/9, 1=+2, 2=+4, 3=+6 .bit.SAMPR = 1, // baudrate & oversampling: 0=A16x, 1=F16x, 2=A8x, 3=F8x, 4=A3x, 5=F3x (A=Arithmetic, F=Fractional(=For LIN)) .bit.SWRST = 0, // reset, other bits are ignored }; SERCOM4->USART.CTRLA = cfga; while(SERCOM4->USART.SYNCBUSY.reg); // configure CTRLB SERCOM_USART_CTRLB_Type cfgb = { .bit.CHSIZE = 0, // character size: 8 bits .bit.COLDEN = 0, // disable collision detection .bit.ENC = 0, // IrDA encoding not applicable .bit.PMODE = 0, // parity not applicable .bit.RXEN = 1, // enable RX, see SYNCBUSY.CTRLB .bit.TXEN = 1, // enable TX, see SYNCBUSY.CTRLB .bit.SBMODE = 0, // set 1 stopbit .bit.SFDE = 0, // disable start of frame detection }; SERCOM4->USART.CTRLB = cfgb; while(SERCOM4->USART.SYNCBUSY.reg); #define BAUDCONST8 ((MAIN_CLOCK_HZ * 8) / (16 * 19200)) SERCOM4->USART.BAUD.FRAC.FP = (BAUDCONST8 % 8); SERCOM4->USART.BAUD.FRAC.BAUD = (BAUDCONST8 / 8); while(SERCOM4->USART.SYNCBUSY.reg); SERCOM4->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | SERCOM_USART_INTENSET_RXBRK; NVIC_SetPriority(SERCOM4_IRQn, 0u); NVIC_EnableIRQ(SERCOM4_IRQn); SERCOM4->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; while(SERCOM4->USART.SYNCBUSY.bit.ENABLE); } void SERCOM4_Handler(void) { /* Temporary variables */ U16 interrupt_status; while(SERCOM4->USART.SYNCBUSY.reg); /* Read and mask interrupt flag register */ interrupt_status = SERCOM4->USART.INTFLAG.reg; interrupt_status &= SERCOM4->USART.INTENSET.reg; if (interrupt_status & SERCOM_USART_INTFLAG_RXBRK) { /* Break and sync must have been received at this time */ // Get an hit here, but ISF is set in the status field SERCOM4->USART.INTFLAG.reg = SERCOM_USART_INTFLAG_RXBRK; } /* After the break/sync the LIN PID must be received */ if (interrupt_status & SERCOM_USART_INTFLAG_RXC) { // Get here as well but the data is always 0xFF U16 tmp = (SERCOM4->USART.DATA.reg & SERCOM_USART_DATA_MASK); } }
When I reconfigure the UART to work with plain UART .FORM = 0, .SAMPR = 0. Re calculate the baud
U64 br = (U64)65536 * (F_CPU - 16 * baud) / F_CPU; // Variable for baud rate
Then I receive the sync byte 55h, the PID 06h but I also get the frame error, because of the 13 dominant bits.
I have run out of ideas to try.. did not even find a issue in errata. Although it mentioned that it might not set ISF if some stop bit error, but my case is the reverse- it is always set!
SEND HELP!!