SimpleLib_03272011

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers serial.h Source File

serial.h

00001 /*
00002 * Copyright or � or Copr. 2010, Thomas SOETE
00003 * 
00004 * Author e-mail: thomas@soete.org
00005 * Library website : http://mbed.org/users/Alkorin/libraries/SimpleLib/
00006 * 
00007 * This software is governed by the CeCILL license under French law and
00008 * abiding by the rules of distribution of free software.  You can  use, 
00009 * modify and/ or redistribute the software under the terms of the CeCILL
00010 * license as circulated by CEA, CNRS and INRIA at the following URL
00011 * "http://www.cecill.info". 
00012 * 
00013 * As a counterpart to the access to the source code and  rights to copy,
00014 * modify and redistribute granted by the license, users are provided only
00015 * with a limited warranty  and the software's author,  the holder of the
00016 * economic rights,  and the successive licensors  have only  limited
00017 * liability. 
00018 * 
00019 * In this respect, the user's attention is drawn to the risks associated
00020 * with loading,  using,  modifying and/or developing or reproducing the
00021 * software by the user in light of its specific status of free software,
00022 * that may mean  that it is complicated to manipulate,  and  that  also
00023 * therefore means  that it is reserved for developers  and  experienced
00024 * professionals having in-depth computer knowledge. Users are therefore
00025 * encouraged to load and test the software's suitability as regards their
00026 * requirements in conditions enabling the security of their systems and/or 
00027 * data to be ensured and,  more generally, to use and operate it in the 
00028 * same conditions as regards security. 
00029 * 
00030 * The fact that you are presently reading this means that you have had
00031 * knowledge of the CeCILL license and that you accept its terms.
00032 */
00033 
00034 #ifndef __SIMPLELIB_SERIAL_H__
00035 #define __SIMPLELIB_SERIAL_H__
00036 
00037 #include "mbed_globals.h"
00038 #include "interrupts.h"
00039 
00040 /**********************************
00041  *    Simple Serial Managment     *
00042  **********************************
00043  * The interrupt handler is :     *
00044  * SERIAL_INTERRUPT_HANDLER(void) *
00045  * UART0 : Serial over USB        *
00046  * UART1 : TX p13, RX p14         *
00047  * UART2 : TX p28, RX p27         *
00048  * UART3 : TX p9,  RX p10         *
00049  **********************************/
00050  
00051 /** Registers **/
00052 // Serial port (Choose UARTn (0,1,2,3))
00053 #define UART_NUMBER UART0
00054 #define UART_BASE TOKENPASTE2(LPC_,UART_NUMBER)
00055 
00056 // Peripheral Clock Selection registers (See 4.7.3 p56)
00057 #define UART0_PCLK_REG (LPC_SC->PCLKSEL0)
00058 #define UART1_PCLK_REG (LPC_SC->PCLKSEL0)
00059 #define UART2_PCLK_REG (LPC_SC->PCLKSEL1)
00060 #define UART3_PCLK_REG (LPC_SC->PCLKSEL1)
00061 #define UART_PCLK_REG  TOKENPASTE2(UART_NUMBER,_PCLK_REG)
00062 
00063 #define UART0_PCLK_OFFSET   6
00064 #define UART1_PCLK_OFFSET   8
00065 #define UART2_PCLK_OFFSET  16
00066 #define UART3_PCLK_OFFSET  18
00067 #define UART_PCLK_OFFSET   TOKENPASTE2(UART_NUMBER,_PCLK_OFFSET)
00068 
00069 #define UART0_PCLK ((LPC_SC->PCLKSEL0 >>  6) & 0x03)
00070 #define UART1_PCLK ((LPC_SC->PCLKSEL0 >>  8) & 0x03)
00071 #define UART2_PCLK ((LPC_SC->PCLKSEL1 >> 16) & 0x03)
00072 #define UART3_PCLK ((LPC_SC->PCLKSEL1 >> 18) & 0x03)
00073 #define UART_PCLK TOKENPASTE2(UART_NUMBER,_PCLK)
00074 
00075 // Pin Function Select register (See 8.5.1-8 p108)
00076 #define UART0RX_PINSEL_REG (LPC_PINCON->PINSEL0)
00077 #define UART1RX_PINSEL_REG (LPC_PINCON->PINSEL1)
00078 #define UART2RX_PINSEL_REG (LPC_PINCON->PINSEL0)
00079 #define UART3RX_PINSEL_REG (LPC_PINCON->PINSEL0)
00080 #define UARTRX_PINSEL_REG  TOKENPASTE2(UART_NUMBER,RX_PINSEL_REG)
00081 
00082 #define UART0TX_PINSEL_REG (LPC_PINCON->PINSEL0)
00083 #define UART1TX_PINSEL_REG (LPC_PINCON->PINSEL0)
00084 #define UART2TX_PINSEL_REG (LPC_PINCON->PINSEL0)
00085 #define UART3TX_PINSEL_REG (LPC_PINCON->PINSEL0)
00086 #define UARTTX_PINSEL_REG  TOKENPASTE2(UART_NUMBER,TX_PINSEL_REG)
00087 
00088 #define UART0RX_PINSEL_OFFSET   6
00089 #define UART1RX_PINSEL_OFFSET   0
00090 #define UART2RX_PINSEL_OFFSET  22
00091 #define UART3RX_PINSEL_OFFSET   2
00092 #define UARTRX_PINSEL_OFFSET    TOKENPASTE2(UART_NUMBER,RX_PINSEL_OFFSET)
00093 
00094 #define UART0TX_PINSEL_OFFSET   4
00095 #define UART1TX_PINSEL_OFFSET  30
00096 #define UART2TX_PINSEL_OFFSET  20
00097 #define UART3TX_PINSEL_OFFSET   0
00098 #define UARTTX_PINSEL_OFFSET    TOKENPASTE2(UART_NUMBER,TX_PINSEL_OFFSET)
00099 
00100 #define UART0_PINSEL_VALUE    1U
00101 #define UART1_PINSEL_VALUE    1U
00102 #define UART2_PINSEL_VALUE    1U
00103 #define UART3_PINSEL_VALUE    2U
00104 #define UART_PINSEL_VALUE     TOKENPASTE2(UART_NUMBER,_PINSEL_VALUE)
00105 
00106 /** Interrupt handlers **/
00107 #define SERIAL_INTERRUPT_HANDLER EXTERN_C void __IRQ TOKENPASTE2(UART_NUMBER,_IRQHandler)
00108 
00109 /** Bits **/
00110 // RBR Interrupt Enable (UnIER, 14.4.4 p302)
00111 #define RBR_INT_BIT 0
00112 // Receiver Data Ready (UnLSR, 14.4.8 p306)
00113 #define RDR_BIT 0
00114 // Transmitter Holding Register Empty (UnLSR, 14.4.8 p306)
00115 #define THRE_BIT 5
00116 // RBR Interrupt Enable (UnIER, 14.4.4 p302)
00117 #define SERIAL_INT_RX 1
00118 // THRE Interrupt Enable (UnIER, 14.4.4 p302)
00119 #define SERIAL_INT_TX 2
00120 // Divisor Latch Access Bit (UnLCR, 14.4.7 p306)
00121 #define DLA_BIT 7
00122 // Power Control for Peripherals (PCONP, 4.8.7.1 p63)
00123 #define UART0_PCONP_BIT  3
00124 #define UART1_PCONP_BIT  4
00125 #define UART2_PCONP_BIT 24
00126 #define UART3_PCONP_BIT 25
00127 
00128 /** Macros **/
00129 #define SERIAL_PUTCHAR(c)               do {                                                        \
00130                                             while (GET_BIT_VALUE(UART_BASE->LSR, THRE_BIT) == 0);   \
00131                                             UART_BASE->THR = c;                                     \
00132                                         } while(0)
00133 
00134 #define SERIAL_DATA_TO_READ()           (GET_BIT_VALUE(UART_BASE->LSR, RDR_BIT) == 1)
00135 
00136 #define SERIAL_GETCHAR()                (UART_BASE->RBR)
00137 
00138 // Enable interrupt for RX or TX (SERIAL_INT_RX and SERIAL_INT_TX)
00139 #define SERIAL_ENABLE_INTERRUPT(value)  do {                                                    \
00140                                             UART_BASE->IER = value;                             \
00141                                             ENABLE_INTERRUPT(TOKENPASTE2(UART_NUMBER,_IRQn));   \
00142                                         } while(0)
00143 
00144 extern __INLINE void SERIAL_INIT()
00145 {
00146     // Enable UARTn
00147     SET_BIT_VALUE(LPC_SC->PCONP, TOKENPASTE2(UART_NUMBER,_PCONP_BIT) , 1);
00148     // Enable FIFO and reset RX/TX FIFO (See 14.4.6 p305)
00149     UART_BASE->FCR = 0x07;
00150     // 8-bits, No Parity, 1 stop bit (See 14.4.7 p306)
00151     UART_BASE->LCR = 0x03;
00152     // Set CCLK as Peripheral Clock for UART (96MHz with mbed library)
00153     UART_PCLK_REG = (UART_PCLK_REG & (~(3UL << UART_PCLK_OFFSET))) | (1U << UART_PCLK_OFFSET);
00154     // Define Pin's functions as UART
00155     UARTRX_PINSEL_REG = (UARTRX_PINSEL_REG & (~(3U << UARTRX_PINSEL_OFFSET))) | (UART_PINSEL_VALUE << UARTRX_PINSEL_OFFSET);
00156     UARTTX_PINSEL_REG = (UARTTX_PINSEL_REG & (~(3U << UARTTX_PINSEL_OFFSET))) | (UART_PINSEL_VALUE << UARTTX_PINSEL_OFFSET);
00157 }
00158 
00159 // See 14.4.5 p303
00160 extern __INLINE int SERIAL_CHECK_INTERRUPT(void) {
00161     uint32_t serialStatus = UART_BASE->IIR;
00162 
00163     if (serialStatus & 1) // IntStatus, 1 = No Interrupt is pending.
00164         return 0;
00165 
00166     serialStatus = (serialStatus >> 1) & 0x3; // IntId, 2 = More than threshold data to read, 6 = Some caracters to read
00167     if (serialStatus != 2 && serialStatus != 6)
00168         return 0;
00169 
00170     return 1;
00171 }
00172 
00173 extern __INLINE void SERIAL_SETBAUD(unsigned int baud) {
00174     // Peripheral Clock Selection register bit values (See Table 42, p57)
00175     uint16_t divisorValue = (SystemCoreClock / 16 / baud);
00176     #if 0
00177         // Peripheral Clock for UART is set to CCLK in SERIAL_INIT. Divisor is then 1.
00178         // Else, use code below
00179         static int divisors[4] = { 4, 1, 2, 8 };
00180         uint16_t divisorValue = ((SystemCoreClock / 16 / baud) / divisors[UART_PCLK]);
00181     #endif
00182     
00183     UART_BASE->LCR |= (1 << DLA_BIT);
00184     UART_BASE->DLM = (uint8_t) (divisorValue >> 8);
00185     UART_BASE->DLL = (uint8_t)  divisorValue;
00186     UART_BASE->LCR &= ~(1 << DLA_BIT);
00187 }
00188 
00189 #endif