📄 uart_drv.c
字号:
/****************************************************************
** *
** FILE : UARTDRV.C *
** COPYRIGHT : (c) 2004 .Xiamen Yaxon NetWork CO.LTD *
** *
** 2004.11.24 *
****************************************************************/
#include "includes.h"
#include "bsp.h"
#include "roundbuf.h"
#define EN_TX0_PDC 1
#define EN_TX1_PDC 1
/* 标准异步模式 : 8 bits , 1 stop , no parity */
#define USART_ASYNC_MODE ( AT91C_US_CHMODE_NORMAL + AT91C_US_NBSTOP_1_BIT + \
AT91C_US_PAR_NONE + AT91C_US_CHRL_8_BITS + \
AT91C_US_CLKS_CLOCK )
/*
********************************************************************************
* DEFINE CONFIG PARAMETERS
********************************************************************************
*/
#define UART_SENDING 0x01
#define UART_INIT 0x80
#define MAX_UART 1
#define AT91_UART_NUM 2
#define MAX_SBUF 2048
#define MAX_RBUF 2048
#define RXPDC_BUFSIZE 32
#define TXPDC_BUFSIZE 32
/*
********************************************************************************
* DEFINE UART_STRUT
********************************************************************************
*/
typedef struct {
AT91PS_USART reg; /* register base address */
INT32U pin_mask_rxd; /* RXD pin number */
INT32U pin_mask_txd; /* TXD pin number */
INT32U pin_mask_sck; /* SCK pin number */
INT32U pid; /* at91_usart device peripheral id */
} USART_DESC;
typedef struct {
INT32U baud; // uart baud
INT8U status; // uart status
INT8U s_buf[MAX_SBUF]; // uart send buffer
INT8U r_buf[MAX_RBUF];
ROUNDBUF_STRUCT s_round; // uart send round buffer
ROUNDBUF_STRUCT r_round;
}UART_STRUCT;
/*
********************************************************************************
* DEFINE MODULE VARIANT
********************************************************************************
*/
static UART_STRUCT uarts[AT91_UART_NUM];
static INT8U RxPDCBuf[AT91_UART_NUM][RXPDC_BUFSIZE];
static INT8U TxPDCBuf[AT91_UART_NUM][TXPDC_BUFSIZE];
static USART_DESC dev_usart[2] = {
{ /* USART0 */
AT91C_BASE_US0,
AT91C_P15_RXD0,
AT91C_P14_TXD0,
AT91C_P13_SCK0,
AT91C_ID_US0
},{ /* USART1 */
AT91C_BASE_US1,
AT91C_P22_RXD1,
AT91C_P21_TXD1,
AT91C_P20_SCK1,
AT91C_ID_US1
}
};
/***********************************************************************
* USART_Reset - 复位并使能发送和接收
************************************************************************/
static void ResetUART(INT32U chan)
{
USART_DESC *usart = &dev_usart[chan];
if (chan > MAX_UART) return;
usart->reg->US_CR = AT91C_US_RSTRX|AT91C_US_RSTTX;
usart->reg->US_CR = AT91C_US_RXEN|AT91C_US_TXEN;
}
void EnableUARTInt(INT32U chan,INT32U Int_mode)
{
USART_DESC *usart = &dev_usart[chan];
if (chan > MAX_UART) return;
usart->reg->US_IER = Int_mode;
}
void DisableUARTInt(INT32U chan,INT32U Int_mode)
{
USART_DESC *usart = &dev_usart[chan];
if (chan > MAX_UART) return;
usart->reg->US_IDR = Int_mode;
}
/***********************************************************************
* InitUART - open the USART port
************************************************************************/
void InitUART (INT32U chan, INT32U baud)
{
USART_DESC *usart ;
if(chan > MAX_UART) return ;
usart = &dev_usart[chan];
AT91C_BASE_PS->PS_PCER = 1 << (usart->pid); // enable usart Peripheral clock
usart->reg->US_IDR= (INT32S)(-1); // Disable interrupts
AT91C_BASE_PIO->PIO_PDR = (usart->pin_mask_rxd | usart->pin_mask_txd); // configure TX and RX pins as Peripheral
// reset receiver and transmitter
usart->reg->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX |
AT91C_US_RXDIS | AT91C_US_TXDIS ;
usart->reg->US_RCR = 0 ;
usart->reg->US_TCR = 0 ;
// set desired baudrate
usart->reg->US_BRGR = AT91F_US_Baudrate(MCK, baud);
usart->reg->US_MR = USART_ASYNC_MODE & 0xfffffff0;
// config time guard reg */
usart->reg->US_TTGR = 0;
usart->reg->US_RTOR = 0;
usart->reg->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
}
/*********************************************************************
* USART_Close - close the USART channel
**********************************************************************/
void UART_Close (INT32U chan)
{
USART_DESC *usart = &dev_usart[chan];
if (chan > MAX_UART) return;
AT91C_BASE_PS->PS_PCDR = (1 << usart->pid); // disable USART clock
usart->reg->US_BRGR=0;
usart->reg->US_MR=0;
usart->reg->US_TTGR=0;
usart->reg->US_IDR = 0xffffffff;// disable USART interrupts
/* cancel current transfer or receive */
usart->reg->US_RCR = 0;
usart->reg->US_TCR = 0;
/* disable transmitter and receiver */
usart->reg->US_CR = AT91C_US_RSTTX | AT91C_US_RSTRX;
usart->reg->US_CR = AT91C_US_TXDIS | AT91C_US_RXDIS;
}
/* define uarts send isr */
static void uarts_isr_s(INT8U chan)
{
INT16S cur;
INT8U count;
USART_DESC *usart = &dev_usart[chan];
usart->reg->US_CR = AT91C_US_RSTSTA;
if ((uarts[chan].status & UART_INIT) == 0 || (uarts[chan].status & UART_SENDING) == 0) {
DisableUARTInt(chan,AT91C_US_TXRDY);
return;
}
if (UsedOfRoundBuf(&uarts[chan].s_round) > 0) {
for(count=0; count<32; count++) {
if ((cur = ReadRoundBuf(&uarts[chan].s_round)) != -1) {
TxPDCBuf[chan][count] = cur;
} else {
break;
}
}
usart->reg->US_TPR = (INT32U)TxPDCBuf[chan];
usart->reg->US_TCR = count;
DisableUARTInt(chan,AT91C_US_TXRDY);
EnableUARTInt(chan,AT91C_US_ENDTX);
usart->reg->US_CR = AT91C_US_TXEN;
} else {
uarts[chan].status &= (~UART_SENDING);
DisableUARTInt(chan,AT91C_US_TXRDY);
}
}
/* define uarts receive isr */
static void uarts_isr_r(INT8U chan)
{
INT8U recvdata;
USART_DESC *usart = &dev_usart[chan];
usart->reg->US_CR = AT91C_US_RSTSTA;
if (uarts[chan].status & UART_INIT) {
recvdata = ReadUARTReg(chan);
//RxPDCBuf[chan][0] = recvdata;
//usart->reg->US_RPR = (INT32U)RxPDCBuf[chan]+1;
usart->reg->US_RPR = (INT32U)RxPDCBuf[chan];
//usart->reg->US_RCR = RXPDC_BUFSIZE-1;
usart->reg->US_RCR = RXPDC_BUFSIZE;
DisableUARTInt(chan,AT91C_US_RXRDY);
usart->reg->US_RTOR = 8;
usart->reg->US_CR = AT91C_US_STTTO;
EnableUARTInt(chan,AT91C_US_TIMEOUT|AT91C_US_ENDRX);
WriteRoundBuf(&uarts[chan].r_round, recvdata);
} else {
ReadUARTReg(chan); // NOTE: clear interrupt flag
}
}
/* define pdc receive isr */
static void pdc_isr_r(INT8U chan)
{
//可能还需要加一些互斥操作
INT8U rxlen;
USART_DESC *usart = &dev_usart[chan];
usart->reg->US_CR = AT91C_US_RSTSTA;
if ((uarts[chan].status & UART_INIT) == 0) return;
ReadUARTReg(chan); // 防止又产生一次RXRDY中断
EnableUARTInt(chan,AT91C_US_RXRDY);
rxlen = RXPDC_BUFSIZE - usart->reg->US_RCR;
usart->reg->US_RCR = 0;
DisableUARTInt(chan,AT91C_US_ENDRX|AT91C_US_TIMEOUT);
usart->reg->US_RTOR = 0;
WriteBlockRoundBuf(&uarts[chan].r_round, RxPDCBuf[chan], rxlen);
}
#if EN_TX0_PDC || EN_TX1_PDC > 0
static void pdc_isr_s(INT8U chan)
{
INT16S cur;
INT8U count;
USART_DESC *usart = &dev_usart[chan];
//usart->reg->US_CR = AT91C_US_RSTSTA;
if (UsedOfRoundBuf(&uarts[chan].s_round) > 0) {
for(count=0; count<32; count++) {
if ((cur = ReadRoundBuf(&uarts[chan].s_round)) != -1) {
TxPDCBuf[chan][count] = cur;
} else {
break;
}
}
usart->reg->US_TPR = (INT32U)TxPDCBuf[chan];
usart->reg->US_TCR = count;
EnableUARTInt(chan,AT91C_US_ENDTX);
usart->reg->US_CR = AT91C_US_TXEN;
} else {
uarts[chan].status &= (~UART_SENDING);
DisableUARTInt(chan,AT91C_US_ENDTX);
}
}
#endif
void uarts_reset(INT32U chan)
{
INT16S cur;
if (uarts[chan].status & UART_INIT) {
ResetUART(chan);
InitUART(chan, uarts[chan].baud); /* Initialize UART */
if (uarts[chan].status & UART_SENDING) {
if ((cur = ReadRoundBuf(&uarts[chan].s_round)) == -1) {
uarts[chan].status &= (~UART_SENDING);
DisableUARTInt(chan,AT91C_US_RXRDY); /* NOTE: disable Rx Interrupt */
} else {
EnableUARTInt(chan,AT91C_US_TXRDY); /* Enable UART Tx interrupt */
WriteUARTReg(chan, cur); /* Send Data from UART */
}
}
} else {
// ??DisableUARTInt(chan,AT91C_US_RXRDY); /* NOTE: disable Rx Interrupt */
}
}
/* return bytes of send free buffer */
INT16U uarts_ready(INT32U chan)
{
return LeftOfRoundBuf(&uarts[chan].s_round);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -