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!
Hi Alex
1)
while ( (UART2_S1 & UART_S1_TDRE_MASK) == 0 );
looks OK so there is probably a different reason for it not operating as expected.
Note that if you use Tx interrupts this method is very inefficient - you should instead use a Tx buffer and send each subsequent character in the interrupt so that your code doesn't block.
2)
Check how ICS_S is defined in the header file - if it is a const register it won't let you write to it, which would not be exactly correct because one can write a '1' to clear the loss bit.
Also check that you are clearing the correct bit since ICS_S_LOCK_MASK looks incorrect to me - I think you will find you need to write a bit called LOLS instead.
Not doing this will generally not be a problem because it is unlikely that the flag will be set. Also, if it remains set it doesn't make any difference if you are not checking it elsewhere.
3)
I don't see that the UART Tx interrupt is enabled anywhere and so it may be normal that the interrupt callback is thus never called.
See links below for a complete Open Source solution for KEA64 including buffered UART method and (approx.) real-time simulation of KEA64 in Visual Studio.
Regards
Mark
Kinetis: http://www.utasker.com/kinetis.html
Kinetis KEA64:
- http://www.utasker.com/kinetis/FRDM-KEAZ64Q64.html
- http://www.utasker.com/kinetis/TRK-KEA64.html
S32 Design Studio: http://www.utasker.com/kinetis/compilers.html#S32
UART: http://www.utasker.com/docs/uTasker/uTaskerUART.PDF
UART videos:
- https://youtu.be/OrqSn9x7N1E
- https://youtu.be/GaoWE-tMRq4
- https://youtu.be/89sZ4nW-mgw
Free Open Source solution: https://github.com/uTasker/uTasker-Kinetis
Working project in 15 minutes video: https://youtu.be/K8ScSgpgQ6M
For better, faster, cheaper product developments consider the uTasker developer's version, professional Kinetis support, one-on-one training and complete fast-track project solutions to set you apart from the herd : http://www.utasker.com/support.html