📄 uart.c
字号:
// 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(!isRxDone[ch]);
pUartRxStr[ch] = ( char *)(UART_BUF+DMA_BUF_LEN);
return pUartRxStr[ch];
}
void TestUart(void)
{
unsigned char ch;
ch = UartConfig();
if( UartOpen(ch,1) == SENDBREAK )
{
printf("\n\nSend Break Signal has been transfered");
return;
}
// UART Tx test with interrupt
printf("\n[Uart channel %d Tx Test]\n",ch);
TxString(ch, TestString);
printf("\nTx Done~ \n");
// UART Rx test with interrupt
printf("\n[Uart channel %d Rx Test]\n",ch);
printf("Case 1 : Interrupt mode. After typing characters and pressing ENTER key.\n");
printf("Case 2 : Interrupt FIFO mode & DMA mode. After typing characters and pressing ENTER key until FIFO level trigger.\n");
printf(" Then, you will see those characters.\n");
printf("\nRx : %s \n",RxString(ch));
printf("\nRx Done~ \n");
// Test End
printf("\nComplete UART test!!! \n");
UartClose(ch);
SetDbgUart(1); // change channel setting for debug port set
}
void UartTx(void)
{
unsigned char ch;
char str[128];
ch = UartConfig();
UartOpen(ch,1);
printf("\n[Uart%1d Tx String]\n",ch);
printf("\nIf you want to exit, press 'ESC' key at first. The character instead of 'ESC' is ignored.\n");
while (getchar() != 0x1b)
{
gets(str);
// printf("Tx : ");
TxString(ch, str);
printf("\nIf you want to exit, press 'ESC' key at first. The character instead of 'ESC' is ignored.\n");
}
UartClose(ch);
SetDbgUart(0); // change channel setting for debug port set
}
void UartRx(void)
{
unsigned char ch;
ch = UartConfig();
UartOpen(ch,1);
printf("\n[Uart%1d Rx String]\n",ch);
printf("\nIf you want to exit, press 'ESC' key at first. The character instead of 'ESC' is ignored.\n");
while (getchar() != 0x1b)
{
printf("Rx : %s ", RxString(ch));
printf("\nIf you want to exit, press 'ESC' key at first. The character instead of 'ESC' is ignored.\n");
}
UartClose(ch);
SetDbgUart(0); // change channel setting for debug port set
}
void SetUartPort(void)
{ //Push UART GPIO port configuration
save_rGPHCON = rGPHCON;
//Configure UART port
rGPHCON &= ~((0xf<<20)|(0xf<<16)|(0xf<<12)|(0xf<<8)|(0xf<<4)|(0xf<<0));
rGPHCON |= ((0xa<<20)|(0xa<<16)|(0xa<<12)|(0xa<<8)|(0xa<<4)|(0xa<<0));
}
void ReturnUartPort(void)
{ //Pop UART GPIO port configuration
rGPHCON = save_rGPHCON;
}
void CalcBaudrate( UART_REGS *pUartRegs, UART_CON *pUartCon)
{
float tempDiv;
unsigned int nOpClock;
unsigned int nSlot;
switch(pUartCon->cOpClock)
{
case 1 : nOpClock = UextClk; break;// Uextclk
case 3 : nOpClock = EpllClk; break;// Epll
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];
}
int InitializeUart( UART_REGS *pUartRegs, UART_CON *pUartCon) // Initialize register set with current control set
{
#if 1
rGPHCON = ((rGPHCON & ~(0x03 << 26)) | (0x02 << 26));
rMISCCR = ((rMISCCR & ~(0x07 << 4)) | (0x04 << 4));
#endif
CalcBaudrate(pUartRegs, pUartCon);
pUartRegs->rUlCon = (pUartCon->fSelUartIrda<<6)|(pUartCon->cParityBit<<3)|(pUartCon->cStopBit<<2)
|(pUartCon->cDataBit);
pUartRegs->rUCon = (pUartCon->cOpClock<<10)|TX_INT_TYPE(g_bIsLevelInt)|RX_INT_TYPE(g_bIsLevelInt)|RX_ERR_INT_EN|RX_TIMEOUT_EN
|(pUartCon->fLoopTest<<5)| (pUartCon->cSendBreakSignal<<4) |(pUartCon->cTxMode<<2)|(pUartCon->cRxMode);
if(pUartCon->cSendBreakSignal)
return SENDBREAK;
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;
return 0;
}
//ARM disables IFQ in CPSR When it enters ISR, There is no need to masking SUBMASK or MASK registers
void __irq UartIsr0(void)
{
UartSubIsr(0);
}
void __irq UartIsr1(void)
{
UartSubIsr(1);
}
void __irq UartIsr2(void)
{
UartSubIsr(2);
}
void __irq UartIsr3(void)
{
UartSubIsr(3);
}
void UartSubIsr(unsigned char ch)
{
unsigned int ErrorStatus = 0;
char ReadChar;
unsigned int uSubSrcPnd;
volatile UART_REGS *pUartRegs;
uSubSrcPnd = rSUBSRCPND;
pUartRegs = ( UART_REGS *)(UART_REG_BASE+UART_REG_OFFSET*ch);
if(ch == 1) { SUBINTOFFSET = 3; SRCPNDOFFSET = 23; }
else if(ch == 2) { SUBINTOFFSET = 6; SRCPNDOFFSET = 15; }
else if(ch == 3) { SUBINTOFFSET = 24; SRCPNDOFFSET = 18; }
else { SUBINTOFFSET = 0; SRCPNDOFFSET = 28; }// default : CH 0
if(!g_bIsLevelInt) rSUBSRCPND = (BIT_UART_ERROR<<SUBINTOFFSET)|(BIT_UART_TXD<<SUBINTOFFSET)|(BIT_UART_RXD<<SUBINTOFFSET);
// Check Errors
if (uSubSrcPnd & (BIT_UART_ERROR<< SUBINTOFFSET))
{
ErrorStatus = pUartRegs->rUerStat;
switch(ErrorStatus)//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", ErrorStatus); break;
}
isRxDone[ch] = 1;
rINTSUBMSK |= (BIT_UART_RXD<<SUBINTOFFSET);
}
// Tx ISR
if (uSubSrcPnd & (BIT_UART_TXD<<SUBINTOFFSET))
{
if (pUartRegs->rUfCon & 1) // 1 : fifo enable
{
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])) // if there is no character in the pUartTxStr[ch], Tx is done
{ rINTSUBMSK |= (BIT_UART_TXD<<SUBINTOFFSET); isTxDone[ch] = 1; }
}
else // 0 : fifo disable
{
if (*pUartTxStr[ch]) pUartRegs->rUtxh = *pUartTxStr[ch]++; // if there is no character in the pUartTxStr[ch], Tx is done
else
{ rINTSUBMSK |= (BIT_UART_TXD<<SUBINTOFFSET); isTxDone[ch] = 1; }
}
}
// Rx ISR
if (uSubSrcPnd & (BIT_UART_RXD<<SUBINTOFFSET))
{
if (pUartRegs->rUfCon & 1) // 1 : fifo enable
{
while (pUartRegs->rUfStat & 0x3f) //until rx fifo count 0
*pUartRxStr[ch]++ = (unsigned char)(pUartRegs->rUrxh);
if(*(pUartRxStr[ch]-1) == RX_END_CHAR)
{
*pUartRxStr[ch] = NULL; isRxDone[ch] = 1;
rINTSUBMSK |= (BIT_UART_RXD<<SUBINTOFFSET);
}
}
else // 0 : fifo disable
{
ReadChar = (unsigned char)(pUartRegs->rUrxh);
if (ReadChar != RX_END_CHAR) *pUartRxStr[ch]++ = ReadChar;
else
{
*pUartRxStr[ch] = NULL; printf("\n");
isRxDone[ch] = 1;
rINTSUBMSK |= (BIT_UART_RXD<<SUBINTOFFSET);
}
}
}
if(g_bIsLevelInt) rSUBSRCPND = (BIT_UART_ERROR<<SUBINTOFFSET)|(BIT_UART_TXD<<SUBINTOFFSET)|(BIT_UART_RXD<<SUBINTOFFSET);
ClearPending(BIT_UART);
}
void __irq DmaIsr(void) // only one for test
{
unsigned char ch;
unsigned char* pBuf;
volatile unsigned int i;
if (rSUBSRCPND&BIT_SUB_DMA0)
{ //printf("\n [TX]IN DMA ");
rDMASKTRIG0=0; // Stop Dma0
ch = ((rDMAREQSEL0>>1) -19)/2;
isTxDone[ch] = 1;
rINTSUBMSK |= (BIT_SUB_DMA0);
rSUBSRCPND = BIT_SUB_DMA0;
ClearPending(BIT_DMA);
}
if (rSUBSRCPND&BIT_SUB_DMA1)
{ //printf("\n [RX]IN DMA ");
rDMASKTRIG1=0; // Stop Dma1
pBuf = (unsigned char*)UART_BUF;
ch = ((rDMAREQSEL1>>1) -19)/2;
for (i=0; i<DMA_BUF_LEN; i++)
*pUartRxStr[ch]++ = *pBuf++;
if ( *(pUartRxStr[ch]-1) == RX_END_CHAR )
{
isRxDone[ch] = 1;
*pUartRxStr[ch] = NULL; // added null after rx string
rINTSUBMSK |= BIT_SUB_DMA1;
rINTMSK |= BIT_DMA;
}
else
{
rDMASKTRIG1 = (0<<2)|(1<<1)|(0); //no-stop, DMA1 channel on, no-SW trigger
}
rSUBSRCPND = BIT_SUB_DMA1;
ClearPending(BIT_DMA);
}
}
////////////////////// User library functions /////////////////////
unsigned char SetBaudrate(unsigned char ch, unsigned int Baudrate)
{
UART_REGS *pUartRegs;
UART_CON *pUartCon;
if (ch > 2) return FALSE;
pUartCon = &UartCon[ch];
pUartRegs = (UART_REGS *)(UART_REG_BASE+UART_REG_OFFSET*ch);
pUartCon->iBaudrate = Baudrate;
CalcBaudrate(pUartRegs, pUartCon);
return TRUE;
}
unsigned char SetOpClock(unsigned char ch, unsigned int OpClock)
{
volatile UART_REGS *pUartRegs;
volatile UART_CON *pUartCon;
if (ch > 2) return FALSE;
pUartCon = &UartCon[ch];
pUartRegs = (volatile UART_REGS *)(UART_REG_BASE+UART_REG_OFFSET*ch);
pUartCon->cOpClock = OpClock;
pUartRegs->rUCon &= ~(3<<10);
pUartRegs->rUCon |= (pUartCon->cOpClock<<10);
return TRUE;
}
//DataBit 0:5bit, 1:6bit, 2:7bit, 3:8bit
//ParityBit 0,1,2,3:no parity, 4:odd, 5:even, 6:forced 1, 7:forced 0
//StopBit 0:one stopbit, 1:two stopbit
unsigned char SetLineCon(unsigned char ch, unsigned char DataBit, unsigned char ParityBit, unsigned char StopBit)
{
volatile UART_REGS *pUartRegs;
volatile UART_CON *pUartCon;
if (ch > 2) return FALSE;
pUartCon = &UartCon[ch];
pUartRegs = (volatile UART_REGS *)(UART_REG_BASE+UART_REG_OFFSET*ch);
pUartCon->cDataBit = DataBit;
pUartCon->cParityBit = ParityBit;
pUartCon->cStopBit = StopBit;
pUartRegs->rUlCon = pUartRegs->rUlCon&(~0x3f) | (pUartCon->cParityBit<<3)|(pUartCon->cStopBit<<2)|(pUartCon->cDataBit);
return TRUE;
}
unsigned char SetDbgUart(unsigned char ch)
{
if (ch > 3) return FALSE;
memcpy(&UartCon[ch], &UartCon[4], sizeof(UART_CON));
UartOpen(ch,1);
return TRUE;
}
unsigned char UartOpen(unsigned char ch, unsigned int SetIRQ) // setting H/W & initializing regiter
{
if(SetIRQ)
{
pISR_UART0 = (unsigned)UartIsr0;
pISR_UART1 = (unsigned)UartIsr1;
pISR_UART2 = (unsigned)UartIsr2;
pISR_UART3 = (unsigned)UartIsr3;
pISR_DMA = (unsigned)DmaIsr;
}
switch(ch)
{
case 0 :
rGPHCON &= ~(0xf000f); // GPH0,1,8,9
rGPHCON |= 0xa000a; // Uart 0 Rx, Tx, Rts, Cts
if(InitializeUart(UART0_REG, &UartCon[0]) == SENDBREAK)
return SENDBREAK; // Initialize register set for Uart 0
break;
case 1 :
rGPHCON &= ~(0xf000f<<4); // GPH2,3,10,11
rGPHCON |= (0xa000a<<4); // Uart 1 Rx, Tx, Rts, Cts
if(InitializeUart(UART1_REG, &UartCon[1]) == SENDBREAK)
return SENDBREAK;
break;
case 2 :
rGPHCON &= ~(0xf<<6); // GPH4,5
rGPHCON |= (0xa<<6); // Uart 2 Rx, Tx
if(InitializeUart(UART2_REG, &UartCon[2]) == SENDBREAK)
return SENDBREAK;
break;
case 3 :
rGPHCON &= ~(0xf<<12); // GPH6,7
rGPHCON |= (0xa<<12); // Uart 3 Rx, Tx
if(InitializeUart(UART3_REG, &UartCon[3]) == SENDBREAK)
return SENDBREAK;
break;
default :
printf("Can't open UARTx!! Select 0,1, or 2!!");
return FALSE;
}
return TRUE;
}
unsigned char UartClose(unsigned char ch) // return to reset value
{
if (ch > 3) return FALSE;
rINTMSK |= (BIT_UART);
rINTSUBMSK |= (BIT_UART_ERROR<<SUBINTOFFSET)|(BIT_UART_TXD<<SUBINTOFFSET)|(BIT_UART_RXD<<SUBINTOFFSET);
rSUBSRCPND |= (BIT_UART_ERROR<<SUBINTOFFSET)|(BIT_UART_TXD<<SUBINTOFFSET)|(BIT_UART_RXD<<SUBINTOFFSET);
ClearPending(BIT_UART);
switch(ch)
{
case 0 :
rGPHCON &= ~(0xf000f); // GPH0,1,8,9
break;
case 1 :
rGPHCON &= ~(0xf000f<<4); // GPH2,3,10,11
break;
case 2 :
rGPHCON &= ~(0xf<<6); // GPH4,5
break;
case 3 :
rGPHCON &= ~(0xf<<12); // GPH6,7
break;
default :
printf("Can't close UARTx!! Select 0,1, or 2!!");
return FALSE;
}
return TRUE;
}
//---------------------------------------UART0 test function-------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -