/* ***************************************************************** *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