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