MSPM0C1106: UART 9 Bit Address Mode Debug

Part Number: MSPM0C1106

Customer is strugging to debug 9 Bit Address UART Mode where UART1 is initially TX to UART2 that detects the activity and sends back to UART1

 

Customer can only transmit 1 message and the tx interrupt doesn't appear to trigger again.

 

Customer have printf outputs at the bottom.

 

Here is what they think is the relevant code:

 

volatile uint8_t uart1RxBuffer[UART_RX1_BUFFER_SIZE];

volatile uint16_t uart1RxHead = 0;

volatile uint16_t uart1RxTail = 0;

 

volatile uint8_t uart2RxBuffer[UART_RX2_BUFFER_SIZE];

volatile uint16_t uart2RxHead = 0;

volatile uint16_t uart2RxTail = 0;

 

volatile uint8_t uart2TxBuffer[TX2_BUFFER_SIZE];

volatile uint16_t uart2TxHead = 0;

volatile uint16_t uart2TxTail = 0;

 

volatile uint8_t uart1TxBuffer[TX1_BUFFER_SIZE];

volatile uint16_t uart1TxHead = 0;

volatile uint16_t uart1TxTail = 0;

/* Track if this is first byte of message */

 

static volatile bool uart1IsFirstByte = true;

static volatile bool uart2IsFirstByte = true;

 

#define UART_LCRH_EPS_BIT_POSITION  (2U)

 

static inline void setEPSBit(UART_Regs *uart)

{

    uart->LCRH |= (1UL << UART_LCRH_EPS_BIT_POSITION);

}

 

static inline void clearEPSBit(UART_Regs *uart)

{

    uart->LCRH &= ~(1UL << UART_LCRH_EPS_BIT_POSITION);

}

 

void UART1_IRQHandler(void)

{

    switch (DL_UART_Main_getPendingInterrupt(UART_1_INST))

    {

        case DL_UART_MAIN_IIDX_RX:

        printf("made it to uart1 interrupt rx isr\n");

         bool wasEmpty = (uart2TxHead == uart2TxTail);

            while (!DL_UART_Main_isRXFIFOEmpty(UART_1_INST))

            {

                uint8_t rx = DL_UART_receiveData(UART_1_INST);

                uint16_t nextHead = (uart2TxHead + 1) % TX2_BUFFER_SIZE;

                if (nextHead != uart2TxTail)

                {

                    uart2TxBuffer[uart2TxHead] = rx;

                    uart2TxHead = nextHead;

                }

            }

 

            /* Kickstart TX if buffer was empty */

 

            if (wasEmpty && (uart2TxHead != uart2TxTail))

            {

                uart2IsFirstByte = true;

                DL_UART_Main_enableInterrupt(

                    UART_2_INST,

                    DL_UART_MAIN_INTERRUPT_TX

                );

            }

 

            break;

 

        case DL_UART_MAIN_IIDX_TX:

        printf("made it to uart1 tx interrupt isr\n");

            while (!DL_UART_Main_isTXFIFOFull(UART_1_INST) &&

                   (uart1TxHead != uart1TxTail))

            {

                /* Set or clear EPS bit based on first byte status */

                if (uart1IsFirstByte)

                {

                    setEPSBit(UART_1_INST);      /* 9th bit = 1 for address */

                    uart1IsFirstByte = false;

                }

                else

                {

                    clearEPSBit(UART_1_INST);    /* 9th bit = 0 for data */

                }

                /* Send data UNCHANGED - EPS bit in LCRH controls 9th bit */

                uint8_t txData = uart1TxBuffer[uart1TxTail];

                printf("txdata is %x\n", txData);

                DL_UART_Main_transmitData(UART_1_INST, txData);

 

                uart1TxTail = (uart1TxTail + 1) % TX1_BUFFER_SIZE;

            }

 

            /* Disable TX interrupt if buffer empty */

            if (uart1TxHead == uart1TxTail)

            {

                DL_UART_Main_disableInterrupt(

                    UART_1_INST,

                    DL_UART_MAIN_INTERRUPT_TX

                );

                uart1IsFirstByte = true;

            }

            break;

 

            case DL_UART_MAIN_IIDX_OVERRUN_ERROR:

            DL_UART_Main_clearInterruptStatus(

                UART_1_INST,

                DL_UART_MAIN_INTERRUPT_OVERRUN_ERROR

            );

            break;

             case DL_UART_MAIN_IIDX_PARITY_ERROR:

               printf("uart 1 PARITY ERROR\n");

               break;

        default:

            break;

    }

}

 

