UART Problem with MK60F12

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

UART Problem with MK60F12

Jump to solution
1,951 Views
nicholasf
Contributor III

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. 

Labels (1)
0 Kudos
1 Solution
880 Views
mjbcswitzerland
Specialist V

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

View solution in original post

0 Kudos
3 Replies
880 Views
Rick_Li
NXP Employee
NXP Employee

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!

881 Views
mjbcswitzerland
Specialist V

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

0 Kudos
880 Views
nicholasf
Contributor III

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

0 Kudos