AnsweredAssumed Answered

KEA64 - Low Level UART Setting up

Question asked by Alex C. on Apr 12, 2018
Latest reply on Apr 12, 2018 by Mark Butcher

Hello!

 

I am trying to make a simple UART Echo application for a processor from family SKEAZN64. I simply want to get back any character send from a terminal via serial port.

 

My code consists of the following three files:

 

1. main.c

#include <stdint.h>
#include "SKEAZN642.h"
#include "UART.h"

/// Configure clock
void Clk_Init()
{
     ICS_C1 |= ICS_C1_IRCLKEN_MASK;                /* Enable the internal reference clock*/
     ICS_C3 = 0x50;                                    /* Reference clock frequency = 31.25 kHz*/
     while ( !(ICS_S & ICS_S_LOCK_MASK) );     /* Wait for PLL lock, now running at 40 MHz (1024*39.0625 kHz) */
     ICS_C2 |= ICS_C2_BDIV( 1 );                /*BDIV=2, Bus clock = 20 MHz*/
     //ICS_S |= ICS_S_LOCK_MASK;                     /* Clear Loss of lock sticky bit */ ????????
     //???
}

/// UART2 Callback Handler
void Uart_Interrupt(uint8_t data)
{
     // Print back received character
     Uart_SendChar( data );
}

int main(void)
{
     /// Clock initialization
     Clk_Init(); /* Configure clocks to run at 20 Mhz */

     /// UART2 Initialization
     UART_Init();                                   /*Initialize Uart2 at 9600 bauds */
     Uart_SetCallback( Uart_Interrupt );      /* Set the callback function that the UART driver will call when receiving a char */
     NVIC_EnableIRQ( UART2_IRQn );                /* Enable UART2 interrupt */

     // Send "WELCOME\r\n"
     Uart_SendChar( 0x57 );     // W
     Uart_SendChar( 0x45 );     // E
     Uart_SendChar( 0x4c );     // L
     Uart_SendChar( 0x43 );     // C
     Uart_SendChar( 0x4f );     // O
     Uart_SendChar( 0x4d );     // M
     Uart_SendChar( 0x45 );     // E
     Uart_SendChar( 0xD );     //\r
     Uart_SendChar( 0xA );     //\n

     for ( ;; )
     {
          static int i = 0;
          i++;
     }

     /* Never leave main */
     return 0;
}

 

2. UART.h

#ifndef UART_H_
#define UART_H_

#include <stdint.h>
#include "SKEAZN642.h"

/*******************************************************************************
* Types
********************************************************************************/

typedef void(*pt2Func)(void);            /* Pointer to Functions, void argument */
typedef void(*pt2FuncU8)(uint8_t);       /* Pointer to Functions, UINT8 argument */

void UART_Init(void);
void Uart_SendChar(uint8_t send);
uint8_t Uart_GetChar(void);
void Uart_SetCallback(pt2FuncU8 ptr);

#endif /* UART_H_ */

 

3. UART.c

/// Global Variable
pt2FuncU8 Uart_Callback;

/// Local function prototype
void UART2_IRQHandler(void);

void UART_Init()
{
     SIM_SCGC |= SIM_SCGC_UART2_MASK;      /* Enable bus clock in UART2*/
     UART2_BDH = 0;                               /* One stop bit*/
     UART2_BDL = 128;                          /* Baud rate at 9600*/
     UART2_C1 = 0;                               /* No parity enable,8 bit format*/
     UART2_C2 |= UART_C2_TE_MASK;           /* Enable Transmitter*/
     UART2_C2 |= UART_C2_RE_MASK;           /* Enable Receiver*/
     UART2_C2 |= UART_C2_RIE_MASK;           /* Enable Receiver interrupts*/
}

void Uart_SetCallback(pt2FuncU8 ptr)
{
     Uart_Callback = ptr;
}

void Uart_SendChar(uint8_t send)
{
     while ( (UART2_S1 & UART_S1_TDRE_MASK) == 0 )
          ;                     /* Wait for transmit buffer to be empty*/

     (void)UART2_S1;      /* Read UART2_S1 register*/
     UART2_D = send;      /* Send data*/
}

uint8_t Uart_GetChar()
{
     uint8_t recieve;
     while ( ( UART2_S1 & UART_S1_RDRF_MASK) == 0 )
          ;                          /* Wait for received buffer to be full*/

     (void) UART2_S1;           /* Read UART2_S1 register*/
     recieve = UART2_D;           /* Read received data*/
     return recieve;
}

void UART2_IRQHandler()
{
     (void)UART2_S1; /* Clear reception flag mechanism*/
     Uart_Callback( Uart_GetChar() );
}

 

Now the code have some big problems:

 

1. Instead of sending initially "WELCOME\r\n" it just send "WEL_and_some_garbage". My guess is that it is not waiting for transmission buffer to be empty! But why not?

This is the loop which should block execution until another char can be send:

while (  (UART2_S1 & UART_S1_TDRE_MASK) == 0  );

But what's wrong with it?

 

2. The clock initialization

The function was extracted from official documentation AN4942:

void Clk_Init()
{
    ICS_C1 |= ICS_C1_IRCLKEN_MASK;             /* Enable the internal reference clock*/
    ICS_C3 = 0x50;                             /* Reference clock frequency = 31.25 kHz*/
    while ( !(ICS_S & ICS_S_LOCK_MASK) );    /* Wait for PLL lock, now running at 40 MHz (1024*39.0625 kHz) */
    ICS_C2 |= ICS_C2_BDIV( 1 );             /*BDIV=2, Bus clock = 20 MHz*/
    //ICS_S |= ICS_S_LOCK_MASK;                 /* Clear Loss of lock sticky bit */ ????????
    //???
}

 

However, there is an error on the last commented line: error: assignment of read-only member 'S'

Have no clue why so I just commented that line!

 

3. The callback function is not called when a character is send from UART0.

 

PS: The UART2 port works fine with processor Expert.

PS2: Most of the code is from: https://www.nxp.com/docs/en/application-note/AN4942.pdf 

 

I also have attached the project archive in case you may want to give a try!

Attachments

Outcomes