Help Setting Up UART0 Intterupt For MCU to PC Comm?

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

Help Setting Up UART0 Intterupt For MCU to PC Comm?

2,025 Views
Mamaro
Contributor II

Board: KL25Z
   I'm having trouble getting this example from my arm book to work. I'm supposed to setup UART0 and GPIOA, pins 1 and 2 to talk with OpenSDA which can communicate with my PC via Teraterm.

   All I know is that in the Init_UART0() function, after Port A pins 1 and 2 are set(lines 84 & 85) to Tx and Rx the UART0_IRQHandler() immediately gets called and then the program gets stuck on the if statement that checks the Receive Data Register(line 158) like it's an infinite loop. I haven't sent any characters from my PC...

Any idea why this is happening or tips on how I can fix it?

//================== Includes ======================
#include "MKL25Z4.h" // Device header
#include <stdio.h>

//=================== Defines ======================
#define UART_OVERSAMPLE_RATE (16)
#define SYS_CLOCK (48E6)
#define Q_MAX_SIZE (256)

//================= Structures ======================
typedef struct {
 uint8_t Data[Q_MAX_SIZE];
 unsigned int Head; //Index of the oldest data element
 unsigned int Tail; //Index of the next free space
 unsigned int Size; //Number of elements in use
} volatile Q_T;

//================== Globals ==========================
Q_T TxQ;
Q_T RxQ;

//================ Prototypes ===========================
void Init_UART0(uint32_t);

int     Q_Enqueue(Q_T*, uint8_t);
uint8_t Q_Dequeue(Q_T*         );
void    Q_Init   (Q_T*         );
int     Q_Empty  (Q_T*         );
int     Q_Full   (Q_T*         );
int     Q_Size   (Q_T*         );

//================== Entry Point ===============================
int main(){
 uint8_t buffer[80], myChar, * buffPtr;
 
 Init_UART0(115200);
 
 Q_Enqueue(&TxQ, 'a');
 
 while(1){
  //blocking recieve
  while(Q_Size(&RxQ) == 0); //Loops until there data in the queue
  
  myChar = Q_Dequeue(&RxQ);
  
  //Blocking transmit
  sprintf((char *)buffer, "You pressed %c\n\r",myChar);
  //enqueue string
  buffPtr = buffer;
  while(*buffPtr != '\0'){
  //Copy characters up to null terminator
   while(Q_Full(&TxQ)); //Wait for space to open up
   Q_Enqueue(&TxQ, *buffPtr);
   buffPtr++;
  }
  //Start transmitter if it isn's already running
  if(!(UART0->C2 & UART0_C2_TIE_MASK)){
      UART0->C2 |= UART0_C2_TIE(1);
  }
 }
}

//=================== Function Definitions =========================

