I am using a K60 UART module to communicate with another device, and the communication works fine, except that the UART fails to trigger an interrupt when (UART0_S1) RDRF is set, even though (UART_C2) RIE was set during configuration. I have read every thread on the Kinetis forum related to UART, and have found nothing of any use in my case.
The K60's UART is not triggering an interrupt when the number of bytes received is equal to or greater than the watermark value. UART0_C2's RIE bit is set, and the UART0_S1 RDRF is changing from 0 to 1, but no interrupt is being generated. The UART0_C5 RDMAS bit is set to 0, so no DMA request is being generated, and the microcontroller is not calling an undefined interrupt or freezing up. The UART module is receiving the data well, and RWFIFO, RCFIFO, and all the other registers are behaving normally, but no interrupt is being generated by the RDRF flag.
There is some redundant code in the configuration, because I have been trying to make this work for the last two days, so please forgive the sloppy coding.
The configuration function and its call are as follows:
void uart_init (UART_MemMapPtr uartch, int sysclk, int baud, void * lon_vector, void * rx_tx_vector, void * err_vector) // sysclk is the module clock frequency in MHz
{
register uint16_t ubd, brfa;
uint8_t temp;
unsigned short int LON = NULL, RX_TX = NULL, ERR = NULL;
/* Enable the clock to the selected UART */
if(uartch == UART0_BASE_PTR){
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;
PORTA_GPCHR = ((0x0003C000))&0xFFFF0000 | PORT_PCR_MUX(3); // set pins to UART
PORTA_GPCLR = ((0x0003C000)<<0x10)&0xFFFF0000 | PORT_PCR_MUX(3); // set pins to UART
SIM_SCGC4 |= SIM_SCGC4_UART0_MASK;
LON = INT_UART0_LON;
RX_TX = INT_UART0_RX_TX;
ERR = INT_UART0_ERR;
}else if (uartch == UART1_BASE_PTR){
SIM_SCGC4 |= SIM_SCGC4_UART1_MASK;
RX_TX = INT_UART1_RX_TX;
ERR = INT_UART1_ERR;
}else if (uartch == UART2_BASE_PTR){
SIM_SCGC4 |= SIM_SCGC4_UART2_MASK;
SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;
PORTD_GPCLR = ((0x0000000F)<<0x10)&0xFFFF0000 | PORT_PCR_MUX(2); // set pins to UART
RX_TX = INT_UART2_RX_TX;
ERR = INT_UART2_ERR;
}else if(uartch == UART3_BASE_PTR){
SIM_SCGC4 |= SIM_SCGC4_UART3_MASK;
RX_TX = INT_UART3_RX_TX;
ERR = INT_UART3_ERR;
}else if(uartch == UART4_BASE_PTR){
SIM_SCGC1 |= SIM_SCGC1_UART4_MASK;
SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;
PORTE_GPCHR = ((0x0F000000))&0xFFFF0000 | PORT_PCR_MUX(3); // set pins to UART
RX_TX = INT_UART4_RX_TX;
ERR = INT_UART4_ERR;
}else{
SIM_SCGC1 |= SIM_SCGC1_UART5_MASK;
RX_TX = INT_UART5_RX_TX;
ERR = INT_UART5_ERR;
}
if(LON != NULL)
int_disable(LON);
int_disable(RX_TX);
int_disable(ERR);
UART_C2_REG(uartch) = 0x00; //UART_C2_REG(uartch) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK ); // Make sure that the transmitter and receiver are disabled while we change settings.
UART_C1_REG(uartch) = 0; // Configure the UART for 8-bit mode, no parity We need all default settings, so entire register is cleared
ubd = (uint16_t)(sysclk*62500/baud); // Calculate baud settings // (sysclk*1000000)/(baud*16)
temp = UART_BDH_REG(uartch) & ~(UART_BDH_SBR(0x1F)); // Save off the current value of the UARTx_BDH except for the SBR
UART_BDH_REG(uartch) = temp | UART_BDH_SBR(((ubd & 0x1F00) >> 8));
UART_BDL_REG(uartch) = (uint8_t)(ubd & UART_BDL_SBR_MASK);
brfa = ((sysclk*2000/baud) - (ubd * 32)); // Determine if a fractional divider is needed to get closer to the baud rate // (sysclk*32000)/(baud*16)
temp = UART_C4_REG(uartch) & ~(UART_C4_BRFA(0x1F)); // Save off the current value of the UARTx_C4 register except for the BRFA
UART_C4_REG(uartch) = temp | UART_C4_BRFA(brfa); // set the baud rate fine adjust
//begin F
UART_MODEM_REG(uartch) = UART_MODEM_TXRTSPOL_MASK | UART_MODEM_TXRTSE_MASK; // select RTS controlled by transmitter, with active high polarity // UART_MODEM_TXCTSE_MASK makes it so that the CTS value can block the transmitter
UART_PFIFO_REG(uartch) |= UART_PFIFO_RXFE_MASK /*| UART_PFIFO_TXFE_MASK | UART_PFIFO_RXFIFOSIZE(0b001)*/; // set transmit and receive buffer sizes
UART_RWFIFO_REG(uartch) = UART_RWFIFO_RXWATER(0x1); // this value is the number of datawords in the FIFO that will set RIE interrupt
while(UART_RCFIFO_REG(uartch)) // clean out the FIFO
temp = UART_D_REG(uartch); // reading D when the data register is empty causes the FIFO pointer to become misaligned
if((UART_S1_REG(uartch) & UART_S1_RDRF_MASK)||(UART_SFIFO_REG(uartch) & (UART_SFIFO_RXOF_MASK | UART_SFIFO_TXOF_MASK))){// if receipt flag is set, clear the receipt flag
//temp = UART_D_REG(uartch); // read D to clear RDRF
UART_SFIFO_REG(uartch) = UART_SFIFO_RXOF_MASK | UART_SFIFO_TXOF_MASK ; // clear over and underflow error flags
}
if((UART_S1_REG(uartch) & UART_S1_OR_MASK) || (UART_SFIFO_REG(uartch) & UART_SFIFO_RXUF_MASK)){
UART_D_REG(uartch) = 0x00; // write D to clear RDRF
UART_SFIFO_REG(uartch) = UART_SFIFO_RXUF_MASK; // clear over and underflow error flags
}
temp = UART_SFIFO_REG(uartch);
//UART_SFIFO_REG(uartch) = UART_SFIFO_RXOF_MASK | UART_SFIFO_RXUF_MASK | UART_SFIFO_TXOF_MASK ; // clear over and underflow error flags
//UART_CFIFO_REG(uartch) = UART_CFIFO_TXFLUSH_MASK | UART_CFIFO_RXFLUSH_MASK;
if((lon_vector!=NULL) && (LON != NULL)){
ram_insertVector(LON, lon_vector);
int_enable(LON);
}if(rx_tx_vector != NULL){
ram_insertVector(RX_TX, rx_tx_vector);
UART_C2_REG(uartch) |= UART_C2_RIE_MASK; // RIE enables the receiver full interrupt
UART_S2_REG(uartch) &= ~UART_S2_LBKDE_MASK; // if LBKDE is set, RDRF doesn't work
UART_C5_REG(uartch) &= ~UART_C5_RDMAS_MASK; // disable DMA select, so that receipt generates interrupt
int_enable(RX_TX);
}if(err_vector != NULL){
ram_insertVector(ERR, err_vector);
int_enable(ERR);
}
UART_C2_REG(uartch) |= (UART_C2_TE_MASK | UART_C2_RE_MASK ); // Enable receiver and transmitter
}
Initialization funciton call call:
uart_init(UART0_BASE_PTR, core_frequency(), PROJECT_BAUD_RATE, NULL, project_rx, NULL);// initialize UART port
PROJECT_BAUD_RATE == 115200
'project_rx' is the name of the function to be called in the interrupt.
Solved! Go to Solution.
Hi
If you have the interrupt in the UART enabled and also in the NVIC the interrupt must fire when the flag gets set.
Does you Tx interrupt work?
Check the NVIC to see whether something is pending but can't get through due to maybe an incorrect flag setting.
Try leaving all FIFO settings at default values to see whether it makes a difference (just to see whether the interrupt maybe then fires).
Regards
Mark
Kinetis: µTasker Kinetis support
K60: µTasker Kinetis TWR-K60N512 support / µTasker Kinetis TWR-K60D100M support / µTasker Kinetis TWR-K60F120M support
UARTs: http://www.utasker.com/docs/uTasker/uTaskerUART.PDF
For the complete "out-of-the-box" Kinetis experience and faster time to market
Hi,
I agree with Mark, maybe you did not configured correctly.
According the reference manual, the IRQ number for UART0 status is 45.
To enable UART TX and RX interrupt, you need enable UART0 status interrupt first, the code can be as below:
//45%32 = 1, MOD(45, 32) =13
NVICICPR1 |= (1<<13); // Clear pending interrupt on UART0 status
NVICISER1 |= (1<<13); // Enable UART0 status interrupt
NVICIP45 = 0x02; //Set the priority to 2
hope it helps!
Hi
If you have the interrupt in the UART enabled and also in the NVIC the interrupt must fire when the flag gets set.
Does you Tx interrupt work?
Check the NVIC to see whether something is pending but can't get through due to maybe an incorrect flag setting.
Try leaving all FIFO settings at default values to see whether it makes a difference (just to see whether the interrupt maybe then fires).
Regards
Mark
Kinetis: µTasker Kinetis support
K60: µTasker Kinetis TWR-K60N512 support / µTasker Kinetis TWR-K60D100M support / µTasker Kinetis TWR-K60F120M support
UARTs: http://www.utasker.com/docs/uTasker/uTaskerUART.PDF
For the complete "out-of-the-box" Kinetis experience and faster time to market
Hi Mark,
I had not looked at the NVIC registers in detail before your post. After your post, I took a look at the priority registers, comparing them to the ISPR, and found that a higher priority interrupt was blocking the UART interrupt from being serviced (due to a number of other issues). It turns out that I had been looking too closely at the UART registers, and not paid enough attention to the NVIC registers. Thanks for the idea!
-NickF