Port of Keils USBCDC example, compiles ok. Gets stuck at init

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers serial.c Source File

serial.c

00001 /*----------------------------------------------------------------------------
00002  *      Name:    serial.c
00003  *      Purpose: serial port handling for LPC17xx
00004  *      Version: V1.20
00005  *----------------------------------------------------------------------------
00006  *      This software is supplied "AS IS" without any warranties, express,
00007  *      implied or statutory, including but not limited to the implied
00008  *      warranties of fitness for purpose, satisfactory quality and
00009  *      noninfringement. Keil extends you a royalty-free right to reproduce
00010  *      and distribute executable files created using this software for use
00011  *      on NXP Semiconductors LPC microcontroller devices only. Nothing else 
00012  *      gives you the right to use this software.
00013  *
00014  * Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
00015  *---------------------------------------------------------------------------*/
00016 #include "LPC17xx.h"                                   // LPC17xx definitions
00017 //#include "LPC23xx.h"
00018 #include "type.h"
00019 #include "serial.h"
00020 
00021 #include "compatible.h"
00022 
00023 /*----------------------------------------------------------------------------
00024   Defines for ring buffers
00025  *---------------------------------------------------------------------------*/
00026 #define SER_BUF_SIZE               (128)               // serial buffer in bytes (power 2)
00027 #define SER_BUF_MASK               (SER_BUF_SIZE-1ul)  // buffer size mask
00028 
00029 /* Buffer read / write macros */
00030 #define SER_BUF_RESET(serBuf)      (serBuf.rdIdx = serBuf.wrIdx = 0)
00031 #define SER_BUF_WR(serBuf, dataIn) (serBuf.data[SER_BUF_MASK & serBuf.wrIdx++] = (dataIn))
00032 #define SER_BUF_RD(serBuf)         (serBuf.data[SER_BUF_MASK & serBuf.rdIdx++])   
00033 #define SER_BUF_EMPTY(serBuf)      (serBuf.rdIdx == serBuf.wrIdx)
00034 #define SER_BUF_FULL(serBuf)       (serBuf.rdIdx == serBuf.wrIdx+1)
00035 #define SER_BUF_COUNT(serBuf)      (SER_BUF_MASK & (serBuf.wrIdx - serBuf.rdIdx))
00036 
00037 // buffer type
00038 typedef struct __SER_BUF_T {
00039   unsigned char data[SER_BUF_SIZE];
00040   unsigned int wrIdx;
00041   unsigned int rdIdx;
00042 } SER_BUF_T;
00043 
00044 unsigned long          ser_txRestart;                  // NZ if TX restart is required
00045 unsigned short         ser_lineState;                  // ((msr << 8) | (lsr))
00046 SER_BUF_T              ser_out;                        // Serial data buffers
00047 SER_BUF_T              ser_in;
00048 
00049 /*----------------------------------------------------------------------------
00050   open the serial port
00051  *---------------------------------------------------------------------------*/
00052 void ser_OpenPort (char portNum) {
00053  
00054   if ( portNum == 0 )
00055   {    
00056     /* Port 0 */
00057     NVIC_DisableIRQ(UART0_IRQn);
00058     LPC_PINCON->PINSEL0 &= ~0x000000F0;
00059     LPC_PINCON->PINSEL0 |= 0x00000050;     /* RxD0 is P0.3 and TxD0 is P0.2 */
00060   }
00061   else
00062   {
00063     /* Port 1 */
00064     NVIC_DisableIRQ(UART1_IRQn);
00065     LPC_PINCON->PINSEL4 &= ~0x0000000F;
00066     LPC_PINCON->PINSEL4 |= 0x0000000A;    /* Enable RxD1 P2.1, TxD1 P2.0 */
00067   }
00068   return;
00069 }
00070 
00071 /*----------------------------------------------------------------------------
00072   close the serial port
00073  *---------------------------------------------------------------------------*/
00074 void ser_ClosePort (char portNum ) {
00075   if ( portNum == 0 )
00076   {
00077     /* POrt 0 */
00078     LPC_PINCON->PINSEL0 &= ~0x000000F0;
00079     /* Disable the interrupt in the VIC and UART controllers */
00080     LPC_UART0->IER = 0;
00081     NVIC_DisableIRQ(UART0_IRQn);
00082   }
00083   else
00084   {
00085     /* Port 1 */
00086     LPC_PINCON->PINSEL4 &= ~0x0000000F;
00087     /* Disable the interrupt in the VIC and UART controllers */
00088     LPC_UART1->IER = 0;
00089     NVIC_DisableIRQ(UART1_IRQn);
00090   }    
00091   return;
00092 }
00093 
00094 /*----------------------------------------------------------------------------
00095   initialize the serial port
00096  *---------------------------------------------------------------------------*/
00097 void ser_InitPort0 (unsigned long baudrate, unsigned int  databits,
00098                   unsigned int  parity,   unsigned int  stopbits) {
00099 
00100   unsigned char lcr_p, lcr_s, lcr_d;
00101   unsigned int dll;
00102   unsigned int pclkdiv, pclk;
00103   
00104   switch (databits) {
00105     case 5:                                            // 5 Data bits
00106       lcr_d = 0x00;
00107     break;
00108     case 6:                                            // 6 Data bits
00109       lcr_d = 0x01;
00110     break;
00111     case 7:                                            // 7 Data bits
00112       lcr_d = 0x02;
00113     break;
00114     case 8:                                            // 8 Data bits
00115     default:
00116       lcr_d = 0x03;
00117     break;
00118   }
00119 
00120   switch (stopbits) {
00121     case 1:                                            // 1,5 Stop bits
00122     case 2:                                            // 2   Stop bits
00123       lcr_s = 0x04;
00124     break;
00125     case 0:                                            // 1   Stop bit
00126     default:
00127       lcr_s = 0x00;
00128     break;
00129   }
00130 
00131   switch (parity) {
00132     case 1:                                            // Parity Odd
00133       lcr_p = 0x08;
00134     break;
00135     case 2:                                            // Parity Even
00136       lcr_p = 0x18;
00137     break;
00138     case 3:                                            // Parity Mark
00139       lcr_p = 0x28;
00140     break;
00141     case 4:                                            // Parity Space
00142       lcr_p = 0x38;
00143     break;
00144     case 0:                                            // Parity None
00145     default:
00146       lcr_p = 0x00;
00147     break;
00148   }
00149 
00150   SER_BUF_RESET(ser_out);                              // reset out buffer
00151   SER_BUF_RESET(ser_in);                               // reset in buffer
00152   
00153   /* Bit 6~7 is for UART0 */
00154   pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
00155 
00156   switch ( pclkdiv )
00157   {
00158     case 0x00:
00159     default:
00160       pclk = SystemFrequency/4;
00161       break;
00162     case 0x01:
00163       pclk = SystemFrequency;
00164       break; 
00165     case 0x02:
00166       pclk = SystemFrequency/2;
00167       break; 
00168     case 0x03:
00169       pclk = SystemFrequency/8;
00170       break;
00171   }
00172 
00173   dll = (pclk/16)/baudrate ;    /*baud rate */
00174   LPC_UART0->FDR = 0;                             // Fractional divider not used
00175   LPC_UART0->LCR = 0x80 | lcr_d | lcr_p | lcr_s;  // Data bits, Parity,   Stop bit
00176   LPC_UART0->DLL = dll;                           // Baud Rate depending on PCLK
00177   LPC_UART0->DLM = (dll >> 8);                    // High divisor latch
00178   LPC_UART0->LCR = 0x00 | lcr_d | lcr_p | lcr_s;  // DLAB = 0
00179   LPC_UART0->IER = 0x03;                          // Enable TX/RX interrupts
00180 
00181   LPC_UART0->FCR = 0x07;                /* Enable and reset TX and RX FIFO. */
00182   ser_txRestart = 1;                                   // TX fifo is empty
00183 
00184   /* Enable the UART Interrupt */
00185   NVIC_EnableIRQ(UART0_IRQn);
00186   return;
00187 }
00188 
00189 /*----------------------------------------------------------------------------
00190   initialize the serial port
00191  *---------------------------------------------------------------------------*/
00192 void ser_InitPort1 (unsigned long baudrate, unsigned int  databits,
00193                   unsigned int  parity,   unsigned int  stopbits) {
00194 
00195   unsigned char lcr_p, lcr_s, lcr_d;
00196   unsigned int dll;
00197   unsigned int pclkdiv, pclk;
00198   
00199   switch (databits) {
00200     case 5:                                            // 5 Data bits
00201       lcr_d = 0x00;
00202     break;
00203     case 6:                                            // 6 Data bits
00204       lcr_d = 0x01;
00205     break;
00206     case 7:                                            // 7 Data bits
00207       lcr_d = 0x02;
00208     break;
00209     case 8:                                            // 8 Data bits
00210     default:
00211       lcr_d = 0x03;
00212     break;
00213   }
00214 
00215   switch (stopbits) {
00216     case 1:                                            // 1,5 Stop bits
00217     case 2:                                            // 2   Stop bits
00218       lcr_s = 0x04;
00219     break;
00220     case 0:                                            // 1   Stop bit
00221     default:
00222       lcr_s = 0x00;
00223     break;
00224   }
00225 
00226   switch (parity) {
00227     case 1:                                            // Parity Odd
00228       lcr_p = 0x08;
00229     break;
00230     case 2:                                            // Parity Even
00231       lcr_p = 0x18;
00232     break;
00233     case 3:                                            // Parity Mark
00234       lcr_p = 0x28;
00235     break;
00236     case 4:                                            // Parity Space
00237       lcr_p = 0x38;
00238     break;
00239     case 0:                                            // Parity None
00240     default:
00241       lcr_p = 0x00;
00242     break;
00243   }
00244 
00245   SER_BUF_RESET(ser_out);                              // reset out buffer
00246   SER_BUF_RESET(ser_in);                               // reset in buffer
00247   
00248   /* Bit 8,9 are for UART1 */
00249   pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03;
00250 
00251   switch ( pclkdiv )
00252   {
00253     case 0x00:
00254     default:
00255       pclk = SystemFrequency/4;
00256       break;
00257     case 0x01:
00258       pclk = SystemFrequency;
00259       break; 
00260     case 0x02:
00261       pclk = SystemFrequency/2;
00262       break; 
00263     case 0x03:
00264       pclk = SystemFrequency/8;
00265       break;
00266   }
00267 
00268   dll = (pclk/16)/baudrate ;    /*baud rate */
00269   LPC_UART1->FDR = 0;                             // Fractional divider not used
00270   LPC_UART1->LCR = 0x80 | lcr_d | lcr_p | lcr_s;  // Data bits, Parity,   Stop bit
00271   LPC_UART1->DLL = dll;                           // Baud Rate depending on PCLK
00272   LPC_UART1->DLM = (dll >> 8);                    // High divisor latch
00273   LPC_UART1->LCR = 0x00 | lcr_d | lcr_p | lcr_s;  // DLAB = 0
00274   LPC_UART1->IER = 0x03;                          // Enable TX/RX interrupts
00275 
00276   LPC_UART1->FCR = 0x07;                /* Enable and reset TX and RX FIFO. */
00277   ser_txRestart = 1;                                   // TX fifo is empty
00278 
00279   /* Enable the UART Interrupt */
00280   NVIC_EnableIRQ(UART1_IRQn);
00281   return;
00282 }
00283 
00284 /*----------------------------------------------------------------------------
00285   read data from serial port
00286  *---------------------------------------------------------------------------*/
00287 int ser_Read (char *buffer, const int *length) {
00288   int bytesToRead, bytesRead;
00289   
00290   /* Read *length bytes, block if *bytes are not avaialable    */
00291   bytesToRead = *length;
00292   bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length);
00293   bytesRead = bytesToRead;
00294 
00295   while (bytesToRead--) {
00296     while (SER_BUF_EMPTY(ser_in));                     // Block until data is available if none
00297     *buffer++ = SER_BUF_RD(ser_in);
00298   }
00299   return (bytesRead);  
00300 }
00301 
00302 /*----------------------------------------------------------------------------
00303   write data to the serial port
00304  *---------------------------------------------------------------------------*/
00305 int ser_Write (char portNum, const char *buffer, int *length) {
00306   int  bytesToWrite, bytesWritten;
00307 
00308   // Write *length bytes
00309   bytesToWrite = *length;
00310   bytesWritten = bytesToWrite;
00311 
00312   while (!SER_BUF_EMPTY(ser_out));               // Block until space is available if none
00313   while (bytesToWrite) {
00314       SER_BUF_WR(ser_out, *buffer++);            // Read Rx FIFO to buffer  
00315       bytesToWrite--;
00316   }     
00317 
00318   if (ser_txRestart) {
00319     ser_txRestart = 0;
00320     if ( portNum == 0 )
00321     {
00322       LPC_UART0->THR = SER_BUF_RD(ser_out);             // Write to the Tx Register
00323     }
00324     else
00325     {
00326       LPC_UART1->THR = SER_BUF_RD(ser_out);             // Write to the Tx Register
00327     }
00328   }
00329 
00330   return (bytesWritten); 
00331 }
00332 
00333 /*----------------------------------------------------------------------------
00334   check if character(s) are available at the serial interface
00335  *---------------------------------------------------------------------------*/
00336 void ser_AvailChar (int *availChar) {
00337 
00338   *availChar = SER_BUF_COUNT(ser_in);
00339 
00340 }
00341 
00342 /*----------------------------------------------------------------------------
00343   read the line state of the serial port
00344  *---------------------------------------------------------------------------*/
00345 void ser_LineState (unsigned short *lineState) {
00346 
00347   *lineState = ser_lineState;
00348   ser_lineState = 0;
00349 
00350 }
00351 
00352 /*----------------------------------------------------------------------------
00353   serial port 0 interrupt
00354  *---------------------------------------------------------------------------*/
00355 void UART0_IRQHandler(void) 
00356 { 
00357   volatile unsigned long iir;
00358   
00359   iir = LPC_UART0->IIR;
00360    
00361   if ((iir & 0x4) || (iir & 0xC)) {            // RDA or CTI pending
00362     while (LPC_UART0->LSR & 0x01) {                 // Rx FIFO is not empty
00363       SER_BUF_WR(ser_in, LPC_UART0->RBR);           // Read Rx FIFO to buffer  
00364     }
00365   }
00366   if ((iir & 0x2)) {                           // TXMIS pending
00367     if (SER_BUF_COUNT(ser_out) != 0) {
00368       LPC_UART0->THR = SER_BUF_RD(ser_out);         // Write to the Tx FIFO
00369       ser_txRestart = 0;
00370     }
00371     else {
00372       ser_txRestart = 1;
00373     }
00374   }
00375   ser_lineState = LPC_UART0->LSR & 0x1E;            // update linestate
00376   return;
00377 }
00378 
00379 /*----------------------------------------------------------------------------
00380   serial port 1 interrupt
00381  *---------------------------------------------------------------------------*/
00382 void UART1_IRQHandler(void) 
00383 { 
00384   volatile unsigned long iir;
00385   
00386   iir = LPC_UART1->IIR;
00387    
00388   if ((iir & 0x4) || (iir & 0xC)) {            // RDA or CTI pending
00389     while (LPC_UART1->LSR & 0x01) {                 // Rx FIFO is not empty
00390       SER_BUF_WR(ser_in, LPC_UART1->RBR);           // Read Rx FIFO to buffer  
00391     }
00392   }
00393   if ((iir & 0x2)) {                           // TXMIS pending
00394     if (SER_BUF_COUNT(ser_out) != 0) {
00395       LPC_UART1->THR = SER_BUF_RD(ser_out);         // Write to the Tx FIFO
00396       ser_txRestart = 0;
00397     }
00398     else {
00399       ser_txRestart = 1;
00400     }
00401   }
00402   ser_lineState = ((LPC_UART1->MSR<<8)|LPC_UART1->LSR) & 0xE01E;    // update linestate
00403   return;
00404 }
00405 
00406