// *********************************************
// Initiate and Setup UART and interrupts     *
// *********************************************
void Init_UART0(uint32_t baudRate){
 
 uint16_t sbr;
 
 //Enable clock gating for UART0 and PortA
 SIM->SCGC4 |= SIM_SCGC4_UART0_MASK;
 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
 
 //Make sure transmitter and receciver are disabled before init
 UART0->C2 &= ~UART0_C2_TE_MASK & ~UART0_C2_RE_MASK;
 
 //Set UART cloack to 48 MHz clock
 SIM->SOPT2 |= SIM_SOPT2_UART0SRC(1); //What is this source MCG?
 SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;
 
 //Set pins to UART0 Rx and Tx
 PORTA->PCR[1] = PORT_PCR_ISF_MASK | PORT_PCR_MUX(2); //Rx
 PORTA->PCR[2] = PORT_PCR_ISF_MASK | PORT_PCR_MUX(2); //Tx
 
 //================ Info on the registers can be found on pg.228 - 230 =====================
 /*Registers
  *UARTx_C1 - Control register 1
  *UARTx_C2 - Control register 2
  *UARTx_S1 - Status  register 1
  *
  *Acronyms
  *PF - Parity Error Flag
  *FE - Framing Error Flag
  *NF - Noise Detected Flag
  *TC - Transmition Complete Flag
  *OR - Rx buffer data not read before new data was recieved
  *TDRE - buffer has room for another character
  *RDRF - theres data to read from the recieve buffer
  *IDLE - data line is idle
 
  *TIE   - if(1) interrupt when transmit data register is empty
  *RIE   - if(1) interrupt when recieve data register is full
  *MSBF  - if(1) Most Significent Bits is sent first
  *RXINV - if(1) inverts recieved data
  *ORIE, NEIE, FEIE, PEIE - interrupt when corresponding flag is set
 */
 
 //Set baud rate and oversampling ratio
 sbr = (uint16_t)((SYS_CLOCK)/(baudRate * UART_OVERSAMPLE_RATE));
 UART0->BDH &= ~UART0_BDH_SBR_MASK;
 UART0->BDH |=  UART0_BDH_SBR(sbr>>8);
 UART0->BDL  =  UART0_BDL_SBR(sbr   );
 UART0->C4  |=  UART0_C4_OSR(UART_OVERSAMPLE_RATE - 1);
 
 //Disable interrupts for RX active edge and LIN break detect, select one stop bit
 UART0->BDH |= UART0_BDH_RXEDGIE(0) | UART0_BDH_SBNS(0) | UART0_BDH_LBKDIE(0);
 
 //Don't enable loopback mode, use 8 data bit mode, don't use parity
 UART0->C1 |= UART0_C1_LOOPS(0) | UART0_C1_M(0)    |UART_C1_PE(0);
 //Don't invert transmit data, do enable interrupts for errors
 UART0->C3 |= UART_C3_TXINV(0)  | UART0_C3_ORIE(1) | UART0_C3_NEIE(1)
           |  UART0_C3_FEIE(1)  | UART0_C3_PEIE(1);
 
 //Clear error flags
 UART0->S1 =  UART0_S1_OR(1) | UART0_S1_NF(1) | UART0_S1_FE(1) | UART0_S1_PF(1); 
 
 //Send LSB first, do not invert received data
 UART0->S2 |= UART0_S2_MSBF(0) | UART0_S2_RXINV(0);
 
 Q_Init(&TxQ);
 Q_Init(&RxQ);
 
 NVIC_SetPriority    (UART0_IRQn, 2); //0, 1, 2, or 3
 NVIC_ClearPendingIRQ(UART0_IRQn   );
 NVIC_EnableIRQ      (UART0_IRQn   );
 
 UART0->C2 |= UART0_C2_RIE(1);
 
 //Enable
 UART0->C2 |= UART0_C2_TE(1)   | UART_C2_RE(1);     
}
//*********************************************
// UART0 Interrupt Request Handler            *
//*********************************************
void UART0_IRQHandler(void){
 uint8_t myChar;
 
 if(UART0->S1 & (UART_S1_OR_MASK | UART_S1_NF_MASK |
                UART_S1_FE_MASK | UART_S1_PF_MASK)){
  //clear the error flags
  UART0->S1 |= UART0_S1_OR_MASK | UART0_S1_NF_MASK |
               UART0_S1_FE_MASK | UART0_S1_PF_MASK;
  //Read the data register to clear RDRF
  myChar = UART0->D;
 }
 if(UART0->S1 & UART0_S1_RDRF_MASK){
  //Recieved a character
  myChar = UART0->D;
  if(!Q_Full(&RxQ)){
   Q_Enqueue(&RxQ, myChar);
  }
  else{
   //error - queue full
   //discard character
  }
 }
 if((UART0->C2 & UART0_C2_TIE_MASK) &&
    (UART0->S1 & UART0_S1_TDRE_MASK)){
  //Can sen another character
  if(!Q_Empty(&TxQ)){
   UART0->D = Q_Dequeue(&TxQ);
  }
  else{
   //queue is empty so disable transmitter interrupt
   UART0->C2 &= ~UART0_C2_TIE_MASK;
  }
 }
}
//******************************************************************
// Initializes values in Transmit and Receive Queue Structures     *
//******************************************************************
void Q_Init(Q_T* queue){
 unsigned int i;
 
 for(i = 0; i < Q_MAX_SIZE; i++)
  queue->Data[i] = 0;
 
 queue->Head = 0;
 queue->Tail = 0;
 queue->Size = 0;
}
//*********************************************************
// Returns State and Info of a Queue Strucuture           *
//*********************************************************
int Q_Empty  (Q_T* queue){
 return queue->Size == 0;
}
int Q_Full   (Q_T* queue){
 return queue->Size == Q_MAX_SIZE;
}
int Q_Size   (Q_T* queue){
 return queue->Size;
}
//*****************************************************************
// Inserts data into the Queue and updates the Queue's members    *
//*****************************************************************
int Q_Enqueue(Q_T* queue, uint8_t data){
 uint32_t masking_state;
 
 //If queue is full, don't overwrite data, but do return an error code
 if(!Q_Full(queue)){
  queue->Data[queue->Tail++] = data;
  queue->Tail%= Q_MAX_SIZE;
  
  //Protect queue->Size++ operation from premption
  //Save current masking state
  masking_state = __get_PRIMASK();
  //Disable interrupts
  __disable_irq();
  //Update variable
  queue->Size++;
  //Restore interrupt masking state
  __set_PRIMASK(masking_state);
  
  return 1; //Success
 }else
  return 0; //Failure
}
//******************************************************************
// Extracts data from the Queue and updates the Queue's members    *
//******************************************************************
uint8_t Q_Dequeue(Q_T* queue){
 uint8_t masking_state;
 uint8_t transmition = 0;
 
 if(!Q_Empty(queue)){
  transmition = queue->Data[queue->Head];
  queue->Data[queue->Head++] = '_'; //Empty unused entries for debugging
  queue->Head %= Q_MAX_SIZE;
  
  //Protect queue->Size-- operation from preemption
  //Save current masking state
  masking_state = __get_PRIMASK();
  //Disable interrupts
  __disable_irq();
  //Update variable
  queue->Size;
  //Restore interrupt masking state
  __set_PRIMASK(masking_state);
 }
 return transmition;
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Labels (1)
0 Kudos
Reply
3 Replies

1,885 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi Miguel,

Please download the latest MCUXpresso SDK of FRDM-KL25Z and refer the uart_interrupt example.

uart_interrupt example.png

SDK_2.2.0_FRDM-KL25Z.png

Best Regards,

Robin

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

1,885 Views
Mamaro
Contributor II

Haha Thanks. Wait, what was my question again?

0 Kudos
Reply

1,886 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Have you check the waveform on UART pins by using oscilloscope?

I am not able to gets stuck on line 158.

Are you using FRDM-KL25Z board?

Best Regards,

Robin

0 Kudos
Reply