⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart_drv.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************
**                                                              *
**  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 + -