/*
*****************************************************************
*name: IE_egwu_uartio.h
*author: Samuel Igwe
*date: 08/25/2015
*description: IE_egwu_uartio header.
*****************************************************************
*/
#ifndef IE_EGWU_UARTIO_H
#define IE_EGWU_UARTIO_H
#include "chip.h"
#include "chip_lpc177x_8x.h"
#include "uart_17xx_40xx.h"
#include "IE_tclib.h"
#include "IE_egwu_setup.h"
#define EGWU_UART_BUF_SIZE 80
#define ASCII_BS 8
#define ASCII_TAB 9
#define ASCII_LF 10
#define ASCII_CR 13
#define ASCII_ESC 27
#define ASCII_SPACE 32
#define ASCII_DEL 127
struct STR_UART_BUFFER {
volatile unsigned int wdTopMutex, wdTopIndex;
volatile unsigned int wdBotMutex, wdBotIndex;
volatile unsigned int *ptrUsrIndex,*ptrUsrMutex;
volatile unsigned int *ptrDmaMutex;
volatile unsigned char sbTopBuf[EGWU_UART_BUF_SIZE+1];
volatile unsigned char sbBotBuf[EGWU_UART_BUF_SIZE+1];
volatile unsigned char *ptrUsrBuf;
}strUartTxBuf;
/*
*********************************************************
*routines
*********************************************************
*/
char uartio_getch(void);
char uartio_getc(void);
int uartio_gets(char *ptrString, int wdSize);
int uartio_tx_flush(void);
void setup_uartio(void);
void uartio_putc(char byByte);
void uartio_dma_isr(void);
void uartio_puts(char *ptrString, int wdStrlen);
void uartio_printf(char *ptrString, int wdValue);
void test_determine_fractional_divider_values(void);
#endif
/*
*****************************************************************
*name: IE_egwu_uartio.c
*author: Samuel Igwe
*date: 08/25/2015
*description: uartio support functions. sets up call
* back array of functions for dealing with gpdma
* channel interrupts
*****************************************************************
*/
#ifndef IE_EGWU_UARTIO_C
#define IE_EGWU_UARTIO_C
#include "IE_egwu_uartio.h"
/*
*****************************************************************
*description: initialization routine
* dont forget to initialize ptrDmaMutex
*****************************************************************
*/
void
setup_uartio(void)
{
tclib_memset((unsigned char *)&strUartTxBuf, 0, sizeof(strUartTxBuf));
strUartTxBuf.ptrUsrBuf = strUartTxBuf.sbTopBuf;
strUartTxBuf.ptrUsrIndex= &strUartTxBuf.wdTopIndex;
strUartTxBuf.ptrUsrMutex= &strUartTxBuf.wdTopMutex;
strUartTxBuf.ptrDmaMutex= &strUartTxBuf.wdTopMutex;
}
/*
*****************************************************************
*description: getch routine. non blocking read
*output: 0 on error or valid char
*****************************************************************
*/
char
uartio_getch(void)
{
volatile unsigned int wdTemp;
wdTemp = Chip_UART_ReadLineStatus(EGWU_ONBOARD_UART);
if((wdTemp & UART_LSR_RDR) == 0)
return 0;
else
{
wdTemp = Chip_UART_ReadByte(EGWU_ONBOARD_UART);
return wdTemp;
}
}
/*
*****************************************************************
*description: getc routine.
*output: valid char
*****************************************************************
*/
char
uartio_getc(void)
{
volatile unsigned int wdTemp;
do
{
wdTemp = Chip_UART_ReadLineStatus(EGWU_ONBOARD_UART);
wdTemp &= UART_LSR_RDR;
}while(wdTemp == 0);
wdTemp = Chip_UART_ReadByte(EGWU_ONBOARD_UART);
return wdTemp;
}
/*
*****************************************************************
*description: putc routine.
*input: char byByte
*****************************************************************
*/
void
uartio_putc(char byByte)
{
volatile unsigned int wdTemp;
Chip_UART_SendByte(EGWU_ONBOARD_UART, byByte);
do
{
wdTemp = Chip_UART_ReadLineStatus(EGWU_ONBOARD_UART);
//wdTemp &= (UART_LSR_TEMT | UART_LSR_THRE);
wdTemp &= UART_LSR_TEMT;
}while(wdTemp != UART_LSR_TEMT);
}
/*
*****************************************************************
*description: gets routine.
*inputs: char *ptrString
* int wdSize
*output: int string length
*note: echo back typed characters
*****************************************************************
*/
int
uartio_gets(char *ptrString, int wdSize)
{
volatile unsigned char wdByte;
volatile unsigned int wdStrlen = 0;
while(wdSize > 0)
{
wdByte = uartio_getc();
switch(wdByte)
{
case ASCII_CR:
case ASCII_ESC:
{
*(ptrString + wdStrlen) = 0;
return wdStrlen;
}
case ASCII_BS:
{
if(wdStrlen > 0)
{
uartio_putc(ASCII_BS);
wdStrlen--;
}
break;
}
case ASCII_DEL:
{
*(ptrString + wdStrlen) = 0;
break;
}
default:
{
*(ptrString + wdStrlen) = wdByte;
uartio_putc(wdByte);
wdStrlen++;
wdSize--;
break;
}
}
}
*(ptrString + wdStrlen) = 0;
return wdStrlen;
}
/*
*****************************************************************
*description: uartio dma isr
*note: a) clear index
* b) swap pointers
* c) release mutex
*****************************************************************
*/
void
uartio_dma_isr(void)
{
tclib_release_semaphore((unsigned int *)(strUartTxBuf.ptrDmaMutex));
}
/*
*****************************************************************
*description: uartio tx flush routine. can be called by timer
* (systick) isr as well as uartio_puts()
*
*notes: check strUartTxBuf.ptrUsrIndex != 0
* a) attempt to acquire the mutex
* b) if unsuccessful return -1
* c) if successful proceed
* d) request dma channel
* e) call nvic_dma_hook_isr_to_chan()
* f) program dma to generate int on complete
* g) set ptrUsr* pointers to the other half buffers
* h) clear *ptrIndex to 0
* i) return 0
*
* j) dont NOT busy poll in this routine since it is
* called both by uartio_puts() and the systick
* handler every 1mS
* k) to prevent race condition of dual dma channels
* writing to uart tx ... examine ptrDmaMutex in
* uartio_tx_flush
* l) uartio_tx_flush should return 0 on success -1
* otherwise
*****************************************************************
*/
int
uartio_tx_flush(void)
{
volatile unsigned int wdTemp, wdChan;
if(*(strUartTxBuf.ptrUsrIndex) == 0)
return 0;
/*check to see if a dma is in operation*/
if(*(strUartTxBuf.ptrDmaMutex) != 0)
return -1;
if((tclib_acquire_semaphore((unsigned int *)strUartTxBuf.ptrUsrMutex)) == 0)
return -1;
else
strUartTxBuf.ptrDmaMutex = strUartTxBuf.ptrUsrMutex;
wdChan = Chip_GPDMA_GetFreeChannel(LPC_GPDMA, 0);
gpdma_hook_chan_isr(wdChan, uartio_dma_isr);
/*
*************************************************************
*program dma controller
*************************************************************
*/
LPC_GPDMA->INTTCCLEAR = (1 << wdChan);
LPC_GPDMA->INTERRCLR = (1 << wdChan);
LPC_GPDMA->CH[wdChan].SRCADDR = (unsigned int)strUartTxBuf.ptrUsrBuf;
LPC_GPDMA->CH[wdChan].DESTADDR= (unsigned int)&LPC_UART1->THR;
LPC_GPDMA->CH[wdChan].LLI = 0;
wdTemp = (*strUartTxBuf.ptrUsrIndex);
wdTemp |= GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_1);
wdTemp |= GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_1);
wdTemp |= GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_BYTE);
wdTemp |= GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_BYTE);
wdTemp |= GPDMA_DMACCxControl_SI;
wdTemp |= GPDMA_DMACCxControl_I;
LPC_GPDMA->CH[wdChan].CONTROL = wdTemp;
wdTemp = GPDMA_DMACCxConfig_DestPeripheral(GPDMA_CONN_UART1_Tx);
wdTemp |= GPDMA_DMACCxConfig_TransferType(GPDMA_TRANSFERTYPE_M2P_CONTROLLER_DMA);
wdTemp |= GPDMA_DMACCxConfig_IE;
wdTemp |= GPDMA_DMACCxConfig_ITC;
wdTemp |= GPDMA_DMACCxConfig_E;
LPC_GPDMA->CH[wdChan].CONFIG = wdTemp;
wdTemp = GPDMA_DMACConfig_E;
LPC_GPDMA->CONFIG = wdTemp;
*(strUartTxBuf.ptrUsrIndex) = 0;
if(strUartTxBuf.ptrUsrIndex == &strUartTxBuf.wdTopIndex)
{
strUartTxBuf.ptrUsrBuf = strUartTxBuf.sbBotBuf;
strUartTxBuf.ptrUsrIndex= &strUartTxBuf.wdBotIndex;
strUartTxBuf.ptrUsrMutex= &strUartTxBuf.wdBotMutex;
}
else
{
strUartTxBuf.ptrUsrBuf = strUartTxBuf.sbTopBuf;
strUartTxBuf.ptrUsrIndex= &strUartTxBuf.wdTopIndex;
strUartTxBuf.ptrUsrMutex= &strUartTxBuf.wdTopMutex;
}
return 0;
}
/*
*****************************************************************
*description: puts routine.
*inputs: char *ptrString = pointer to string
* int wdLen = number of characters to print
*****************************************************************
*/
void
uartio_puts(char *ptrString, int wdLen)
{
volatile unsigned int **ptrMutex, **ptrIndex, wdTemp;
volatile unsigned char **ptrBuf;
ptrMutex = &(strUartTxBuf.ptrUsrMutex);
ptrIndex = &(strUartTxBuf.ptrUsrIndex);
ptrBuf = &(strUartTxBuf.ptrUsrBuf);
do
{
wdTemp = tclib_acquire_semaphore((unsigned int *)*ptrMutex);
}while(wdTemp == 0);
while((wdLen--) >= 0)
{
if((**ptrIndex) != EGWU_UART_BUF_SIZE)
{
*((*ptrBuf) + (**ptrIndex)) = *ptrString;
ptrString++;
(**ptrIndex)++;
}
else
{
tclib_release_semaphore((unsigned int *)*ptrMutex);
while(uartio_tx_flush() !=0)
;
do
{
wdTemp = tclib_acquire_semaphore((unsigned int *)*ptrMutex);
}while(wdTemp == 0);
}
}
tclib_release_semaphore((unsigned int *)*ptrMutex);
}
/*
*****************************************************************
*description: printf routine.
*inputs: char *ptrString = null terminated string
* int wdValue = %d/%x value
*****************************************************************
*/
void
uartio_printf(char *ptrString, int wdValue)
{
volatile unsigned int wdOffset, wdTemp;
volatile char byChar, *ptrBase, sbTemp[20+1];
ptrBase = ptrString;
wdOffset= 0;
while(*(ptrBase + wdOffset) !=0)
{
byChar = *(ptrBase + wdOffset);
switch(byChar)
{
case '%':
{
if(wdOffset > 0)
{
uartio_puts((char *)ptrBase, (wdOffset-1));
ptrBase += wdOffset;
wdOffset = 0;
}
ptrBase++;
wdOffset = 0;
if(*(ptrBase + wdOffset) == 0)
return;
byChar = *(ptrBase + wdOffset);
ptrBase++;
switch(byChar)
{
case 'd':
case 'x':
{
tclib_itoa((unsigned int)wdValue, (unsigned char *)sbTemp);
wdTemp = tclib_strlen((unsigned char *)sbTemp);
uartio_puts((char *)sbTemp, wdTemp);
break;
}
case 'c':
{
ptrBase--;
*(ptrBase) = (unsigned char)wdValue;
wdOffset++;
break;
}
case 's':
{
wdTemp = tclib_strlen((unsigned char *)wdValue);
uartio_puts((char *)wdValue, wdTemp);
break;
}
default:
{
wdOffset++;
break;
}
}
break;
}
default:
{
wdOffset++;
break;
}
}
}
if(wdOffset > 0)
uartio_puts((char *)ptrBase, wdOffset);
}
/*
***********************************************************************
description: fractional divider test routine. used to tweak the uart
baud rate clock
notes: for this to work - put a paper clip between pin 2(rx)
and pin 3(tx) of the serial cable. which effectively
creates a loop back.
then set a break point where the "if" test of the data
read back evaluates as true
***********************************************************************
*/
void
test_determine_fractional_divider_values(void)
{
volatile unsigned int wdTemp, wdCount, wdErrorFlag;
volatile unsigned int wdMulVal, wdDivAddVal;
const int wdTestVal='0';
/*
*******************************************************************
cycle through the 14 x 15 fractional divider values
reset RX fifo
wait 1mS after setting fractional dividers
write and read back three values in succession
turn on flag if any error
evaluate results
*******************************************************************
*/
for(wdMulVal = 1; wdMulVal <= 15; wdMulVal++)
{
for(wdDivAddVal = 0; wdDivAddVal <= 15; wdDivAddVal++)
{
wdTemp = (wdMulVal << 4);
wdTemp |= wdDivAddVal;
EGWU_ONBOARD_UART->FDR = wdTemp;
timer_delay_mS(1);
EGWU_ONBOARD_UART->FCR |= UART_FCR_RX_RS;
for(wdCount = 0, wdErrorFlag = 0; wdCount < 3; wdCount++)
{
uartio_putc(wdTestVal + wdCount);
//if((uartio_getc()) != (wdTestVal + wdCount))
// wdErrorFlag++;
}
if(wdErrorFlag == 0)
{
uartio_putc(wdMulVal);
uartio_putc(wdDivAddVal);
}
}
}
/*
*******************************************************************
flash bi-LED in a sequence every 500mS
*******************************************************************
*/
do
{
wdTemp++;
gpio_set_lpc_biled(wdTemp);
timer_delay_mS(1000);
}while(0);
}
#endif
No comments:
Post a Comment