I had been using the internal 12Mhz RC because the external crystal wasnt working. And by working I mean:
per lpc1778 manual:
with the appropriate bias caps CX1 and CX2, setting bits 4 (oscillator range select) and 5 (main oscillator enable) of the System Control and Status register should return read only bit 6 (oscillator status) as ready.
This wasnt happening and I thought perhaps it was because I chose 12pf for bias caps from an earlier crystal selection before I bought the 24Mhz versions on ebay.
The datasheet says using capacitor values 18pf or 39pf depending on crystal load capacitance. I ordered 18pf and 39pf 0603's on ebay. And replaced the 12pf on the board ... TO NO AVAIL
With phase 2 nearing completion (and me needing a precise crystal clock source for the SDRAM controller/USB interface and FPGA) I decided to revisit the schematic and noticed that I had shorted XTAL1 pin to ground via 0ohm resistor R13. Why I put that in the design I dont know ... and I have to go to storage to find the notebooks I made notes on when I designed this board.
What I do know is that it doesnt belong there. So I brought out my hot air tool and removed R13
Then I launched GDB to see if the oscillator status changes after I enable the logic driver and sure enough it does.
(gdb) monitor reset halt
JTAG tap: lpc1788.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Only resetting the Cortex-M core, use a reset-init event handler to reset any peripherals or configure hardware srst support.
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc
(gdb) monitor mdw 0x400fc1a0
0x400fc1a0: 00000009
(gdb) monitor mww 0x400fc1a0 0x39
(gdb) monitor mdw 0x400fc1a0
0x400fc1a0: 00000079
I removed R13 on the other spare EGWU board with CX1/CX2 bias caps of 12pf and tested it and it worked as well.
The next few days will be devoted to debugging UARTIO code and writing the YModem transfer code ... before delving in the SDRAM controller
Tuesday, August 25, 2015
Phase 2: Code posting guidelines
select all (text)
select font = times
leave text =large
this prevents wrap around
select font = times
leave text =large
this prevents wrap around
Phase 2: IE_egwu_uartio
/* ***************************************************************** *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
Phase 2: IE_egwu_setup
/* **************************************************************************** *name: IE_egwu_setup.h *author: Samuel Igwe *date: 06/30/2015 *description: pll/clock/iopin initialization **************************************************************************** */ #ifndef IE_EGWU_SETUP_H #define IE_EGWU_SETUP_H #include "chip.h" #include "chip_lpc177x_8x.h" #include "gpdma_17xx_40xx.h" #include "IE_egwu_uartio.h" /* ************************************************************************* *#defines ************************************************************************* */ #define EGWU_ONBOARD_UART LPC_UART1 #define EGWU_UART_BAUD_RATE 115200 #define LPC177X_NUM_INT 40 #define LPC177X_PREEMPT_PRIO_GROUP 2 #define EGWU_CPU_CLK_RATE 120000000 #define EGWU_CPU_OSC_RATE 24000000 #define EGWU_SYSTICK_RATE (EGWU_CPU_CLK_RATE/1000) #define LPC177X_SRAM_BASE 0x10000000 #define LPC_BILED_PORT 1 #define LPC_BILED_PIN1 23 #define LPC_BILED_PIN2 24 #define LPC_LED_PORT 1 #define LPC_LED_PIN 8 #define EGWU_NVIC_USER_BILED_MASK 0x1 #define EGWU_NVIC_FAULT_BILED_MASK 0x2 struct STR_EGWU_SYSTICK { volatile unsigned int wdSeconds; volatile unsigned int wdTicks; }strSysTick; #define MINIMUM_PERIPHERAL_IRQ_PRIORITY 3 enum egwu_int_pl { USB_INT_PL=MINIMUM_PERIPHERAL_IRQ_PRIORITY, UART_INT_PL, DMA_INT_PL, GPIO_INT_PL, WD_INT_PL}; extern int EGWU_IVT; const uint32_t OscRateIn; void (*ptrGpDmaUserIsr[GPDMA_NUMBER_CHANNELS])(void); unsigned int wdEnableGpDmaInt; /* ************************************************************************* *routines ************************************************************************* */ void setup_pll(void); void setup_nvic(void); void setup_gpio(void); void setup_uart(void); void nvic_systick_isr(void); void nvic_fault_isr(void); void nvic_user_isr(void); void gpio_set_lpc_biled(unsigned int wdLedMask); void setup_gpdma(void); void nvic_dma_isr(void); void gpdma_hook_chan_isr(int wdChannel,\ void (*ptrFunc)(void)); void gpdma_unhook_chan_isr(int wdChannel); void timer_delay_mS(int wdMs); #endif
/* **************************************************************************** *name: IE_egwu_setup.c *author: Samuel Igwe *date: 06/30/2015 *description: pll/clock/iopin initialization **************************************************************************** */ #ifndef IE_EGWU_SETUP_C #define IE_EGWU_SETUP_C #include "IE_egwu_setup.h" /* **************************************************************************** *description: pll/clock. *inputs: none *note: main pll (0) m=5 p=1 * pllin=24 pllout=120 fcco=240 * alt pll (1) m=2 p=2 * pllin=24 pllout48 fcco=192 * * the condition pllin = 1 < 25Mhz and fcco = 156 -> 320 has * has been satisfied * cpu = 120Mhz * emc = 60Mhz * gpio= 40Mhz * * when using the internal oscillator aim for 120Mhz as well * main pll (0) m=10 p=1 * pllin=12 pllout=120 fcco=240 **************************************************************************** */ void setup_pll(void) { /* ************************************************************************ *switch to using default clock source ************************************************************************ */ Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_IRC); Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_SYSCLK); Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE); Chip_Clock_DisablePLL(SYSCTL_USB_PLL, SYSCTL_PLL_ENABLE); /* ************************************************************************ *use the internal rc clock for phase 1 and 2, while await replacement *caps for the crystal oscillator driver ************************************************************************ */ #ifdef EXT_CLK Chip_Clock_SetCrystalRangeHi(); Chip_Clock_EnableCrystal(); if((Chip_Clock_IsCrystalEnabled()) == TRUE) Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL); Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 5, 1); Chip_Clock_SetupPLL(SYSCTL_USB_PLL, 2, 2); Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE); Chip_Clock_EnablePLL(SYSCTL_USB_PLL, SYSCTL_PLL_ENABLE); #else Chip_Clock_SetupPLL(SYSCTL_MAIN_PLL, 10, 1); Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_ENABLE); #endif /* ************************************************************************ *delay a bit to let the logic do its thing ************************************************************************ */ while(Chip_Clock_IsMainPLLLocked() == 0) ; #ifdef EXT_CLK Chip_Clock_SetMainPLLSource(SYSCTL_PLLCLKSRC_MAINOSC); while(Chip_Clock_IsUSBPLLLocked() == 0) ; #endif /* ************************************************************************ *resume initialization ************************************************************************ */ Chip_Clock_SetCPUClockDiv(1); Chip_Clock_SetCPUClockSource(SYSCTL_CCLKSRC_MAINPLL); #ifdef EXT_CLK Chip_Clock_SetUSBClockDiv(1); Chip_Clock_SetUSBClockSource(SYSCTL_USBCLKSRC_USBPLL); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB); #endif Chip_Clock_SetPCLKDiv(3); /* ************************************************************************ *enable all the peripherals ************************************************************************ */ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_TIMER0); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_TIMER1); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART0); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART1); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_RTC); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_EMC); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C0); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C1); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2C2); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SSP0); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SSP1); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPDMA); Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPIO); /* ************************************************************************ *enable emc and clkout ************************************************************************ */ Chip_Clock_SetEMCClockDiv(SYSCTL_EMC_DIV2); Chip_Clock_SetCLKOUTSource(SYSCTL_CLKOUTSRC_MAINOSC, 3); Chip_Clock_EnableCLKOUT(); } /* **************************************************************************** *description: configure nvic *inputs: none *notes: assume vector table is the global "ivt" * skip stack and reset positions * default isrs * nvic_fault_isr() * nvic_systic_isr() * nvic_user_isr() **************************************************************************** */ void setup_nvic(void) { volatile unsigned int wdTemp, *ptrTemp; volatile int wdCount; ptrTemp = (volatile unsigned int *)&EGWU_IVT; for(wdCount = 2; wdCount < (LPC177X_NUM_INT + 16); wdCount++) { if(wdCount < 15) /*faults*/ wdTemp = (int) nvic_fault_isr; else { switch(wdCount) { case 15: /*systick*/ wdTemp = (int) nvic_systick_isr; break; case 42: /*dma*/ wdTemp = (int) nvic_dma_isr; break; default: wdTemp = (int) nvic_user_isr; break; } } wdTemp |= 1; /*thumb - mandatory*/ *(ptrTemp + wdCount) = wdTemp; } /* ************************************************************************ *selecting nvic priority group 2 (there are 32 pre-rempt priority *levels on the lpc17xx) *[7:3] = preempt priority field (5 bits) *[2:0] = sub priority field (3 bits) * *this allows me to allocate 32 interrupt priority levels thought I doubt *Id use that many interrupts in this project but one never knows * *for now set interrupts (system handler priority) *4 + 5 + 6 to priority level 0 *11+14 to priority level 1 *15 (systick)to priority level 2 *(peripherals interrupt) *26 (dma) to priority level 3 *interrupts 1 through 3 are fixed (reset to fault) *set to rest to maximum priority (0xff) ************************************************************************ */ NVIC_SetPriorityGrouping(LPC177X_PREEMPT_PRIO_GROUP); for (wdCount = MemoryManagement_IRQn; wdCount < (LPC177X_NUM_INT); wdCount++) { switch(wdCount) { case UsageFault_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 0, 0); break; case SVCall_IRQn: case PendSV_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 1, 0); break; case SysTick_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 2, 0); break; case DMA_IRQn: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 3, 0); break; default: wdTemp = NVIC_EncodePriority(LPC177X_PREEMPT_PRIO_GROUP, 9, 0); break; } NVIC_SetPriority(wdCount, wdTemp); } /* ************************************************************************ *setup systick timer for 1mS tick *configure variables ************************************************************************ */ strSysTick.wdSeconds = 0; strSysTick.wdTicks = 0; SysTick_Config(EGWU_CPU_CLK_RATE/1000); /* ************************************************************************ *cpu synchronization ************************************************************************ */ asm("dsb"); asm("isb"); /* ************************************************************************ *enable mem/bus/usage fault interrupts ************************************************************************ */ wdTemp = SCB_SHCSR_MEMFAULTENA_Msk; wdTemp |= SCB_SHCSR_BUSFAULTENA_Msk; wdTemp |= SCB_SHCSR_USGFAULTENA_Msk; SCB->SHCSR = wdTemp; /* ************************************************************************ *remap vector table *enable interrupts on the processor level ************************************************************************ */ SCB->VTOR = LPC177X_SRAM_BASE; asm("cpsie i"); } /* **************************************************************************** *description: gpio configuration *inputs: none *note: mapping is as follows * p0[00] - p0[01] = fx4 =uart0 * p0[02] - p0[11] = fx2 =sspi + i2c * p0[12] - p0[13] = fx1 =usb * p0[15] - p0[18] = fx2 =spi * p0[23] - p0[25] = fx1 =adc * p0[26] = fx2 =dac * p0[30] = fx0 =gpio1 * p0[31] = fx1 =usb * * p1[02] - p1[10] = fx0 =gpio * p1[11] - p1[12] = fx3 =pwm * p1[14] = fx0 =gpio * p1[18] - p1[19] = fx0 =gpio3 and gpio4 * p1[23] - p1[24] = fx0 =gpio (bi-led anode) * p1[27] = fx4 =clkout * p1[30] - p1[31] = fx1 =usb * * p2[00] - p[01] = fx1 =uart1 * * p2[10] = fx0 =isp_mode (dont use) * p2[11] = fx1 =gbl_int * * p2[14] - p2[31] = fx1 =emc * * p3[00] - p3[31] = fx0 =emc * * p4[00] - p4[31] = fx0 =emc * * p5[00] - p5[01] = fx0 =emc **************************************************************************** */ void setup_gpio(void) { volatile unsigned int wdCount; /* ************************************************************************ *port 3 and port 4 to function 1 and port 2 (14-31) ************************************************************************ */ for(wdCount = 0; wdCount < 32; wdCount++) { Chip_IOCON_PinMuxSet(LPC_IOCON, 3, wdCount, IOCON_FUNC1); Chip_IOCON_PinMuxSet(LPC_IOCON, 4, wdCount, IOCON_FUNC1); if(wdCount >= 14) Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC1); } /* ************************************************************************ *port 0 ************************************************************************ */ for(wdCount = 0; wdCount < 32; wdCount++) { if(wdCount <= 1) Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC4); else { if((wdCount >= 6 && wdCount <= 11) || (wdCount >= 15 && wdCount <= 18) || (wdCount == 26)) Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC2); else { if((wdCount >= 12 && wdCount <= 13) || (wdCount >= 23 && wdCount <= 25) || (wdCount == 31)) Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC1); else { if(wdCount == 30) Chip_IOCON_PinMuxSet(LPC_IOCON, 0, wdCount, IOCON_FUNC0); } } } } /* ************************************************************************ *port 1 ************************************************************************ */ for(wdCount = 0; wdCount < 32; wdCount++) { if((wdCount >= 2 && wdCount <= 10) || (wdCount >= 18 && wdCount <= 19) || (wdCount >= 23 && wdCount <= 24) || (wdCount == 14)) Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC0); else { if(wdCount >= 11 && wdCount <= 12) Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC3); else { if(wdCount >= 30 && wdCount <= 31) Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC1); else { if(wdCount == 27) Chip_IOCON_PinMuxSet(LPC_IOCON, 1, wdCount, IOCON_FUNC4); } } } } /* ************************************************************************ *port 2 ************************************************************************ */ for(wdCount = 0; wdCount < 14; wdCount++) { if(wdCount <= 1) Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC2); else { if(wdCount >= 14) Chip_IOCON_PinMuxSet(LPC_IOCON, 2, wdCount, IOCON_FUNC1); } } /* ************************************************************************ *set direction for ports configured as gpio ************************************************************************ */ //Chip_GPIO_SetPinDIRInput(LPC_GPIO, 0, 30); Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 30); for(wdCount =0; wdCount < 32; wdCount++) { switch(wdCount) { case 2: case 5: case 9: case 10: case 14: { Chip_GPIO_SetPinDIRInput(LPC_GPIO, 1, wdCount); break; } case 3: case 4: case 6: case 7: case 8: case 18: case 19: case 23: case 24: { Chip_GPIO_SetPinDIROutput(LPC_GPIO, 1, wdCount); break; } } } } /* **************************************************************************** *description: uart configuration *inputs: none *notes: using 40Mhz peripheral clock (cpuclock/3) to derive 115200 baud **************************************************************************** */ void setup_uart(void) { volatile unsigned int wdTemp; /* ************************************************************************ *governing formula is as follows: *Uart(baudrate) = PCLK (40Mhz)/16 x (256 x DLM) + DLL x (1 + DivVal/MulVal) *constraints * 1 <= MulVal <= 15 * 0 <= DivAddVal <= 14 * DivAddVal < MulVal *[for 115200] ************************************************************************ *115200 = 40Mhz/16 x [(256 x DLM) + DLL x (1 + D/M) *115200 = 40Mhz/16 x DLest *DLest = 21.7 *FRest = 1.5 ************************************************************************ *DLest = INT(40Mhz/(16 x 115200 x FRest) *FRest = 40Mhz/(16 x 115200 x DLest) ************************************************************************ *DLest = INT(14.46) = 14 *FRest = 1.55 ************************************************************************ *this satisfies the condition 1.1 < Frest < 1.9 *DL = INT(40Mhz/(16 x 115200 x 1.55) = 14 *DL*FR = 14 x 1.55 = 21.7 ************************************************************************ *from the table *DivAdd = 5 *MulVal = 9 * *determined later that the values 6/7 work best for this osc and board ************************************************************************ *[for 9600] ************************************************************************ *9600 = 40Mhz/16 x [(256 x DLM) + DLL x (1 + D/M) *9600 = 40Mhz/16 x DLest *DLest = 260.41 *FRest = 1.5 ************************************************************************ *DLest = INT(40Mhz/(16 x 9600 x FRest) *FRest = 40Mhz/(16 x 9600 x DLest) ************************************************************************ *DLest = INT(173.61) = 173 *FRest = 1.505 ************************************************************************ *this satisfies the condition 1.1 < Frest < 1.9 *DL = INT(40Mhz/(16 x 9600 x 1.505) = 173.03 *DL*FR = 173 x 1.505 = 260.365 ************************************************************************ *from the table *DivAdd = 5 *MulVal = 9 ************************************************************************ */ #if (EGWU_UART_BAUD_RATE == 115200) Chip_UART_EnableDivisorAccess(EGWU_ONBOARD_UART); Chip_UART_SetDivisorLatches(EGWU_ONBOARD_UART, 14, 0); Chip_UART_DisableDivisorAccess(EGWU_ONBOARD_UART); /* ************************************************************************ *8-N-1 ************************************************************************ */ wdTemp = UART_LCR_WLEN8; wdTemp |= UART_LCR_SBS_1BIT; wdTemp |= UART_LCR_PARITY_DIS; Chip_UART_ConfigData(EGWU_ONBOARD_UART, wdTemp); EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(7) | UART_FDR_DIVADDVAL(6)); #else Chip_UART_EnableDivisorAccess(EGWU_ONBOARD_UART); Chip_UART_SetDivisorLatches(EGWU_ONBOARD_UART, 173, 0); Chip_UART_DisableDivisorAccess(EGWU_ONBOARD_UART); /* ************************************************************************ *8-N-1 ************************************************************************ */ wdTemp = UART_LCR_WLEN8; wdTemp |= UART_LCR_SBS_1BIT; wdTemp |= UART_LCR_PARITY_DIS; Chip_UART_ConfigData(EGWU_ONBOARD_UART, wdTemp); //EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(1) | UART_FDR_DIVADDVAL(0)); #ifdef DIVADDVAL EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(MULVAL) | UART_FDR_DIVADDVAL(DIVADDVAL)); #else EGWU_ONBOARD_UART->FDR = (UART_FDR_MULVAL(9) | UART_FDR_DIVADDVAL(5)); #endif #endif /* ************************************************************************ *reset RX and TX blocks and enable fifos ************************************************************************ */ wdTemp = UART_FCR_FIFO_EN; wdTemp |= UART_FCR_RX_RS; wdTemp |= UART_FCR_TX_RS; wdTemp |= UART_FCR_TRG_LEV1; wdTemp |= UART_FCR_DMAMODE_SEL; Chip_UART_SetupFIFOS(EGWU_ONBOARD_UART, wdTemp); Chip_UART_TXEnable(EGWU_ONBOARD_UART); /* ************************************************************************ *enable interrupts ************************************************************************ */ wdTemp = UART_IER_RBRINT; Chip_UART_IntEnable(EGWU_ONBOARD_UART, wdTemp); } /* **************************************************************************** *description: nvic systic handler *inputs: none *note: toggle P1[8] = 190 uC led used as heartbeat monitor **************************************************************************** */ void nvic_systick_isr(void) { volatile unsigned int wdTemp; strSysTick.wdTicks++; if(strSysTick.wdTicks == 1000) { strSysTick.wdTicks = 0; strSysTick.wdSeconds++; //wdTemp = Chip_GPIO_GetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN); //Chip_GPIO_SetPinState(LPC_GPIO1, LPC_LED_PORT, LPC_LED_PIN, wdTemp); wdTemp = (((LPC_GPIO1->PIN) >> LPC_LED_PIN) & 0x1); wdTemp ^= 0x1; if(wdTemp == 0) (LPC_GPIO1->CLR) = (1 << LPC_LED_PIN); else (LPC_GPIO1->SET) = (1 << LPC_LED_PIN); uartio_tx_flush(); } } /* **************************************************************************** *description: nvic fault handler *inputs: none **************************************************************************** */ void nvic_fault_isr(void) { gpio_set_lpc_biled(EGWU_NVIC_FAULT_BILED_MASK); } /* **************************************************************************** *description: nvic user handler *inputs: none **************************************************************************** */ void nvic_user_isr(void) { gpio_set_lpc_biled(EGWU_NVIC_USER_BILED_MASK); } /* **************************************************************************** *description: set the bi-led connected to the LPC *inputs: unsigned int wdLedMask = led mask only lower two bits matter **************************************************************************** */ void gpio_set_lpc_biled(unsigned int wdLedMask) { wdLedMask &= 0x3; Chip_GPIO_SetPinState(LPC_GPIO, LPC_BILED_PORT, LPC_BILED_PIN1, wdLedMask); Chip_GPIO_SetPinState(LPC_GPIO, LPC_BILED_PORT, LPC_BILED_PIN2, (wdLedMask >> 1)); } /* ***************************************************************** *description: configure the gpdma peripheral * set array of pointers to int to 0 then init gpdma ***************************************************************** */ void setup_gpdma(void) { volatile unsigned int wdCount; for(wdCount=0; wdCount < GPDMA_NUMBER_CHANNELS; wdCount++) *(ptrGpDmaUserIsr + wdCount) = 0; wdEnableGpDmaInt = 0; Chip_GPDMA_Init(LPC_GPDMA); } /* ***************************************************************** *description: channel isr call back ***************************************************************** */ void nvic_dma_isr(void) { volatile unsigned int wdCount; for(wdCount=0; wdCount <GPDMA_NUMBER_CHANNELS; wdCount++) { if((Chip_GPDMA_Interrupt(LPC_GPDMA, wdCount) == SUCCESS) &&\ ptrGpDmaUserIsr[wdCount] != NULL) ptrGpDmaUserIsr[wdCount](); } } /* ***************************************************************** *description: hook channel ISR *inputs: int wdChannel = 0 to GPDMA_NUMBER_CHANNELS * void (*ptrFunc)(void) = pointer to callback function ***************************************************************** */ void gpdma_hook_chan_isr(int wdChannel, \ void (*ptrFunc)(void)) { if(ptrGpDmaUserIsr[wdChannel] == NULL) { ptrGpDmaUserIsr[wdChannel] = ptrFunc; wdEnableGpDmaInt++; NVIC_EnableIRQ(DMA_IRQn); } } /* ***************************************************************** *description: unhook channel ISR *input: int wdChannel = 0 to GPDMA_NUMBER_CHANNELS ***************************************************************** */ void gpdma_unhook_chan_isr(int wdChannel) { if(wdChannel >= GPDMA_NUMBER_CHANNELS) return; ptrGpDmaUserIsr[wdChannel] = 0; wdEnableGpDmaInt--; if(wdEnableGpDmaInt == 0) NVIC_DisableIRQ(DMA_IRQn); } /* ***************************************************************** *description: mS delay using TIMER0 *input: int wdMs = number of milliseconds to delay *note: peripheral clock is 40Mhz ***************************************************************** */ void timer_delay_mS(int wdMs) { volatile unsigned int wdTemp; Chip_TIMER_Reset(LPC_TIMER0); Chip_TIMER_Disable(LPC_TIMER0); Chip_TIMER_PrescaleSet(LPC_TIMER0, 40000); Chip_TIMER_SetMatch(LPC_TIMER0, 0, wdMs); Chip_TIMER_StopOnMatchEnable(LPC_TIMER0, 0); Chip_TIMER_Enable(LPC_TIMER0); do { wdTemp = Chip_TIMER_ReadCount(LPC_TIMER0); }while(wdTemp != wdMs); } #endif
Sunday, August 9, 2015
Phase 2: Overview
modifications to IE_setup.c/.h and uartio.c/.h
the goal is to create buffered and unbuffered version of the various input and output routines that involve the uart. dma will manage one half of the swinging buffer while user is interacting with the other.
in addition create a means to implement the xmodem protocol towards the end. I actually implemented xmodem completely in mc6800 assembly years ago so doing so in C should be too tasking.
IE_setup.c
create
egwu_setup_gpdma
generic gpdma configuration routines
egwu_nvic_gpdma_isr
call table for all 8 channels using pointer to void function
egwu_dma_hook_channel_isr
add user isr to call table above
egwu_dma_unhook_channel_isr
remove user isr from call table above
IE_uartio.c
create
egwu_uartio_fflush
uses dma transfer to clear out one half of the tx swinging buffer
egwu_uartio_tx_dma_isr
user isr to hook unto gpdma isr call table (for any of 8 channels)
egwu_uartio_printf/putc
printf will be buffered
putc will be unbuffered
egwu_uartio_getc/getch/gets
for now gets will be unbuffered but that might change
getc and getch will be unbuffered with the latter simply looking at the
rx fifo flag and returning a code indicating presence or absence of a
key/character
the goal is to create buffered and unbuffered version of the various input and output routines that involve the uart. dma will manage one half of the swinging buffer while user is interacting with the other.
in addition create a means to implement the xmodem protocol towards the end. I actually implemented xmodem completely in mc6800 assembly years ago so doing so in C should be too tasking.
IE_setup.c
create
egwu_setup_gpdma
generic gpdma configuration routines
egwu_nvic_gpdma_isr
call table for all 8 channels using pointer to void function
egwu_dma_hook_channel_isr
add user isr to call table above
egwu_dma_unhook_channel_isr
remove user isr from call table above
IE_uartio.c
create
egwu_uartio_fflush
uses dma transfer to clear out one half of the tx swinging buffer
egwu_uartio_tx_dma_isr
user isr to hook unto gpdma isr call table (for any of 8 channels)
egwu_uartio_printf/putc
printf will be buffered
putc will be unbuffered
egwu_uartio_getc/getch/gets
for now gets will be unbuffered but that might change
getc and getch will be unbuffered with the latter simply looking at the
rx fifo flag and returning a code indicating presence or absence of a
key/character
Subscribe to:
Posts (Atom)