void UART2_IRQHandler(void)

{

    switch (DL_UART_Main_getPendingInterrupt(UART_2_INST))

    {

        case DL_UART_MAIN_IIDX_RX:

         printf("made it to uart2 interrupt rx isr\n");

            bool wasEmpty = (uart1TxHead == uart1TxTail);

            while (!DL_UART_Main_isRXFIFOEmpty(UART_2_INST))

            {

                uint8_t rx = DL_UART_receiveData(UART_2_INST);

                uint16_t nextHead = (uart1TxHead + 1) % TX1_BUFFER_SIZE;

                if (nextHead != uart1TxTail)

                {

                    uart1TxBuffer[uart1TxHead] = rx;

                    uart1TxHead = nextHead;

                }

            }

 

            /* Kickstart TX if buffer was empty */

            if (wasEmpty && (uart1TxHead != uart1TxTail))

            {

                uart1IsFirstByte = true;

                DL_UART_Main_enableInterrupt(

                    UART_1_INST,

                    DL_UART_MAIN_INTERRUPT_TX

                );

            }

            break;

            case DL_UART_MAIN_IIDX_TX:

             printf("made it to uart1 interrupt tx isr\n");

            while (!DL_UART_Main_isTXFIFOFull(UART_2_INST) &&

                   (uart2TxHead != uart2TxTail))

            {

                /* Set or clear EPS bit based on first byte status */

                if (uart2IsFirstByte)

                {

                    setEPSBit(UART_2_INST);      /* 9th bit = 1 for address */

                    uart2IsFirstByte = false;

                }

                else

                {

                    clearEPSBit(UART_2_INST);    /* 9th bit = 0 for data */

                }

                /* Send data UNCHANGED - EPS bit in LCRH controls 9th bit */

                uint8_t txData = uart2TxBuffer[uart2TxTail];

               

                DL_UART_Main_transmitData(UART_2_INST, txData);

 

                uart2TxTail = (uart2TxTail + 1) % TX2_BUFFER_SIZE;

            }

 

            /* Disable TX interrupt if buffer empty */

            if (uart2TxHead == uart2TxTail)

            {

                DL_UART_Main_disableInterrupt(

                    UART_2_INST,

                    DL_UART_MAIN_INTERRUPT_TX

                );

                uart2IsFirstByte = true;

            }

            break;

            case DL_UART_MAIN_IIDX_OVERRUN_ERROR:

            DL_UART_Main_clearInterruptStatus(

                UART_2_INST,

                DL_UART_MAIN_INTERRUPT_OVERRUN_ERROR

            );

            break;

             case DL_UART_MAIN_IIDX_PARITY_ERROR:

               printf("uart 2 PARITY ERROR\n");

               break;

        default:

            break;

    }

}

 


Less relevant code:

int main(void)

{

    SYSCFG_DL_init();

    printf("I am here\n");

 

    // Enable Receive Interrupts for both UART instances

  //  DL_UART_Main_enableInterrupt(UART_1_INST, DL_UART_MAIN_INTERRUPT_RX);

 //   DL_UART_Main_enableInterrupt(UART_2_INST, DL_UART_MAIN_INTERRUPT_RX);

 

    // Enable CPU Interrupts in the NVIC

    NVIC_EnableIRQ(UART_1_INST_INT_IRQN);

    NVIC_EnableIRQ(UART_2_INST_INT_IRQN);

 

    NVIC_SetPriority(UART_1_INST_INT_IRQN, 1);  // highest

    NVIC_SetPriority(UART_2_INST_INT_IRQN, 0);

    NVIC_SetPriority(I2C_INST_INT_IRQN, 2);

    NVIC_SetPriority(ADC12_0_INST_INT_IRQN, 3);

 

    DL_SYSCTL_disableSleepOnExit();

   

    delay_cycles(10000);

 

     while (1)

     {    

     }

}

 

Both uarts set to even and this:

 

 

The output from my printfs:

CORTEX_M0P: I am here

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart1 tx interrupt isr

 

CORTEX_M0P: txdata is 0

 

CORTEX_M0P: txdata is 2

 

CORTEX_M0P: txdata is 51

 

CORTEX_M0P: txdata is 95

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr

 

CORTEX_M0P: made it to uart2 interrupt rx isr