Hi,
I am using TWRK21 120M board, wanted to test uart5 with all settings for baudrate 115200 with bus clock of 60MHz. I am unable to receive and transmit the data. Kindly guide through this.
Thanks & Regards,
Mallikarjuna
Hello Mallikarjuna,
Could you please post what you configured to see why you are unable to receive and transmit data?
Regards,
Earl.
Hello Earl,
Thanks for your reply.
This is to be replied on freescale community in our post:
Below is the configuration for UART5 for TWR-K21 120Mhz:
Enabled the clock for uart 5;
SIM_SCGC1 |= SIM_SCGC1_UART5_MASK
Disabled the TE and RE register
UART_C2_REG(uartch) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );
Cleared the C1 register
UART_C1_REG(UART5_BASE_PTR) = 0
/* Calculate baud settings */
sysclk = 60000;
sbr = (uint16)((sysclk*1000)/(baud * 16)); // sysclk set to 60Mhz; baud set to 115200 and 9600.
As mentioned in reference manual, UART5 uses bus clock of 60Mhz.
/* Save off the current value of the UART5_BDH except for the SBR field */
temp = UART_BDH_REG(UART5_BASE_PTR) & ~(UART_BDH_SBR(0x1F));
UART_BDH_REG(UART5_BASE_PTR) = temp | UART_BDH_SBR(((sbr & 0x1F00) >> 8));
UART_BDL_REG(UART5_BASE_PTR) = (uint8)(sbr & UART_BDL_SBR_MASK);
/* Determine if a fractional divider is needed to get closer to the baud rate */
brfa = (((sysclk*32000)/(baud * 16)) - (sbr * 32));
/* Save off the current value of the UARTx_C4 register except for the BRFA field */
temp = UART_C4_REG(UART5_BASE_PTR) & ~(UART_C4_BRFA(0x1F));
UART_C4_REG(UART5_BASE_PTR) = temp | UART_C4_BRFA(brfa);
/* Enable receiver and transmitter */
UART_C2_REG(uartch) |= (UART_C2_TE_MASK
| UART_C2_RE_MASK );
After these settings, I was not getting any output on the screen.
Then I enabled the PORTD clock too as UART5 is a multiplexed function with PORTD.
After enabling port D's clock, I started getting the junk data.
Kindly let me know which point I am missing.
With Regards,
Mallikarjuna Reddy
Dear Earl,
Thanks for your reply.
Below is the configuration for UART5 for TWR-K21 120Mhz:
Enabled the clock for uart 5;
SIM_SCGC1 |= SIM_SCGC1_UART5_MASK
Disabled the TE and RE register
UART_C2_REG(uartch) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );
Cleared the C1 register
UART_C1_REG(UART5_BASE_PTR) = 0
/* Calculate baud settings */
sysclk = 60000;
sbr = (uint16)((sysclk*1000)/(baud * 16)); // sysclk set to 60Mhz; baud set to 115200 and 9600.
As mentioned in reference manual, UART5 uses bus clock of 60Mhz.
/* Save off the current value of the UART5_BDH except for the SBR field */
temp = UART_BDH_REG(UART5_BASE_PTR) & ~(UART_BDH_SBR(0x1F));
UART_BDH_REG(UART5_BASE_PTR) = temp | UART_BDH_SBR(((sbr & 0x1F00) >> 8));
UART_BDL_REG(UART5_BASE_PTR) = (uint8)(sbr & UART_BDL_SBR_MASK);
/* Determine if a fractional divider is needed to get closer to the baud rate */
brfa = (((sysclk*32000)/(baud * 16)) - (sbr * 32));
/* Save off the current value of the UARTx_C4 register except for the BRFA field */
temp = UART_C4_REG(UART5_BASE_PTR) & ~(UART_C4_BRFA(0x1F));
UART_C4_REG(UART5_BASE_PTR) = temp | UART_C4_BRFA(brfa);
/* Enable receiver and transmitter */
UART_C2_REG(uartch) |= (UART_C2_TE_MASK
| UART_C2_RE_MASK );
After these settings, I was not getting any output on the screen.
Then I enabled the PORTD clock too as UART5 is a multiplexed function with PORTD.
After enabling port D's clock, I started getting the junk data.
Kindly let me know which point I am missing.
Thanks & Regards,
Mallikarjuna Reddy
@@@@@@@@Hi Earl,
Below is the configuration for UART5 for TWR-K21 120Mhz:
Enabled the clock for uart 5;
SIM_SCGC1 |= SIM_SCGC1_UART5_MASK
Disabled the TE and RE register
UART_C2_REG(uartch) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );
Cleared the C1 register
UART_C1_REG(UART5_BASE_PTR) = 0
/* Calculate baud settings */
sysclk = 60000;
sbr = (uint16)((sysclk*1000)/(baud * 16)); // sysclk set to 60Mhz; baud set to 115200 and 9600.
As mentioned in reference manual, UART5 uses bus clock of 60Mhz.
/* Save off the current value of the UART5_BDH except for the SBR field */
temp = UART_BDH_REG(UART5_BASE_PTR) & ~(UART_BDH_SBR(0x1F));
UART_BDH_REG(UART5_BASE_PTR) = temp | UART_BDH_SBR(((sbr & 0x1F00) >> 8));
UART_BDL_REG(UART5_BASE_PTR) = (uint8)(sbr & UART_BDL_SBR_MASK);
/* Determine if a fractional divider is needed to get closer to the baud rate */
brfa = (((sysclk*32000)/(baud * 16)) - (sbr * 32));
/* Save off the current value of the UARTx_C4 register except for the BRFA field */
temp = UART_C4_REG(UART5_BASE_PTR) & ~(UART_C4_BRFA(0x1F));
UART_C4_REG(UART5_BASE_PTR) = temp | UART_C4_BRFA(brfa);
/* Enable receiver and transmitter */
UART_C2_REG(uartch) |= (UART_C2_TE_MASK
| UART_C2_RE_MASK );
After these settings, I was not getting any output on the screen.
Then I enabled the PORTD clock too as UART5 is a multiplexed function with PORTD.
After enabling port D's clock, I started getting the junk data.
Kindly let me know which point I am missing.
Thanks
Hello again,
Please be sure that your bus clock is at 60 MHz. The code below sets the bus clock at this frequency (it was generated by PEx).
void init_hardware()
{
/* Disable the WDOG module */
/* WDOG_UNLOCK: WDOGUNLOCK=0xC520 */
WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xC520); /* Key 1 */
/* WDOG_UNLOCK: WDOGUNLOCK=0xD928 */
WDOG_UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xD928); /* Key 2 */
/* WDOG_STCTRLH: ??=0,DISTESTWDOG=0,BYTESEL=0,TESTSEL=0,TESTWDOG=0,??=0,??=1,WAITEN=1,STOPEN=1,DBGEN=0,ALLOWUPDATE=1,WINEN=0,IRQRSTEN=0,CLKsrc=1,WDOGEN=0 */
WDOG_STCTRLH = WDOG_STCTRLH_BYTESEL(0x00) |
WDOG_STCTRLH_WAITEN_MASK |
WDOG_STCTRLH_STOPEN_MASK |
WDOG_STCTRLH_ALLOWUPDATE_MASK |
WDOG_STCTRLH_CLKSRC_MASK |
0x0100U;
/* System clock initialization */
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=3,OUTDIV4=3,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) |
SIM_CLKDIV1_OUTDIV2(0x01) |
SIM_CLKDIV1_OUTDIV3(0x03) |
SIM_CLKDIV1_OUTDIV4(0x03); /* Set the system prescalers to safe value */
/* SIM_SCGC5: PORTA=1 */
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; /* Enable clock gate for ports to enable pin routing */
if ((PMC_REGSC & PMC_REGSC_ACKISO_MASK) != 0x0U)
{
/* PMC_REGSC: ACKISO=1 */
PMC_REGSC |= PMC_REGSC_ACKISO_MASK; /* Release IO pads after wakeup from VLLS mode. */
}
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=0,OUTDIV3=1,OUTDIV4=3,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0x00) |
SIM_CLKDIV1_OUTDIV2(0x00) |
SIM_CLKDIV1_OUTDIV3(0x01) |
SIM_CLKDIV1_OUTDIV4(0x03); /* Update system prescalers */
/* SIM_SOPT2: PLLFLLSEL=0 */
SIM_SOPT2 &= (uint32_t)~(uint32_t)(SIM_SOPT2_PLLFLLSEL_MASK); /* Select FLL as a clock source for various peripherals */
/* SIM_SOPT1: OSC32KSEL=3 */
SIM_SOPT1 |= SIM_SOPT1_OSC32KSEL(0x03); /* LPO 1kHz oscillator drives 32 kHz clock for various peripherals */
/* Switch to FEI Mode */
/* MCG_C1: CLKS=0,FRDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */
MCG_C1 = MCG_C1_CLKS(0x00) |
MCG_C1_FRDIV(0x00) |
MCG_C1_IREFS_MASK |
MCG_C1_IRCLKEN_MASK;
/* MCG_C2: LOCRE0=0,??=0,RANGE0=0,HGO0=0,EREFS0=0,LP=0,IRCS=0 */
MCG_C2 = MCG_C2_RANGE0(0x00);
/* MCG_C4: DMX32=0,DRST_DRS=2 */
MCG_C4 = (uint8_t)((MCG_C4 & (uint8_t)~(uint8_t)(
MCG_C4_DMX32_MASK |
MCG_C4_DRST_DRS(0x01)
)) | (uint8_t)(
MCG_C4_DRST_DRS(0x02)
));
/* OSC_CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
OSC_CR = OSC_CR_ERCLKEN_MASK;
/* MCG_C7: OSCSEL=0 */
MCG_C7 &= (uint8_t)~(uint8_t)(MCG_C7_OSCSEL_MASK);
/* MCG_C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=0 */
MCG_C5 = MCG_C5_PRDIV0(0x00);
/* MCG_C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0 */
MCG_C6 = MCG_C6_VDIV0(0x00);
while((MCG_S & MCG_S_IREFST_MASK) == 0x00U); /* Check that the source of the FLL reference clock is the internal reference clock. */
while((MCG_S & 0x0CU) != 0x00U); /* Wait until output of the FLL is selected */
}
Also, I wrote the code below which initializes the UART5 for the K21 MCU with interrupts.
static uint8_t* dataToSend;
static uint8_t* dataToReceive;
static uint8_t amountOfBytesToSend;
void UART5_Init()
{
//Enabled the clock gate for UART5.
SIM_SCGC1 |= SIM_SCGC1_UART5_MASK;
//Enabled the clock gate for port D.
SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;
// PORTD_PCR8: ISF=0,MUX=3.
PORTD_PCR8 = ((PORTD_PCR8 & ~(PORT_PCR_ISF_MASK | PORT_PCR_MUX_MASK)) | PORT_PCR_MUX(0x03));
// PORTD_PCR9: ISF=0,MUX=3.
PORTD_PCR9 = ((PORTD_PCR9 & ~(PORT_PCR_ISF_MASK | PORT_PCR_MUX_MASK)) | PORT_PCR_MUX(0x03));
//Disable the TE and RE register.
UART_C2_REG(UART5_BASE_PTR) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK);
//Clear the C1 register.
UART_C1_REG(UART5_BASE_PTR) = 0;
// Calculate baud settings.
uint32_t sysclk = 60000000; //Bus clock.
uint32_t baud = 115200; //Baudrate.
uint32_t sbr = sysclk / (baud * 16);
// Save off the current value of the UART5_BDH except for the SBR field.
uint32_t temp = UART_BDH_REG(UART5_BASE_PTR) & ~(UART_BDH_SBR(0x1F));
UART_BDH_REG(UART5_BASE_PTR) = temp | UART_BDH_SBR(((sbr & 0x1F00) >> 8));
UART_BDL_REG(UART5_BASE_PTR) = (uint8_t)(sbr & UART_BDL_SBR_MASK);
// Determine if a fractional divider is needed to get closer to the baud rate.
uint32_t brfa = (((sysclk*32000)/(baud * 16)) - (sbr * 32));
// Save off the current value of the UARTx_C4 register except for the BRFA field.
temp = UART_C4_REG(UART5_BASE_PTR) & ~(UART_C4_BRFA(0x1F));
UART_C4_REG(UART5_BASE_PTR) = temp | UART_C4_BRFA(brfa);
// Enable the receiver, the transmitter and the interrupts.
UART_C2_REG(UART5_BASE_PTR) |= (/*UART_C2_TCIE_MASK | UART_C2_RIE_MASK |*/ UART_C2_TE_MASK | UART_C2_RE_MASK);
//Enable the interrupts.
NVIC_ICPR(INT_UART5_RX_TX / 32) = (1 << ((INT_UART5_RX_TX - 16) % 32)); //Clear all the pending events
NVIC_ISER(INT_UART5_RX_TX / 32) = (1 << ((INT_UART5_RX_TX - 16) % 32)); //Enables External Interrupt for UART0
}
void UART5_Send(uint8_t* data, uint8_t bytesAmount)
{
amountOfBytesToSend = bytesAmount;
dataToSend = data;
UART5_D = *dataToSend;
UART5_C2 |= UART_C2_TCIE_MASK; //Enable interrupt when the transmission is completed.
}
void UART5_Receive(uint8_t* data)
{
dataToReceive = data;
UART5_C2 |= UART_C2_RIE_MASK; //Enable interrupt when data has been received.
}
void UART5_Status_IRQHandler()
{
if (UART5_S1 & UART_S1_RDRF_MASK) //If the interrupt is caused by a reception.
{
*dataToReceive++ = UART5_D; //Read the data.
}
else if (UART5_S1 & UART_S1_TC_MASK) //If the interrupt is caused by a transmission.
{
if(amountOfBytesToSend--) //If there is data to send, send more data.
{
UART5_D = *dataToSend++;
}
else
{
UART5_C2 &= ~UART_C2_TCIE_MASK;
}
}
}
In CodeWarrior the UART5 ISR is not enabled by default for this MCU, to enable it you have to follow the next steps:
1. Open the archive "Project_Settings/Startup_Code/kinetis_sysinit.c"
2. In the functions array the fields 84 and 85 are 0's, you need to replace it for the functions:
UART5_Status_IRQHandler
UART5_ERR_IRQHandler
3. Declare the function prototype by copying the next two lines in this archive.
void UART5_Status_IRQHandler() __attribute__ ((weak, alias("Default_Handler")));
void UART5_ERR_IRQHandler() __attribute__ ((weak, alias("Default_Handler")));
I hope this helps. I remain at your service.
Regards,
Earl Orlando Ramírez-Sánchez.
/* If this post answers your question, please click the Correct Answer button. */