📄 uart.c
字号:
/**
* Project Name : S3C2460 verification project
*
* Copyright 2004 by Samsung Electronics, Inc.
* All rights reserved.
*
* Project Description :
* This software is only for verifying functions of the S3C2460.
* Anybody can use this code without our permission.
*/
/**
* File Name : uart.c
* Description : S3C2460 UART module code
* Author : Junon Jeon
* Dept : Mobile solution, AP
* Created Date : 2004.06.17
* Version : 0.0
* History
* R0.0 (2004.06.17): Junon draft
*/
#include <stdio.h>
#include "def.h"
#include "option.h"
#include "2460addr.h"
#include "2460lib.h"
#include "Uart.h"
#include "PLL.h"
#define UART_REG_BASE 0x44400000
#define UART_REG_OFFSET 0x4000
#define UART0_REG ( UART_REGS *)UART_REG_BASE // Uart 0 register base address
#define UART1_REG ( UART_REGS *)(UART_REG_BASE+UART_REG_OFFSET)
#define UART2_REG ( UART_REGS *)(UART_REG_BASE+UART_REG_OFFSET*2)
#define UART_BUF (_NONCACHE_STARTADDRESS + 0x10000)
#define FIFO_DEBUG_BUF (_NONCACHE_STARTADDRESS + 0x11000)
#define TX_FIFO_RESET (1<<2)
#define RX_FIFO_RESET (1<<1)
#define TX_INT_TYPE (1<<9) // 0:pulse 1:level
#define RX_INT_TYPE (1<<8) // 0:pulse 1:level
#define RX_TIMEOUT_EN (0<<7) // 0:disable 1:enable, disable for FIFO test
#define RX_ERR_INT_EN (1<<6) // 0:disable 1:enable
#define RTS_ACTIVE (1) // In normal mode, nRTS signal 0:low, 1:High
#define BIT_UART_MODEM (1<<3)
#define BIT_UART_TXD (1<<2)
#define BIT_UART_ERROR (1<<1)
#define BIT_UART_RXD (1)
#define INT_MODE 0
#define DMA_MODE 1
#define DMA_BUF_LEN 8 // for rx
#define TX_END_CHAR NULL
#define RX_END_CHAR '\r'
typedef struct tag_UART_REGS
{
unsigned int rUlCon;
unsigned int rUCon;
unsigned int rUfCon;
unsigned int rUmCon;
unsigned int rUtrStat;
unsigned int rUerStat;
unsigned int rUfStat;
unsigned int rUmStat;
unsigned int rUtxh;
unsigned int rUrxh;
unsigned int rUbrDiv;
unsigned int rUdivSlot;
unsigned int rUintP;
unsigned int rUintSp;
unsigned int rUintM;
} UART_REGS;
typedef struct tag_UART_CON
{
unsigned int iBaudrate;
unsigned char fSelUartIrda; // Uart mode
unsigned char fLoopTest;
unsigned char fAfc;
unsigned char fEnableFifo;
unsigned char cOpClock; // 0,2:PCLK, 1:UEXTCLK, 2:EPLL
unsigned char cDataBit; // 0:5bit, 1:6bit, 2:7bit, 3:8bit
unsigned char cParityBit; // 0:no parity, 1:odd, 2:even, 3:forced 1, 4:forced 0
unsigned char cStopBit; // 0:one stopbit, 1:two stopbit
unsigned char cTxMode; // 0:disable, 1:interrupt or polling, 2:DMA0, 3:DMA1
unsigned char cTxTrig; // 0:empty, 1:16, 2:32, 3:48 (byte)
unsigned char cRxMode; // 0:disable, 1:interrupt or polling, 2:DMA0, 3:DMA1
unsigned char cRxTrig; // 0:1, 1:8, 2:16, 3:32 (byte)
unsigned char cRtsTrig; // 0:63, 1:56, 2:48, ... , 7:8 (byte)
} UART_CON;
void SetUartPort(void);
void ReturnUartPort(void);
void CalcBaudrate( UART_REGS *, UART_CON *);
void InitializeUart( UART_REGS *, UART_CON *); // initialize with current setting
void UartSubIsr(unsigned char );
void __irq UartIsr(void);
void __irq DmaIsr(void);
unsigned char SetBaudrate(unsigned char ch, unsigned int Baudrate);
unsigned char SetOpClock(unsigned char ch, unsigned int OpClock);
unsigned char SetLineCon(unsigned char ch, unsigned char DataBit, unsigned char StopBit, unsigned char ParityBit);
unsigned char SetDbgUart(unsigned char ch); // set registers with debug setting
unsigned char UartOpen(unsigned char ch);
unsigned char UartClose(unsigned char ch);
//void SelectChannel(unsigned char ch);
//void InputUartProperty(unsigned char ch, ...);
void TestUart(void);
void UartTx(void);
void UartRx(void);
static unsigned int save_rGPHCON, save_rGPHPU, save_rSPCON; // for setting Uart Port
static UART_CON UartCon[4] = {{115200,0,0,0,0,0,3,0,0,1,1,1,1,1}
, {115200,0,0,0,0,0,3,0,0,1,1,1,1,1}
, {115200,0,0,0,0,0,3,0,0,1,1,1,1,1}
, {115200,0,0,0,0,0,3,0,0,1,1,1,1,1}};
// control property per each channel. 4th data is defualt value for initialize
const unsigned int nSlotTable[16] = {0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4a52, 0x54aa,
0x5555, 0xd555, 0xd5d5, 0xddd5, 0xdddd, 0xdfdd, 0xdfdf, 0xffdf};
volatile unsigned int UextClk = 12000000;
volatile unsigned int EpllClk = 12000000;
static volatile unsigned char isTxDone[3] = {0, 0, 0};
static volatile unsigned char isRxDone[3] = {0, 0, 0};
char *pUartTxStr[3], *pUartRxStr[3];
// buffer for test
char TestString[]="\nABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890->UART Tx interrupt test is good!!!!\r";
volatile unsigned int *pFifoDebug = (unsigned int *)FIFO_DEBUG_BUF; //temporary for fifo count test
volatile unsigned int fcnt = 0;
/**
* Function Name :
*
* Function Description :
*
* Input :
* Output :
* Version :
*/
void * func_uart_test[][2]=
{
// "0123456789012345" max 15磊 肺茄沥窍咯 comment窍技夸.
//UART
(void *)TestUart, "UART common test ",
(void *)UartTx, "UART Tx string ",
(void *)UartRx, "UART Rx string ",
0,0
};
void Uart_Test(void)
{
int i;
printf("\n====== UART Test program start ======\n");
while(1)
{
i=0;
printf("\n\n");
while(1)
{ //display menu
printf("%2d:%s",i,func_uart_test[i][1]);
i++;
if((int)(func_uart_test[i][0])==0)
{
printf("\n");
break;
}
if((i%4)==0)
printf("\n");
}
printf("\nPress Enter key to exit : ");
i = GetIntNum();
if(i==-1) break; // return.
if(i>=0 && (i<((sizeof(func_uart_test)-1)/8)) ) // select and execute...
( (void (*)(void)) (func_uart_test[i][0]) )();
}
printf("\n====== UART Test program end ======\n");
}
void SetUartPort(void)
{
//Push UART GPIO port configuration
save_rGPHCON = rGPHCON;
save_rGPHPU = rGPHPU;
save_rSPCON = rSPCON;
//Configure UART port
rGPHCON = 0x2AAAAA; // enable all uart channel [22:0]
rGPHPU = 0x7ff; //Uart port pull-up disable [11:0]
rSPCON &= ~(1<<2);
}
void ReturnUartPort(void)
{
//Pop UART GPIO port configuration
rGPHCON = save_rGPHCON;
rGPHPU = save_rGPHPU;
rSPCON = save_rSPCON;
}
void CalcBaudrate( UART_REGS *pUartRegs, UART_CON *pUartCon)
{
float tempDiv;
unsigned int nOpClock;
unsigned int nSlot;
switch(pUartCon->cOpClock)
{
case 1 : // Uextclk
nOpClock = UextClk;
break;
case 3 : // Epll
nOpClock = EpllClk;
break;
case 0 :
case 2 : // Pclk
default :
nOpClock = PCLK;
break;
}
tempDiv = (nOpClock/(16.*pUartCon->iBaudrate)) - 1;
nSlot = (int)((tempDiv - (int)tempDiv) * 16);
pUartRegs->rUbrDiv = (int)(tempDiv);
pUartRegs->rUdivSlot = nSlotTable[nSlot];
// printf(" div = %d, slot = 0x%x\n", (int)(tempDiv), nSlotTable[nSlot]);
}
void InitializeUart( UART_REGS *pUartRegs, UART_CON *pUartCon) // Initialize register set with current control set
{
CalcBaudrate(pUartRegs, pUartCon);
pUartRegs->rUlCon = (pUartCon->fSelUartIrda<<6)|(pUartCon->cParityBit<<3)|(pUartCon->cStopBit<<2)
|(pUartCon->cDataBit);
pUartRegs->rUCon = (pUartCon->cOpClock<<10)|TX_INT_TYPE|RX_INT_TYPE|RX_ERR_INT_EN|RX_TIMEOUT_EN
|(pUartCon->fLoopTest<<5)|(pUartCon->cTxMode<<2)|(pUartCon->cRxMode);
pUartRegs->rUfCon = (pUartCon->cTxTrig<<6)|(pUartCon->cRxTrig<<4)|TX_FIFO_RESET|RX_FIFO_RESET
|(pUartCon->fEnableFifo);
pUartRegs->rUmCon = (pUartCon->cRtsTrig<<5)|(pUartCon->fAfc<<4)|RTS_ACTIVE;
pUartRegs->rUintM = 0xf; // mask
pUartRegs->rUintSp = 0xf; // source pending clear
pUartRegs->rUintP = 0xf; // pending clear
// deglitch bug s/w work around for using EPLL output clock source
{
char sel;
printf("\nSelect whether s/w work-around is adopted or not(y/n)\n");
sel=getchar();
if(sel=='y')
{
rGPHCON &= ~(3<<16);
Delay(2);
rGPHCON |= (2<<16);
printf("\ns/w work-around is adopted..\n");
}
else
printf("\ns/w work-around is not adopted..\n");
}
}
void __irq UartIsr(void)
{
rINTMSK |= BIT_UART;
if (rSUBSRCPND&BIT_SUB_UART0)
{
UartSubIsr(0);
}
if (rSUBSRCPND&BIT_SUB_UART1)
{
UartSubIsr(1);
}
if (rSUBSRCPND&BIT_SUB_UART2)
{
UartSubIsr(2);
}
rINTMSK &= ~(BIT_UART);
}
void UartSubIsr(unsigned char ch)
{
unsigned int tempStat = 0;
unsigned int chBit;
unsigned char tempChar;
UART_REGS *pUartRegs;
chBit = (unsigned int)(1<<ch);
rINTSUBMSK |= chBit;
pUartRegs = ( UART_REGS *)(UART_REG_BASE+UART_REG_OFFSET*ch);
// Check Errors
if (pUartRegs->rUintP & BIT_UART_ERROR)
{
pUartRegs->rUintM |= BIT_UART_ERROR;
pUartRegs->rUintSp = BIT_UART_ERROR;
pUartRegs->rUintP = BIT_UART_ERROR;
tempStat = pUartRegs->rUerStat;
switch(tempStat)//to clear and check the status of register bits
{
case 1:
printf("Overrun error!\n");
break;
case 2:
printf("Parity error!\n");
break;
case 4:
printf("Frame error!\n");
break;
case 6:
printf("Parity, Frame error!\n");
break;
case 8:
printf("Breake detect\n");
break;
case 0xa:
printf("Parity error & Break detect!\n");
break;
case 0xc:
printf("Frame error & Breake detect\n");
break;
case 0xe:
printf("Parity, Frame error & Break detect!\n");
break;
default :
printf("Unknown error : 0x%x\n", tempStat);
break;
}
isRxDone[ch] = 1;
pUartRegs->rUintM &= ~(BIT_UART_ERROR);
}
// Tx ISR
if (pUartRegs->rUintP & BIT_UART_TXD)
{
pUartRegs->rUintM |= BIT_UART_TXD;
pUartRegs->rUintSp = BIT_UART_TXD;
pUartRegs->rUintP = BIT_UART_TXD;
if (pUartRegs->rUfCon & 1) // 1 : fifo enable
{
// for debugging fifo
*pFifoDebug++ = ++fcnt;
*pFifoDebug++ = (pUartRegs->rUfCon>>6)&3;
*pFifoDebug++ = (pUartRegs->rUfStat>>8)&0x3f;
*pFifoDebug = 0;
while (!(pUartRegs->rUfStat & (1<<14)) && (*pUartTxStr[ch] != TX_END_CHAR)) //until tx fifo full or end of string
pUartRegs->rUtxh = *pUartTxStr[ch]++;
if(*pUartTxStr[ch] == TX_END_CHAR)
{
*(pUartTxStr[ch]+1) = NULL;
isTxDone[ch] = 1;
pUartRegs->rUintM |= (BIT_UART_TXD);
rSUBSRCPND = chBit;
ClearPending(BIT_UART);
return;
}
else
{
pUartRegs->rUintM &= ~(BIT_UART_TXD);
}
}
else // 0 : fifo disable
{
if (*pUartTxStr[ch] != TX_END_CHAR)
{
pUartRegs->rUtxh = *pUartTxStr[ch]++;
pUartRegs->rUintM &= ~(BIT_UART_TXD);
}
else
{
*(pUartTxStr[ch]+1) = NULL;
isTxDone[ch] = 1;
rSUBSRCPND = chBit;
ClearPending(BIT_UART);
return;
}
}
}
// Rx ISR
if (pUartRegs->rUintP & BIT_UART_RXD)
{
pUartRegs->rUintM |= BIT_UART_RXD;
pUartRegs->rUintSp = BIT_UART_RXD;
pUartRegs->rUintP = BIT_UART_RXD;
if (pUartRegs->rUfCon & 1) // 1 : fifo enable
{
// for debugging fifo
*pFifoDebug++ = ++fcnt;
*pFifoDebug++ = (pUartRegs->rUfCon>>4)&3;
*pFifoDebug++ = (pUartRegs->rUfStat)&0x3f;
*pFifoDebug = 0;
// while (!(pUartRegs->rUfStat & (1<<6))); // until rx full for AFC rts trigger test
while (pUartRegs->rUfStat & 0x3f) //until rx fifo count 0
{
*pUartRxStr[ch] = (unsigned char)(pUartRegs->rUrxh);
printf("%c", *pUartRxStr[ch]++);
}
if(*(pUartRxStr[ch]-1) == RX_END_CHAR)
{
*pUartRxStr[ch] = NULL;
isRxDone[ch] = 1;
pUartRegs->rUintM |= (BIT_UART_RXD);
rSUBSRCPND = chBit;
ClearPending(BIT_UART);
return;
}
else
{
pUartRegs->rUintM &= ~(BIT_UART_RXD);
}
}
else // 0 : fifo disable
{
tempChar = (unsigned char)(pUartRegs->rUrxh);
if (tempChar != RX_END_CHAR)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -