📄 uart_if.c
字号:
/*
================================================================================
* @file UART_IF.c
* @brief UART interface module
* @author 2006/03/29 Michiru Kagaya
* Copyright (C)SEIKO EPSON Corp. All Rights Reserved.
================================================================================
*/
//=================================
// Include files
//=================================
#include <string.h>
#include "UART_UserConfig.h"
#include "UART_IF.h"
#ifdef TOYA2_C
#include "reg_mx21.h"
#endif // TOYA2_C
//=================================
// enum declaration
//=================================
// Data transmission state
//---------------------------------
enum {
STATE_READY,
STATE_EXEC,
};
//=================================
// Structure declaration
//=================================
// Transmission information structure
//---------------------------------
typedef struct tagIF_TX_INFO {
unsigned char STATE;
unsigned short wTxSize;
UART_IF_CALLBACK pfnCallback;
}IF_TX_INFO, *PIF_TX_INFO;
// Reception information structure
//---------------------------------
typedef struct tagRX_INFO {
unsigned char STATE;
UART_IF_CALLBACK pfnCallback;
UART_IF_CALLBACK pfnRcvdCallback;
}IF_RX_INFO, *PIF_RX_INFO;
// Module management struture
//---------------------------------
typedef struct tagIF_MODULE_INFO {
IF_RX_INFO sRxInfo[MAX_UART_CHANNEL];
IF_TX_INFO sTxInfo[MAX_UART_CHANNEL];
}IF_MODULE_INFO, *PIF_MODULE_INFO;
//=================================
// Variables declaration
//=================================
static IF_MODULE_INFO sModuleSts;
/*
* UART1 - 4 control register operation table
*/
#ifdef TOYA2_C
static volatile unsigned long* regUCR1[] = {
&rlMX21_UCR1_1,
// &rlMX21_UCR1_2,
// &rlMX21_UCR1_3,
// &rlMX21_UCR1_4
} ;
static volatile unsigned long* regUCR2[] = {
&rlMX21_UCR2_1,
// &rlMX21_UCR2_2,
// &rlMX21_UCR2_3,
// &rlMX21_UCR2_4
} ;
static volatile unsigned long* regUCR3[] = {
&rlMX21_UCR3_1,
// &rlMX21_UCR3_2,
// &rlMX21_UCR3_3,
// &rlMX21_UCR3_4
} ;
static volatile unsigned long* regUCR4[] = {
&rlMX21_UCR4_1,
// &rlMX21_UCR4_2,
// &rlMX21_UCR4_3,
// &rlMX21_UCR4_4
} ;
static volatile unsigned long* regUFCR[] = {
&rlMX21_UFCR_1,
// &rlMX21_UFCR_2,
// &rlMX21_UFCR_3,
// &rlMX21_UFCR_4,
};
static volatile unsigned long* regURXD[] = {
&rlMX21_URXD_1,
// &rlMX21_URXD_2,
// &rlMX21_URXD_3,
// &rlMX21_URXD_4,
};
static volatile unsigned long* regUTXD[] = {
&rlMX21_UTXD_1,
// &rlMX21_UTXD_2,
// &rlMX21_UTXD_3,
// &rlMX21_UTXD_4,
};
static volatile unsigned long* regUBIR[] = {
&rlMX21_UBIR_1,
// &rlMX21_UBIR_2,
// &rlMX21_UBIR_3,
// &rlMX21_UBIR_4
};
static volatile unsigned long* regUBMR[] = {
&rlMX21_UBMR_1,
// &rlMX21_UBMR_2,
// &rlMX21_UBMR_3,
// &rlMX21_UBMR_4
};
static volatile unsigned long* regUSR1[] = {
&rlMX21_USR1_1,
// &rlMX21_USR1_2,
// &rlMX21_USR1_3,
// &rlMX21_USR1_4
};
static volatile unsigned long* regUSR2[] = {
&rlMX21_USR2_1,
// &rlMX21_USR2_2,
// &rlMX21_USR2_3,
// &rlMX21_USR2_4
};
static volatile unsigned long* regUTS[] = {
&rlMX21_UTS_1,
// &rlMX21_UTS_2,
// &rlMX21_UTS_3,
// &rlMX21_UTS_4
};
#endif // TOYA2
//=================================
// Prototype declaration
//=================================
static void RxInterrupt( unsigned char bChannel );
static void TxInterrupt( unsigned char bChannel );
short UART_IFInit( void )
{
/* Set the common pin */
#ifdef TOYA2_C
/* UART1: PTE12-15 */
rlMX21_PTE_GUIS &= ~(0x0000F000) ;
rlMX21_PTE_GPR &= ~(0x0000F000) ;
/* Set clock */
rlMX21_PCCR0 |= 0x00000001; /* UART1 CLK Enable: TOYA2 RS232C board */
rlMX21_PCCR0 &= ~0x00000002; /* UART2 CLK Disable:Disconnect in default */
rlMX21_PCCR0 &= ~0x00000004; /* UART3 CLK Disable:Disconnect in default */
rlMX21_PCCR0 &= ~0x00000008; /* UART4 CLK Disable:Disconnect in default */
#endif // TOYA2
return STATUS_SUCCESS;
}
/*
--------------------------------------------------------------------------------
* UART_IFOpen
* @brief Open this module
* @param const PUART_IF_PARAM psParam : Setting information
* UART_IF_CALLBACK pfnRcvdCallback : Reception callback register
* @retval unsigned short
* STATUS_SUCCESS : Complete normally
* STATUS_INVALID_PARAMETER: Parameter error
--------------------------------------------------------------------------------
*/
short UART_IFOpen( const PUART_IF_PARAM psParam, UART_IF_CALLBACK pfnRcvdCallback )
{
unsigned char index;
#ifdef TOYA2_C
unsigned long baudrate = 0; // Baud rate
unsigned long wkUFCR; /* Work variable used for setting register */
unsigned long txTrg = 2; // Transmitter Trigger Level setting value (2-32)
unsigned long rxTrg = 1; // Receiver Trigger Level setting value (1-32)
unsigned long divider; // ulDivider: Setting of dividing frequency value of input clock(1-7)
unsigned long dcmMode = 0; // DCE/DTE setting (0: DCE mode , 1:DTE mode)
const unsigned long regval[] = { 0, 5, 4, 3, 2, 1, 0, 6 };
#endif // TOYA2_C
// Check parameter
if( psParam == NULL || pfnRcvdCallback == NULL
|| psParam->bChannel == 0 || (psParam->bChannel > MAX_UART_CHANNEL) ){
return STATUS_INVALID_PARAMETER;
}
index = psParam->bChannel-1;
#ifdef TOYA2_C
// Configure information
*regUCR1[index] = 0x00000000;
*regUCR2[index] = 0x00007021;
*regUCR3[index] = 0x00000004;
*regUCR4[index] = 0x00000000;
// FIFO setting
txTrg = 2;
rxTrg = 1;
wkUFCR = *regUFCR[index] ; /* Get current value */
wkUFCR &= ~0x0000FC3F; /* Clear TXTL,RXTL */
wkUFCR |= ((txTrg<<10) | (rxTrg<<0)) ; /* Reflect the setting value */
// UART Clock Divider Set
divider = 1;
wkUFCR = *regUFCR[index] ; /* Get current value */
wkUFCR &= ~0x00000380; /* Clear RFDIV */
wkUFCR |= (regval[divider]<<7); /* Reflect the setting value */
*regUFCR[index] = wkUFCR ; /* Set register */
// DCE mode
wkUFCR = *regUFCR[index]; /* Get current value */
wkUFCR &= ~0x00000040; /* Clear the value of RFDIV */
wkUFCR |= (dcmMode<<6); /* Reflect the setting value */
*regUFCR[index] = wkUFCR; /* Set register */
// Set baud rate
switch( psParam->bBaudRate ){
case UART_FUNC_BRATE_9600: baudrate = 9600; break;
case UART_FUNC_BRATE_19200: baudrate = 19200; break;
case UART_FUNC_BRATE_38400: baudrate = 38400; break;
case UART_FUNC_BRATE_57600: baudrate = 57600; break;
case UART_FUNC_BRATE_115200: baudrate = 115200; break;
case UART_FUNC_BRATE_234000: baudrate = 234000; break;
case UART_FUNC_BRATE_468000: baudrate = 468000; break;
case UART_FUNC_BRATE_921600: baudrate = 921600; break;
default:
break;
}
*regUBIR[index] = (baudrate/100) -1; /* NUM: Baudrate/100 -1*/
*regUBMR[index] = 0x270F; /* NUM: Baudrate/100 -1*/
*regUCR1[index] |= 0x01; /* UARTEN Bit Enable */
*regUCR2[index] |= 0x06; /* TXEN, RXEN bit Enable */
#endif // TOYA2_C
// Initialize the management variables
memset( &sModuleSts, 0x00, sizeof(sModuleSts) );
sModuleSts.sRxInfo[index].pfnRcvdCallback = pfnRcvdCallback; // Register the data reception callback
#ifdef TOYA2_C
// Enable the interrupt
*regUCR3[index] |= ((1<<12)|(1<<11)); //
*regUCR4[index] |= (1<<1); // Enable Receiver Overrun Int
*regUCR4[index] |= (1<<2); // Enable BRAK Condition Detect
wkUFCR = *regUFCR[index];
wkUFCR &= ~0x0000FC3F; /* Clear TXTL and RXTL */
wkUFCR |= 0x00000801; // FIFO 1byte Input Interrupt
*regUFCR[index] = wkUFCR;
*regUCR1[index] |= (1<<9); // Enable Receiver Ready Int
*regUCR1[index] |= (1<<0); // UART Enable
#endif // TOYA2_C
return STATUS_SUCCESS;
}
/*
--------------------------------------------------------------------------------
* UART_IFClose
* @brief Close this module
* @param unsigned char bChannel : the channel to close
* @retval unsigned short
* STATUS_SUCCESS : complete normally
--------------------------------------------------------------------------------
*/
short UART_IFClose( unsigned char bChannel )
{
unsigned char index = bChannel - 1;
// check parameter
if( bChannel == 0 || (bChannel > MAX_UART_CHANNEL) ){
return STATUS_INVALID_PARAMETER;
}
sModuleSts.sRxInfo[index].pfnRcvdCallback = NULL; // Register the data reception callback
// Stop here because the hardware is stopped
//--------------------------------------
;
return STATUS_SUCCESS;
}
/*
--------------------------------------------------------------------------------
* UART_IFReadData
* @brief read the data from FIFO
* @param unsigned char bChannel : The channel to use
* unsigned short wSize : The size of read
* unsigned char* pData : Set address
* unsigned short* wActSize : The size actually read
* @retval unsigned short
* STATUS_SUCCESS : Complete normally
* STATUS_UNSUCCESSFUL : complete with error
--------------------------------------------------------------------------------
*/
short UART_IFReadData( unsigned char bChannel, unsigned short wSize, unsigned char* pData, unsigned short* wActSize )
{
unsigned char index = bChannel - 1;
unsigned short wCnt;
#ifdef TOYA2_C
unsigned long dwRxData;
unsigned long dwSts;
#endif // TOYA2_C
if( wActSize != NULL ){
*wActSize = 0; // Intialize the read number
}
#ifdef TOYA2_C
// Check if FIFO is empty
dwSts = *regUTS[index];
if( dwSts & (1<<5) ){
return UART_IF_RXFIFO_EMPTY;
}
#endif // TOYA2_C
// Read data
//--------------------------------
for( wCnt = 0; wCnt < wSize; wCnt++ ){
#ifdef TOYA2_C
dwRxData = *regURXD[index];
// Check if FIFO is empty
if( (dwRxData& 0x00008000) == 0 ){
// Detect the invalid data
break;
}
*pData = (unsigned char)(dwRxData&0x000000FF); /* Save the read data */
#endif // TOYA2_C
pData++;
}
if( wActSize != NULL ){
*wActSize = wCnt; // Set the actually read data number
}
return STATUS_SUCCESS;
}
/*
--------------------------------------------------------------------------------
* UART_IFWriteData
* @brief Write data to FIFO
* @param unsigned char bChannel : The channel to use
* unsigned short wSize : The size to read
* unsigned char* pData : Set address
* UART_IF_CALLBACK pfnCallback : Function that does transmission completion notification
* @retval unsigned short
* STATUS_SUCCESS : Complet normally
* STATUS_UNSUCCESSFUL : Comp[lete with error
--------------------------------------------------------------------------------
*/
short UART_IFWriteData( unsigned char bChannel, unsigned short wSize, unsigned char* pData, UART_IF_CALLBACK pfnCallback )
{
unsigned char index;
unsigned short wCnt;
// Check if it is enable to transmit
index = bChannel-1;
#ifdef TOYA2_C
if( 0 == (*regUSR1[index] & (1<<13)) )
{
return UART_IF_STATUS_TX_NOT_READY;
}
#endif // TOYA2_C
for( wCnt = 0; wCnt < wSize; wCnt++ ){
#ifdef TOYA2_C
// Check if the TxFIFO is FULL
if( *regUTS[index] & 0x00000010 ){
break;
}
*regUTXD[index] = *pData;
#endif // TOYA2_C
pData++;
}
sModuleSts.sTxInfo[index].wTxSize = wCnt; // Number set to FIFO
sModuleSts.sTxInfo[index].STATE = STATE_EXEC; // Set to waiting for completion of transmission
sModuleSts.sTxInfo[index].pfnCallback = pfnCallback; //
#ifdef TOYA2_C
// Enable the FIFO Empty interrupt
*regUCR1[index] |= (1<<6);
#endif // TOYA2_C
return STATUS_SUCCESS;
}
/*
--------------------------------------------------------------------------------
* UART_IF_Interrupt
* @brief UART interrupt main process
* @param none
* @retval none
--------------------------------------------------------------------------------
*/
void UART_IF_Interrupt( void )
{
RxInterrupt( 1 );
TxInterrupt( 1 );
}
/*
--------------------------------------------------------------------------------
* RxInterrupt
* @brief reception interrupt p
* @param unsigned char bChannel
* @retval none
--------------------------------------------------------------------------------
*/
static void RxInterrupt( unsigned char bChannel )
{
#ifdef TOYA2_C
unsigned char index = bChannel - 1;
unsigned long status;
status = *regUSR2[index];
if( status & 0x00000001 ){
// receive data before UART_IF_ReadData is called.
sModuleSts.sRxInfo[index].pfnRcvdCallback( UART_IF_RCVD_DATA, STATUS_SUCCESS, &bChannel );
}
#endif // TOYA2_C
return;
}
/*
--------------------------------------------------------------------------------
* TxInterrupt
* @brief Process transmission interrupt
* @param unsigned char bChannel
* @retval none
--------------------------------------------------------------------------------
*/
static void TxInterrupt( unsigned char bChannel )
{
unsigned char index = bChannel - 1;
#ifdef TOYA2_C
unsigned long status;
status = *regUSR2[index];
// FIFO Empty Complete
if( (status & 0x00004000) && ((*regUCR1[index] & (1<<6)) != 0) ){
//Callbck notification of transmission completed
UART_IF_TX_STS sTxSts;
sTxSts.bChannel = bChannel;
sTxSts.wActSize = sModuleSts.sTxInfo[index].wTxSize;
sModuleSts.sTxInfo[index].STATE = STATE_READY;
// Disable the FIFO Empty interrupt
*regUCR1[index] &= ~(1<<6);
sModuleSts.sTxInfo[index].pfnCallback( UART_IF_SND_DATA_CMP, STATUS_SUCCESS, &sTxSts ); // Completion callback notification
}
#endif // TOYA2_C
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -