📄 uart.c
字号:
//////////
// Function Name : UART_TxString
// Function Description : This function trasmits String through UART
// Input : ch [0~4 UART channel]
// str [character type string that you want to transmit, the last charater of string should be 'NULL']
// Output : NONE
// Version : v0.1
void UART_TxString(u8 ch, u8 *str) // The last character of 'str' should be NULL
{
volatile UART_REGS *pUartRegs;
volatile UART_CON *pUartCon;
u8 cTemp;
u32 uTemp2;
pUartRegs = (volatile UART_REGS *)(UART_BASE+UART_OFFSET*ch);
pUartCon = &g_AUartCon[ch];
g_AisTxDone[ch] = 0;
g_pUartTxStr[ch] = str;
g_pFifoDebug = (u32 *)FIFO_DEBUG_BUF;
g_uFcnt = 0;
cTemp = Inp8(&pUartCon->cTxMode ) & 3;
if ( cTemp == 1 ) // interrupt mode
{
INTC_Enable(NUM_UART0);
INTC_Enable(NUM_UART1);
INTC_Enable(NUM_UART2);
INTC_Enable(NUM_UART3);
uTemp2 = Inp32(&pUartRegs->rUintM);
uTemp2 &= ~(BIT_UART_TXD);
Outp32(&pUartRegs->rUintM,uTemp2);
// pUartRegs->rUintM &= ~(BIT_UART_TXD);
}
else if ( (cTemp==2) || (cTemp==3) ) // dma mode
{
/*
rDISRC0 = (unsigned int)str; // Start address
rDISRCC0 = (0<<1)|(0); // AHB,Increment
rDIDST0 = (unsigned int)(&pUartRegs->rUtxh); // Memory buffer Address
rDIDSTC0 = (1<<1)|(1); // APB,Fixed
rDCON0 = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(1<<22)|(0<<20)|strlen(str);
//handshake, sync PCLK, TC int, single tx, single service,auto-reload off, Byte size Tx, Tx count value
rDMAREQSEL0 = ((19+ch*2)<<1)|1;
// Clear Int Pending and Unmask
rSUBSRCPND = BIT_SUB_DMA0;
ClearPending(BIT_DMA);
rINTMSK &= ~(BIT_DMA);
rINTSUBMSK &= ~(BIT_SUB_DMA0);
rDMASKTRIG0 = (0<<2)|(1<<1)|(0); //no-stop, DMA0 channel on, no-SW trigger
*/
}
while(!g_AisTxDone[ch]);
// for debugging fifo
if ( (Inp32(&pUartRegs->rUfCon) & 1) && (cTemp == 1) ) // 1 : fifo enable
{
g_pFifoDebug = (u32 *)FIFO_DEBUG_BUF;
while(*g_pFifoDebug) // g_pFifoDebug address, Tx count, UfCon, g_uFcnt
printf("[0x%x,%d,0x%x,%d] ", g_pFifoDebug, *g_pFifoDebug++, *g_pFifoDebug++,*g_pFifoDebug++);
}
}
//////////
// Function Name : UART_RxString
// Function Description : This function receives String through UART
// Input : ch [0~4 UART channel]
// Output : g_pUartRxStr[ch] [charater type received string]
// Version : v0.1
u8* UART_RxString(u8 ch) // The last character of input string should be '\r'. simple test code
{
volatile UART_REGS *pUartRegs;
volatile UART_CON *pUartCon;
u8 cTemp;
u32 uTemp2;
pUartRegs = (volatile UART_REGS *)(UART_BASE+UART_OFFSET*ch);
pUartCon = &g_AUartCon[ch];
g_AisRxDone[ch] = 0;
g_pUartRxStr[ch] = ( u8 *)(UART_BUF+DMA_BUF_LEN);
g_pFifoDebug = (u32 *)FIFO_DEBUG_BUF;
g_uFcnt = 0;
cTemp = Inp8(pUartCon->cRxMode) & 3;
if ( cTemp == 1 ) // interrupt mode
{
Outp32(&pUartRegs->rUintSp , (BIT_UART_MODEM|BIT_UART_TXD|BIT_UART_ERROR|BIT_UART_RXD));
Outp32(&pUartRegs->rUintP , (BIT_UART_MODEM|BIT_UART_TXD|BIT_UART_ERROR|BIT_UART_RXD));
INTC_Enable(NUM_UART0);
INTC_Enable(NUM_UART1);
INTC_Enable(NUM_UART2);
INTC_Enable(NUM_UART3);
uTemp2 = Inp32(&pUartRegs->rUintM);
uTemp2 &= ~(BIT_UART_ERROR|BIT_UART_RXD);
Outp32(&pUartRegs->rUintM,uTemp2);
}
else if ( (cTemp == 2) || (cTemp == 3) ) // dma mode
{
/*
printf("\nIn DMA rxstring mode");
rDISRC1=(unsigned int)(&pUartRegs->rUrxh); // Start address
rDISRCC1=(1<<1)|(1); // APB,Fixed
rDIDST1=(unsigned int)(UART_BUF); // Memory buffer Address
rDIDSTC1= (0<<1)|(0); // AHB,Increment
rDCON1=(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(1<<22)|(0<<20)|(DMA_BUF_LEN);
//handshake, sync PCLK, TC int, single tx, single service,auto-reload off, Byte size Tx, Tx count value
rDMAREQSEL1 = ((20+ch*2)<<1)|1;
// Clear Int Pending and Unmask
rINTMSK &= ~(BIT_DMA);
rINTSUBMSK &= ~(BIT_SUB_DMA1);
rDMASKTRIG1 = (0<<2)|(1<<1)|(0); //no-stop, DMA1 channel on, no-SW trigger
*/
}
while(!g_AisRxDone[ch]);
// for debugging fifo
if ( (Inp32(&pUartRegs->rUfCon) & 1) && (cTemp == 1) ) // 1 : fifo enable
{
g_pFifoDebug = (u32 *)FIFO_DEBUG_BUF;
while(*g_pFifoDebug)
printf("[0x%x,%d,0x%x,%d] ", g_pFifoDebug, *g_pFifoDebug++, *g_pFifoDebug++,*g_pFifoDebug++);
}
g_pUartRxStr[ch] = ( u8 *)(UART_BUF+DMA_BUF_LEN);
return g_pUartRxStr[ch];
}
//////////
// Function Name : UART_Open
// Function Description : This function set up H/W(GPIO) and initialize SFR of UART
// Input : ch [0~4 UART channel]
// Output : g_pUartRxStr[ch] [charater type received string]
// Version : v0.1
u8 UART_Open(u8 ch) // setting H/W & initializing regiter
{
if(ch == 0)
g_pUartDebugRegs = UART0_BASE;
else if(ch == 1)
g_pUartDebugRegs = UART1_BASE;
else if(ch == 2)
g_pUartDebugRegs = UART2_BASE;
else if(ch == 3)
g_pUartDebugRegs = UART3_BASE;
/*
INTC_SetVectAddr(NUM_DMA1,Isr_Dma);
if(ch == 0)
{
INTC_SetVectAddr(NUM_UART0,Isr_Uart0);
INTC_Enable(NUM_UART0);
}
else if(ch == 1)
{
INTC_SetVectAddr(NUM_UART1,Isr_Uart1);
INTC_Enable(NUM_UART1);
}
else if(ch == 2)
{
INTC_SetVectAddr(NUM_UART2,Isr_Uart2);
INTC_Enable(NUM_UART2);
}
else if(ch == 3)
{
INTC_SetVectAddr(NUM_UART3,Isr_Uart3);
INTC_Enable(NUM_UART3);
}
else
return 0;
*/
switch(ch)
{
case 0 :
GPIO_SetFunctionEach(eGPIO_A, eGPIO_0, 2); //Uart0 RXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_1, 2); //Uart0 TXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_2, 2); //Uart0 CTSn
GPIO_SetFunctionEach(eGPIO_A, eGPIO_3, 2); //Uart0 RTSn
// rGPHCON &= ~(0xf000f); // GPH0,1,8,9
// rGPHCON |= 0xa000a; // Uart 0 Rx, Tx, Rts, Cts
if(UART_InitializeREG(UART0_BASE, &g_AUartCon[0]) == SENDBREAK)
return SENDBREAK; // Initialize register set for Uart 0
break;
case 1 :
GPIO_SetFunctionEach(eGPIO_A, eGPIO_4, 2); //Uart1 RXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_5, 2); //Uart1 TXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_6, 2); //Uart1 CTSn
GPIO_SetFunctionEach(eGPIO_A, eGPIO_7, 2); //Uart1 RTSn
// rGPHCON &= ~(0xf000f<<4); // GPH2,3,10,11
// rGPHCON |= (0xa000a<<4); // Uart 1 Rx, Tx, Rts, Cts
if(UART_InitializeREG(UART1_BASE, &g_AUartCon[1]) == SENDBREAK)
return SENDBREAK;
break;
case 2 :
GPIO_SetFunctionEach(eGPIO_B, eGPIO_0, 2); //Uart2 RXD
GPIO_SetFunctionEach(eGPIO_B, eGPIO_1, 2); //Uart2 TXD
// rGPHCON &= ~(0xf<<6); // GPH4,5
// rGPHCON |= (0xa<<6); // Uart 2 Rx, Tx
if(UART_InitializeREG(UART2_BASE, &g_AUartCon[2]) == SENDBREAK)
return SENDBREAK;
break;
case 3 :
GPIO_SetFunctionEach(eGPIO_B, eGPIO_2, 2); //Uart2 RXD
GPIO_SetFunctionEach(eGPIO_B, eGPIO_3, 2); //Uart2 TXD
// rGPHCON &= ~(0xf<<12); // GPH6,7
// rGPHCON |= (0xa<<12); // Uart 3 Rx, Tx
if(UART_InitializeREG(UART3_BASE, &g_AUartCon[3]) == SENDBREAK)
return SENDBREAK;
break;
default :
//printf("Can't open UARTx!! Select 0,1, or 2!!");
return FALSE;
}
return TRUE;
}
//////////
// Function Name : UART_Close
// Function Description : This function closed H/W(GPIO) and disable UART exception
// Input : ch [0~4 UART channel]
// Output : 1: success 2:fail
// Version : v0.1
u8 UART_Close(u8 ch) // return to reset value
{
volatile UART_REGS *pUartRegs;
if (ch > 2) return FALSE;
pUartRegs = (volatile UART_REGS *)(UART_BASE+UART_OFFSET*ch);
INTC_Disable(NUM_UART0);
INTC_Disable(NUM_UART1);
INTC_Disable(NUM_UART2);
INTC_Disable(NUM_UART3);
pUartRegs->rUintM |= (BIT_UART_MODEM|BIT_UART_TXD|BIT_UART_ERROR|BIT_UART_RXD);
switch(ch)
{
case 0 :
GPIO_SetFunctionEach(eGPIO_A, eGPIO_4, 0); //Uart1 RXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_5, 0); //Uart1 TXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_6, 0); //Uart1 CTSn
GPIO_SetFunctionEach(eGPIO_A, eGPIO_7, 0); //Uart1 RTSn
break;
case 1 :
GPIO_SetFunctionEach(eGPIO_A, eGPIO_4, 0); //Uart1 RXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_5, 0); //Uart1 TXD
GPIO_SetFunctionEach(eGPIO_A, eGPIO_6, 0); //Uart1 CTSn
GPIO_SetFunctionEach(eGPIO_A, eGPIO_7, 0); //Uart1 RTSn
break;
case 2 :
GPIO_SetFunctionEach(eGPIO_B, eGPIO_0, 0); //Uart2 RXD
GPIO_SetFunctionEach(eGPIO_B, eGPIO_1, 0); //Uart2 TXD
break;
case 3 :
GPIO_SetFunctionEach(eGPIO_B, eGPIO_2, 0); //Uart2 RXD
GPIO_SetFunctionEach(eGPIO_B, eGPIO_3, 0); //Uart2 TXD
break;
default :
printf("Can't close UARTx!! Select 0,1, or 2!!");
return FALSE;
}
return TRUE;
}
//////////
// Function Name : UART_InitializeREG
// Function Description : This function set up SFR by pre-defined value
// Input : *pUartRegs [SFR value base address]
// *pUartCon [Pre-defined value's base address, UART_Config]
// Output : SENDBREAK [when sendbreak signal set up]
// 0 [nomal mode (sendbreak signal disable)]
// Version : v0.1
u32 UART_InitializeREG( UART_REGS *pUartRegs, UART_CON *pUartCon) // Initialize register set with current control set
{
UART_CalcBaudrate(pUartRegs, pUartCon);
Outp32(&pUartRegs->rUlCon , (pUartCon->cSelUartIrda<<6)|(pUartCon->cParityBit<<3)|(pUartCon->cStopBit<<2)
|(pUartCon->cDataBit));
Outp32(&pUartRegs->rUCon , (pUartCon->cOpClock<<10)|TX_INT_TYPE|RX_INT_TYPE|RX_ERR_INT_EN|RX_TIMEOUT_EN
|(pUartCon->cLoopTest<<5)| (pUartCon->cSendBreakSignal<<4) |(pUartCon->cTxMode<<2)|(pUartCon->cRxMode));
if(Inp8(&pUartCon->cSendBreakSignal))
return SENDBREAK;
Outp32(&pUartRegs->rUfCon , (pUartCon->cTxTrig<<6)|(pUartCon->cRxTrig<<4)|TX_FIFO_RESET|RX_FIFO_RESET
|(pUartCon->cEnableFifo));
Outp32(&pUartRegs->rUmCon , (pUartCon->cRtsTrig<<5)|(pUartCon->cAfc<<4)|RTS_ACTIVE);
Outp32(&pUartRegs->rUintM , 0xf); // mask
Outp32(&pUartRegs->rUintSp , 0xf); // source pending clear
Outp32(&pUartRegs->rUintP , 0xf); // pending clear
return 0;
}
//////////
// Function Name : UART_CalcBaudrate
// Function Description : This function defines UbrDiv and UdivSlot value depends on OpClock src
// Input : *pUartRegs [SFR value base address]
// *pUartCon [Pre-defined value's base address, UART_Config]
// Output : NONE
// Version : v0.1
void UART_CalcBaudrate( UART_REGS *pUartRegs, UART_CON *pUartCon)
{
const u32 aSlotTable[16] = {0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4a52, 0x54aa,
0x5555, 0xd555, 0xd5d5, 0xddd5, 0xdddd, 0xdfdd, 0xdfdf, 0xffdf};
float tempDiv;
u32 nOpClock;
u32 nSlot;
switch(Inp8(&pUartCon->cOpClock))
{
case 0 :
case 2 : // Pclk
default :
nOpClock = g_PCLK;
break;
}
tempDiv = (nOpClock/(16.*Inp32(&pUartCon->uBaudrate))) - 1;
nSlot = (u32)((tempDiv - (int)tempDiv) * 16);
Outp32(&pUartRegs->rUbrDiv , (u32)(tempDiv));
Outp32(&pUartRegs->rUdivSlot , aSlotTable[nSlot]);
//printf(" div = %d, slot = 0x%x\n", (u32)(tempDiv), aSlotTable[nSlot]);
}
//////////
// Function Name : Isr_Uart0~3
// Function Description : These are Interrupt Service Routine of UART which are connected to Isr_UartSub
// Input : NONE
// Output : NONE
// Version : v0.1
void __irq Isr_Uart0(void)
{
Isr_UartSub(0);
INTC_ClearVectAddr();
}
void __irq Isr_Uart1(void)
{
Isr_UartSub(1);
INTC_ClearVectAddr();
}
void __irq Isr_Uart2(void)
{
Isr_UartSub(2);
INTC_ClearVectAddr();
}
void __irq Isr_Uart3(void)
{
Isr_UartSub(3);
INTC_ClearVectAddr();
}
//////////
// Function Name : Isr_UartSub
// Function Description : This is Uart SubISR which checks errors and operates Tx and Rx
// Input : NONE
// Output : NONE
// Version : v0.1
void Isr_UartSub(u8 ch)
{
u32 ErrorStatus = 0;
volatile UART_REGS *pUartRegs;
u8 tempChar;
u32 uTemp;
pUartRegs = ( UART_REGS *)(UART_BASE+UART_OFFSET*ch);
// Check Errors
if (Inp32(&pUartRegs->rUintP) & BIT_UART_ERROR)
{
uTemp = Inp32(&pUartRegs->rUintM);
uTemp |= BIT_UART_ERROR;
Outp32(&pUartRegs->rUintM , uTemp);
// pUartRegs->rUintM |= BIT_UART_ERROR;
Outp32(&pUartRegs->rUintSp , BIT_UART_ERROR);
Outp32(&pUartRegs->rUintP , BIT_UART_ERROR);
ErrorStatus = Inp32(&pUartRegs->rUerStat);
switch(ErrorStatus)//to clear and check the status of register bits
{
case 1:
printf("%d ch : Overrun error!\n",ch);
break;
case 2:
printf("%d ch : Parity error!\n",ch);
break;
case 4:
printf("%d ch : Frame error!\n",ch);
break;
case 6:
printf("%d ch : Parity, Frame error!\n",ch);
break;
case 8:
printf("%d ch : Breake detect\n",ch);
break;
case 0xa:
printf("%d ch : Parity error & Break detect!\n",ch);
break;
case 0xc:
printf("%d ch : Frame error & Breake detect\n",ch);
break;
case 0xe:
printf("%d ch : Parity, Frame error & Break detect!\n",ch);
break;
default :
printf("Unknown error : 0x%x\n", ErrorStatus);
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -