Simple mbed library with macros
Dependents: SimpleTimer SimpleUART SimpleTimer Stoppuhr1
serial.h@8:f8b47457fdcf, 2010-11-13 (annotated)
- Committer:
- Alkorin
- Date:
- Sat Nov 13 22:15:12 2010 +0000
- Revision:
- 8:f8b47457fdcf
- Parent:
- 7:8443cecf62d1
- Child:
- 9:9cb955772c69
Added License
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Alkorin | 8:f8b47457fdcf | 1 | /* |
Alkorin | 8:f8b47457fdcf | 2 | * Copyright or © or Copr. 2010, Thomas SOETE |
Alkorin | 8:f8b47457fdcf | 3 | * |
Alkorin | 8:f8b47457fdcf | 4 | * Author e-mail: thomas@soete.org |
Alkorin | 8:f8b47457fdcf | 5 | * |
Alkorin | 8:f8b47457fdcf | 6 | * This software is governed by the CeCILL license under French law and |
Alkorin | 8:f8b47457fdcf | 7 | * abiding by the rules of distribution of free software. You can use, |
Alkorin | 8:f8b47457fdcf | 8 | * modify and/ or redistribute the software under the terms of the CeCILL |
Alkorin | 8:f8b47457fdcf | 9 | * license as circulated by CEA, CNRS and INRIA at the following URL |
Alkorin | 8:f8b47457fdcf | 10 | * "http://www.cecill.info". |
Alkorin | 8:f8b47457fdcf | 11 | * |
Alkorin | 8:f8b47457fdcf | 12 | * As a counterpart to the access to the source code and rights to copy, |
Alkorin | 8:f8b47457fdcf | 13 | * modify and redistribute granted by the license, users are provided only |
Alkorin | 8:f8b47457fdcf | 14 | * with a limited warranty and the software's author, the holder of the |
Alkorin | 8:f8b47457fdcf | 15 | * economic rights, and the successive licensors have only limited |
Alkorin | 8:f8b47457fdcf | 16 | * liability. |
Alkorin | 8:f8b47457fdcf | 17 | * |
Alkorin | 8:f8b47457fdcf | 18 | * In this respect, the user's attention is drawn to the risks associated |
Alkorin | 8:f8b47457fdcf | 19 | * with loading, using, modifying and/or developing or reproducing the |
Alkorin | 8:f8b47457fdcf | 20 | * software by the user in light of its specific status of free software, |
Alkorin | 8:f8b47457fdcf | 21 | * that may mean that it is complicated to manipulate, and that also |
Alkorin | 8:f8b47457fdcf | 22 | * therefore means that it is reserved for developers and experienced |
Alkorin | 8:f8b47457fdcf | 23 | * professionals having in-depth computer knowledge. Users are therefore |
Alkorin | 8:f8b47457fdcf | 24 | * encouraged to load and test the software's suitability as regards their |
Alkorin | 8:f8b47457fdcf | 25 | * requirements in conditions enabling the security of their systems and/or |
Alkorin | 8:f8b47457fdcf | 26 | * data to be ensured and, more generally, to use and operate it in the |
Alkorin | 8:f8b47457fdcf | 27 | * same conditions as regards security. |
Alkorin | 8:f8b47457fdcf | 28 | * |
Alkorin | 8:f8b47457fdcf | 29 | * The fact that you are presently reading this means that you have had |
Alkorin | 8:f8b47457fdcf | 30 | * knowledge of the CeCILL license and that you accept its terms. |
Alkorin | 8:f8b47457fdcf | 31 | */ |
Alkorin | 8:f8b47457fdcf | 32 | |
Alkorin | 4:afddc4848b6c | 33 | #ifndef __SERIAL_H__ |
Alkorin | 4:afddc4848b6c | 34 | #define __SERIAL_H__ |
Alkorin | 4:afddc4848b6c | 35 | |
Alkorin | 4:afddc4848b6c | 36 | #include "mbed_globals.h" |
Alkorin | 5:b3aa0a49e21f | 37 | #include "interrupts.h" |
Alkorin | 4:afddc4848b6c | 38 | |
Alkorin | 5:b3aa0a49e21f | 39 | /* Simple Serial Managment * |
Alkorin | 5:b3aa0a49e21f | 40 | * The interrupt handler is : * |
Alkorin | 7:8443cecf62d1 | 41 | * SERIAL_INTERRUPT_HANDLER(void) * |
Alkorin | 7:8443cecf62d1 | 42 | * UART0 : Serial over USB * |
Alkorin | 7:8443cecf62d1 | 43 | * UART1 : TX p13, RX p14 * |
Alkorin | 7:8443cecf62d1 | 44 | * UART2 : TX p28, RX p27 * |
Alkorin | 7:8443cecf62d1 | 45 | * UART3 : TX p9, RX p10 */ |
Alkorin | 5:b3aa0a49e21f | 46 | |
Alkorin | 7:8443cecf62d1 | 47 | // Serial port (Choose UARTn (0,1,2,3)) |
Alkorin | 5:b3aa0a49e21f | 48 | #define UART_NUMBER UART0 |
Alkorin | 5:b3aa0a49e21f | 49 | #define UART_BASE TOKENPASTE2(LPC_,UART_NUMBER) |
Alkorin | 5:b3aa0a49e21f | 50 | |
Alkorin | 5:b3aa0a49e21f | 51 | // Peripheral Clock Selection registers (See 4.7.3 p56) |
Alkorin | 7:8443cecf62d1 | 52 | #define UART0_PCLK_REG (LPC_SC->PCLKSEL0) |
Alkorin | 7:8443cecf62d1 | 53 | #define UART1_PCLK_REG (LPC_SC->PCLKSEL0) |
Alkorin | 7:8443cecf62d1 | 54 | #define UART2_PCLK_REG (LPC_SC->PCLKSEL1) |
Alkorin | 7:8443cecf62d1 | 55 | #define UART3_PCLK_REG (LPC_SC->PCLKSEL1) |
Alkorin | 7:8443cecf62d1 | 56 | #define UART_PCLK_REG TOKENPASTE2(UART_NUMBER,_PCLK_REG) |
Alkorin | 7:8443cecf62d1 | 57 | |
Alkorin | 7:8443cecf62d1 | 58 | #define UART0_PCLK_OFFSET 6 |
Alkorin | 7:8443cecf62d1 | 59 | #define UART1_PCLK_OFFSET 8 |
Alkorin | 7:8443cecf62d1 | 60 | #define UART2_PCLK_OFFSET 16 |
Alkorin | 7:8443cecf62d1 | 61 | #define UART3_PCLK_OFFSET 18 |
Alkorin | 7:8443cecf62d1 | 62 | #define UART_PCLK_OFFSET TOKENPASTE2(UART_NUMBER,_PCLK_OFFSET) |
Alkorin | 7:8443cecf62d1 | 63 | |
Alkorin | 5:b3aa0a49e21f | 64 | #define UART0_PCLK ((LPC_SC->PCLKSEL0 >> 6) & 0x03) |
Alkorin | 7:8443cecf62d1 | 65 | #define UART1_PCLK ((LPC_SC->PCLKSEL0 >> 8) & 0x03) |
Alkorin | 5:b3aa0a49e21f | 66 | #define UART2_PCLK ((LPC_SC->PCLKSEL1 >> 16) & 0x03) |
Alkorin | 5:b3aa0a49e21f | 67 | #define UART3_PCLK ((LPC_SC->PCLKSEL1 >> 18) & 0x03) |
Alkorin | 5:b3aa0a49e21f | 68 | #define UART_PCLK TOKENPASTE2(UART_NUMBER,_PCLK) |
Alkorin | 5:b3aa0a49e21f | 69 | |
Alkorin | 7:8443cecf62d1 | 70 | // Pin Function Select register (See 8.5.1-8 p108) |
Alkorin | 7:8443cecf62d1 | 71 | #define UART0RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 72 | #define UART1RX_PINSEL_REG (LPC_PINCON->PINSEL1) |
Alkorin | 7:8443cecf62d1 | 73 | #define UART2RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 74 | #define UART3RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 75 | #define UARTRX_PINSEL_REG TOKENPASTE2(UART_NUMBER,RX_PINSEL_REG) |
Alkorin | 7:8443cecf62d1 | 76 | |
Alkorin | 7:8443cecf62d1 | 77 | #define UART0TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 78 | #define UART1TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 79 | #define UART2TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 80 | #define UART3TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 81 | #define UARTTX_PINSEL_REG TOKENPASTE2(UART_NUMBER,TX_PINSEL_REG) |
Alkorin | 7:8443cecf62d1 | 82 | |
Alkorin | 7:8443cecf62d1 | 83 | #define UART0RX_PINSEL_OFFSET 6 |
Alkorin | 7:8443cecf62d1 | 84 | #define UART1RX_PINSEL_OFFSET 0 |
Alkorin | 7:8443cecf62d1 | 85 | #define UART2RX_PINSEL_OFFSET 22 |
Alkorin | 7:8443cecf62d1 | 86 | #define UART3RX_PINSEL_OFFSET 2 |
Alkorin | 7:8443cecf62d1 | 87 | #define UARTRX_PINSEL_OFFSET TOKENPASTE2(UART_NUMBER,RX_PINSEL_OFFSET) |
Alkorin | 7:8443cecf62d1 | 88 | |
Alkorin | 7:8443cecf62d1 | 89 | #define UART0TX_PINSEL_OFFSET 4 |
Alkorin | 7:8443cecf62d1 | 90 | #define UART1TX_PINSEL_OFFSET 30 |
Alkorin | 7:8443cecf62d1 | 91 | #define UART2TX_PINSEL_OFFSET 20 |
Alkorin | 7:8443cecf62d1 | 92 | #define UART3TX_PINSEL_OFFSET 0 |
Alkorin | 7:8443cecf62d1 | 93 | #define UARTTX_PINSEL_OFFSET TOKENPASTE2(UART_NUMBER,TX_PINSEL_OFFSET) |
Alkorin | 7:8443cecf62d1 | 94 | |
Alkorin | 7:8443cecf62d1 | 95 | #define UART0_PINSEL_VALUE 1UL |
Alkorin | 7:8443cecf62d1 | 96 | #define UART1_PINSEL_VALUE 1UL |
Alkorin | 7:8443cecf62d1 | 97 | #define UART2_PINSEL_VALUE 1UL |
Alkorin | 7:8443cecf62d1 | 98 | #define UART3_PINSEL_VALUE 2UL |
Alkorin | 7:8443cecf62d1 | 99 | #define UART_PINSEL_VALUE TOKENPASTE2(UART_NUMBER,_PINSEL_VALUE) |
Alkorin | 7:8443cecf62d1 | 100 | |
Alkorin | 5:b3aa0a49e21f | 101 | // Interrupt handlers |
Alkorin | 5:b3aa0a49e21f | 102 | #define SERIAL_INTERRUPT_HANDLER extern "C" void __irq TOKENPASTE2(UART_NUMBER,_IRQHandler) |
Alkorin | 4:afddc4848b6c | 103 | |
Alkorin | 4:afddc4848b6c | 104 | /** Bits **/ |
Alkorin | 4:afddc4848b6c | 105 | // RBR Interrupt Enable (UnIER, 14.4.4 p302) |
Alkorin | 4:afddc4848b6c | 106 | #define RBR_INT_BIT 0 |
Alkorin | 4:afddc4848b6c | 107 | // Receiver Data Ready (UnLSR, 14.4.8 p306) |
Alkorin | 4:afddc4848b6c | 108 | #define RDR_BIT 0 |
Alkorin | 4:afddc4848b6c | 109 | // Transmitter Holding Register Empty (UnLSR, 14.4.8 p306) |
Alkorin | 4:afddc4848b6c | 110 | #define THRE_BIT 5 |
Alkorin | 5:b3aa0a49e21f | 111 | // RBR Interrupt Enable (UnIER, 14.4.4 p302) |
Alkorin | 5:b3aa0a49e21f | 112 | #define SERIAL_INT_RX 1 |
Alkorin | 5:b3aa0a49e21f | 113 | // THRE Interrupt Enable (UnIER, 14.4.4 p302) |
Alkorin | 5:b3aa0a49e21f | 114 | #define SERIAL_INT_TX 2 |
Alkorin | 5:b3aa0a49e21f | 115 | // Divisor Latch Access Bit (UnLCR, 14.4.7 p306) |
Alkorin | 5:b3aa0a49e21f | 116 | #define DLA_BIT 7 |
Alkorin | 7:8443cecf62d1 | 117 | // Power Control for Peripherals (PCONP, 4.8.7.1 p63) |
Alkorin | 7:8443cecf62d1 | 118 | #define UART0_PCONP_BIT 3 |
Alkorin | 7:8443cecf62d1 | 119 | #define UART1_PCONP_BIT 4 |
Alkorin | 7:8443cecf62d1 | 120 | #define UART2_PCONP_BIT 24 |
Alkorin | 7:8443cecf62d1 | 121 | #define UART3_PCONP_BIT 25 |
Alkorin | 4:afddc4848b6c | 122 | |
Alkorin | 4:afddc4848b6c | 123 | /** Macros **/ |
Alkorin | 5:b3aa0a49e21f | 124 | #define SERIAL_PUTCHAR(c) while (GET_BIT_VALUE(UART_BASE->LSR, THRE_BIT) == 0); \ |
Alkorin | 5:b3aa0a49e21f | 125 | UART_BASE->THR = c; |
Alkorin | 5:b3aa0a49e21f | 126 | |
Alkorin | 5:b3aa0a49e21f | 127 | #define SERIAL_DATA_TO_READ() (GET_BIT_VALUE(UART_BASE->LSR, RDR_BIT) == 1) |
Alkorin | 5:b3aa0a49e21f | 128 | |
Alkorin | 5:b3aa0a49e21f | 129 | #define SERIAL_GETCHAR() (UART_BASE->RBR) |
Alkorin | 4:afddc4848b6c | 130 | |
Alkorin | 5:b3aa0a49e21f | 131 | // Enable interrupt for RX or TX (SERIAL_INT_RX and SERIAL_INT_TX) |
Alkorin | 5:b3aa0a49e21f | 132 | #define SERIAL_ENABLE_INTERRUPT(value) UART_BASE->IER = value; \ |
Alkorin | 5:b3aa0a49e21f | 133 | ENABLE_INTERRUPT(TOKENPASTE2(UART_NUMBER,_IRQn)); |
Alkorin | 6:9e1310782abf | 134 | |
Alkorin | 7:8443cecf62d1 | 135 | inline void SERIAL_INIT() |
Alkorin | 7:8443cecf62d1 | 136 | { |
Alkorin | 7:8443cecf62d1 | 137 | // Enable UARTn |
Alkorin | 7:8443cecf62d1 | 138 | SET_BIT_VALUE(LPC_SC->PCONP, TOKENPASTE2(UART_NUMBER,_PCONP_BIT) , 1); |
Alkorin | 7:8443cecf62d1 | 139 | // Enable FIFO and reset RX/TX FIFO (See 14.4.6 p305) |
Alkorin | 7:8443cecf62d1 | 140 | UART_BASE->FCR = 0x07; |
Alkorin | 7:8443cecf62d1 | 141 | // 8-bits, No Parity, 1 stop bit (See 14.4.7 p306) |
Alkorin | 7:8443cecf62d1 | 142 | UART_BASE->LCR = 0x03; |
Alkorin | 7:8443cecf62d1 | 143 | // Set CCLK as Peripheral Clock for UART (96MHz with mbed library) |
Alkorin | 7:8443cecf62d1 | 144 | UART_PCLK_REG = UART_PCLK_REG & ~(3UL << UART_PCLK_OFFSET) | (1UL << UART_PCLK_OFFSET); |
Alkorin | 7:8443cecf62d1 | 145 | // Define Pin's functions as UART |
Alkorin | 7:8443cecf62d1 | 146 | UARTRX_PINSEL_REG = UARTRX_PINSEL_REG & ~(3UL << UARTRX_PINSEL_OFFSET) | (UART_PINSEL_VALUE << UARTRX_PINSEL_OFFSET); |
Alkorin | 7:8443cecf62d1 | 147 | UARTTX_PINSEL_REG = UARTTX_PINSEL_REG & ~(3UL << UARTTX_PINSEL_OFFSET) | (UART_PINSEL_VALUE << UARTTX_PINSEL_OFFSET); |
Alkorin | 7:8443cecf62d1 | 148 | } |
Alkorin | 4:afddc4848b6c | 149 | |
Alkorin | 4:afddc4848b6c | 150 | // See 14.4.5 p303 |
Alkorin | 4:afddc4848b6c | 151 | inline int SERIAL_CHECK_INTERRUPT(void) { |
Alkorin | 4:afddc4848b6c | 152 | uint32_t serialStatus = UART_BASE->IIR; |
Alkorin | 4:afddc4848b6c | 153 | |
Alkorin | 4:afddc4848b6c | 154 | if (serialStatus & 1) // IntStatus, 1 = No Interrupt is pending. |
Alkorin | 4:afddc4848b6c | 155 | return 0; |
Alkorin | 4:afddc4848b6c | 156 | |
Alkorin | 4:afddc4848b6c | 157 | serialStatus = (serialStatus >> 1) & 0x3; // IntId, 2 = More than threshold data to read, 6 = Some caracters to read |
Alkorin | 4:afddc4848b6c | 158 | if (serialStatus != 2 && serialStatus != 6) |
Alkorin | 4:afddc4848b6c | 159 | return 0; |
Alkorin | 4:afddc4848b6c | 160 | |
Alkorin | 4:afddc4848b6c | 161 | return 1; |
Alkorin | 4:afddc4848b6c | 162 | } |
Alkorin | 4:afddc4848b6c | 163 | |
Alkorin | 5:b3aa0a49e21f | 164 | inline void SERIAL_SETBAUD(unsigned int baud) { |
Alkorin | 5:b3aa0a49e21f | 165 | // Peripheral Clock Selection register bit values (See Table 42, p57) |
Alkorin | 8:f8b47457fdcf | 166 | uint16_t divisorValue = (SystemCoreClock / 16 / baud); |
Alkorin | 8:f8b47457fdcf | 167 | #if 0 |
Alkorin | 8:f8b47457fdcf | 168 | // Peripheral Clock for UART is set to CCLK in SERIAL_INIT. Divisor is then 1. |
Alkorin | 8:f8b47457fdcf | 169 | // Else, use code below |
Alkorin | 8:f8b47457fdcf | 170 | static int divisors[4] = { 4, 1, 2, 8 }; |
Alkorin | 8:f8b47457fdcf | 171 | uint16_t divisorValue = ((SystemCoreClock / 16 / baud) / divisors[UART_PCLK]); |
Alkorin | 8:f8b47457fdcf | 172 | #endif |
Alkorin | 5:b3aa0a49e21f | 173 | |
Alkorin | 6:9e1310782abf | 174 | UART_BASE->LCR |= (1 << DLA_BIT); |
Alkorin | 5:b3aa0a49e21f | 175 | UART_BASE->DLM = (uint8_t) (divisorValue >> 8); |
Alkorin | 5:b3aa0a49e21f | 176 | UART_BASE->DLL = (uint8_t) divisorValue; |
Alkorin | 6:9e1310782abf | 177 | UART_BASE->LCR &= ~(1 << DLA_BIT); |
Alkorin | 5:b3aa0a49e21f | 178 | } |
Alkorin | 4:afddc4848b6c | 179 | |
Alkorin | 0:aa3c3d1a5918 | 180 | #endif |