mbed SDK library sources

Fork of mbed-src by mbed official

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Wed Sep 25 10:30:04 2013 +0100
Revision:
30:91c1d09ada54
Child:
51:7838415c99e7
Synchronized with git revision 8f57c1e84759991fa81ede0da2b4aabe8530fa09

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 30:91c1d09ada54 1 /* mbed Microcontroller Library
mbed_official 30:91c1d09ada54 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 30:91c1d09ada54 3 *
mbed_official 30:91c1d09ada54 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 30:91c1d09ada54 5 * you may not use this file except in compliance with the License.
mbed_official 30:91c1d09ada54 6 * You may obtain a copy of the License at
mbed_official 30:91c1d09ada54 7 *
mbed_official 30:91c1d09ada54 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 30:91c1d09ada54 9 *
mbed_official 30:91c1d09ada54 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 30:91c1d09ada54 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 30:91c1d09ada54 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 30:91c1d09ada54 13 * See the License for the specific language governing permissions and
mbed_official 30:91c1d09ada54 14 * limitations under the License.
mbed_official 30:91c1d09ada54 15 */
mbed_official 30:91c1d09ada54 16 // math.h required for floating point operations for baud rate calculation
mbed_official 30:91c1d09ada54 17 #include <math.h>
mbed_official 30:91c1d09ada54 18 #include <string.h>
mbed_official 30:91c1d09ada54 19
mbed_official 30:91c1d09ada54 20 #include "serial_api.h"
mbed_official 30:91c1d09ada54 21 #include "cmsis.h"
mbed_official 30:91c1d09ada54 22 #include "pinmap.h"
mbed_official 30:91c1d09ada54 23 #include "error.h"
mbed_official 30:91c1d09ada54 24
mbed_official 30:91c1d09ada54 25 /******************************************************************************
mbed_official 30:91c1d09ada54 26 * INITIALIZATION
mbed_official 30:91c1d09ada54 27 ******************************************************************************/
mbed_official 30:91c1d09ada54 28 #define UART_NUM 1
mbed_official 30:91c1d09ada54 29
mbed_official 30:91c1d09ada54 30 static const PinMap PinMap_UART_TX[] = {
mbed_official 30:91c1d09ada54 31 {P2_8 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 32 {P3_5 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 33 {P3_0 , UART_0, 0x03},
mbed_official 30:91c1d09ada54 34 {P1_7 , UART_0, 0x01},
mbed_official 30:91c1d09ada54 35 {NC , NC , 0x00}
mbed_official 30:91c1d09ada54 36 };
mbed_official 30:91c1d09ada54 37
mbed_official 30:91c1d09ada54 38 static const PinMap PinMap_UART_RX[] = {
mbed_official 30:91c1d09ada54 39 {P2_7 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 40 {P3_4 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 41 {P3_1 , UART_0, 0x03},
mbed_official 30:91c1d09ada54 42 {P1_6 , UART_0, 0x01},
mbed_official 30:91c1d09ada54 43 {NC , NC , 0x00}
mbed_official 30:91c1d09ada54 44 };
mbed_official 30:91c1d09ada54 45
mbed_official 30:91c1d09ada54 46 static uint32_t serial_irq_ids[UART_NUM] = {0};
mbed_official 30:91c1d09ada54 47 static uart_irq_handler irq_handler;
mbed_official 30:91c1d09ada54 48
mbed_official 30:91c1d09ada54 49 int stdio_uart_inited = 0;
mbed_official 30:91c1d09ada54 50 serial_t stdio_uart;
mbed_official 30:91c1d09ada54 51
mbed_official 30:91c1d09ada54 52 void serial_init(serial_t *obj, PinName tx, PinName rx) {
mbed_official 30:91c1d09ada54 53 int is_stdio_uart = 0;
mbed_official 30:91c1d09ada54 54
mbed_official 30:91c1d09ada54 55 // determine the UART to use
mbed_official 30:91c1d09ada54 56 UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
mbed_official 30:91c1d09ada54 57 UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
mbed_official 30:91c1d09ada54 58 UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
mbed_official 30:91c1d09ada54 59 if ((int)uart == NC) {
mbed_official 30:91c1d09ada54 60 error("Serial pinout mapping failed");
mbed_official 30:91c1d09ada54 61 }
mbed_official 30:91c1d09ada54 62
mbed_official 30:91c1d09ada54 63 obj->uart = (LPC_UART_TypeDef *)uart;
mbed_official 30:91c1d09ada54 64 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
mbed_official 30:91c1d09ada54 65
mbed_official 30:91c1d09ada54 66 // enable fifos and default rx trigger level
mbed_official 30:91c1d09ada54 67 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
mbed_official 30:91c1d09ada54 68 | 0 << 1 // Rx Fifo Reset
mbed_official 30:91c1d09ada54 69 | 0 << 2 // Tx Fifo Reset
mbed_official 30:91c1d09ada54 70 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
mbed_official 30:91c1d09ada54 71
mbed_official 30:91c1d09ada54 72 // disable irqs
mbed_official 30:91c1d09ada54 73 obj->uart->IER = 0 << 0 // Rx Data available irq enable
mbed_official 30:91c1d09ada54 74 | 0 << 1 // Tx Fifo empty irq enable
mbed_official 30:91c1d09ada54 75 | 0 << 2; // Rx Line Status irq enable
mbed_official 30:91c1d09ada54 76
mbed_official 30:91c1d09ada54 77 // set default baud rate and format
mbed_official 30:91c1d09ada54 78 serial_baud (obj, 9600);
mbed_official 30:91c1d09ada54 79 serial_format(obj, 8, ParityNone, 1);
mbed_official 30:91c1d09ada54 80
mbed_official 30:91c1d09ada54 81 // pinout the chosen uart
mbed_official 30:91c1d09ada54 82 pinmap_pinout(tx, PinMap_UART_TX);
mbed_official 30:91c1d09ada54 83 pinmap_pinout(rx, PinMap_UART_RX);
mbed_official 30:91c1d09ada54 84
mbed_official 30:91c1d09ada54 85 // set rx/tx pins in PullUp mode
mbed_official 30:91c1d09ada54 86 pin_mode(tx, PullUp);
mbed_official 30:91c1d09ada54 87 pin_mode(rx, PullUp);
mbed_official 30:91c1d09ada54 88
mbed_official 30:91c1d09ada54 89 switch (uart) {
mbed_official 30:91c1d09ada54 90 case UART_0: obj->index = 0; break;
mbed_official 30:91c1d09ada54 91 }
mbed_official 30:91c1d09ada54 92
mbed_official 30:91c1d09ada54 93 is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
mbed_official 30:91c1d09ada54 94
mbed_official 30:91c1d09ada54 95 if (is_stdio_uart) {
mbed_official 30:91c1d09ada54 96 stdio_uart_inited = 1;
mbed_official 30:91c1d09ada54 97 memcpy(&stdio_uart, obj, sizeof(serial_t));
mbed_official 30:91c1d09ada54 98 }
mbed_official 30:91c1d09ada54 99 }
mbed_official 30:91c1d09ada54 100
mbed_official 30:91c1d09ada54 101 void serial_free(serial_t *obj) {
mbed_official 30:91c1d09ada54 102 serial_irq_ids[obj->index] = 0;
mbed_official 30:91c1d09ada54 103 }
mbed_official 30:91c1d09ada54 104
mbed_official 30:91c1d09ada54 105 // serial_baud
mbed_official 30:91c1d09ada54 106 // set the baud rate, taking in to account the current SystemFrequency
mbed_official 30:91c1d09ada54 107 void serial_baud(serial_t *obj, int baudrate) {
mbed_official 30:91c1d09ada54 108 LPC_SYSCON->UARTCLKDIV = 0x1;
mbed_official 30:91c1d09ada54 109 uint32_t PCLK = SystemCoreClock;
mbed_official 30:91c1d09ada54 110 // First we check to see if the basic divide with no DivAddVal/MulVal
mbed_official 30:91c1d09ada54 111 // ratio gives us an integer result. If it does, we set DivAddVal = 0,
mbed_official 30:91c1d09ada54 112 // MulVal = 1. Otherwise, we search the valid ratio value range to find
mbed_official 30:91c1d09ada54 113 // the closest match. This could be more elegant, using search methods
mbed_official 30:91c1d09ada54 114 // and/or lookup tables, but the brute force method is not that much
mbed_official 30:91c1d09ada54 115 // slower, and is more maintainable.
mbed_official 30:91c1d09ada54 116 uint16_t DL = PCLK / (16 * baudrate);
mbed_official 30:91c1d09ada54 117
mbed_official 30:91c1d09ada54 118 uint8_t DivAddVal = 0;
mbed_official 30:91c1d09ada54 119 uint8_t MulVal = 1;
mbed_official 30:91c1d09ada54 120 int hit = 0;
mbed_official 30:91c1d09ada54 121 uint16_t dlv;
mbed_official 30:91c1d09ada54 122 uint8_t mv, dav;
mbed_official 30:91c1d09ada54 123 if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder
mbed_official 30:91c1d09ada54 124 float err_best = (float) baudrate;
mbed_official 30:91c1d09ada54 125 uint16_t dlmax = DL;
mbed_official 30:91c1d09ada54 126 for ( dlv = (dlmax/2); (dlv <= dlmax) && !hit; dlv++) {
mbed_official 30:91c1d09ada54 127 for ( mv = 1; mv <= 15; mv++) {
mbed_official 30:91c1d09ada54 128 for ( dav = 1; dav < mv; dav++) {
mbed_official 30:91c1d09ada54 129 float ratio = 1.0f + ((float) dav / (float) mv);
mbed_official 30:91c1d09ada54 130 float calcbaud = (float)PCLK / (16.0f * (float) dlv * ratio);
mbed_official 30:91c1d09ada54 131 float err = fabs(((float) baudrate - calcbaud) / (float) baudrate);
mbed_official 30:91c1d09ada54 132 if (err < err_best) {
mbed_official 30:91c1d09ada54 133 DL = dlv;
mbed_official 30:91c1d09ada54 134 DivAddVal = dav;
mbed_official 30:91c1d09ada54 135 MulVal = mv;
mbed_official 30:91c1d09ada54 136 err_best = err;
mbed_official 30:91c1d09ada54 137 if (err < 0.001f) {
mbed_official 30:91c1d09ada54 138 hit = 1;
mbed_official 30:91c1d09ada54 139 }
mbed_official 30:91c1d09ada54 140 }
mbed_official 30:91c1d09ada54 141 }
mbed_official 30:91c1d09ada54 142 }
mbed_official 30:91c1d09ada54 143 }
mbed_official 30:91c1d09ada54 144 }
mbed_official 30:91c1d09ada54 145
mbed_official 30:91c1d09ada54 146 // set LCR[DLAB] to enable writing to divider registers
mbed_official 30:91c1d09ada54 147 obj->uart->LCR |= (1 << 7);
mbed_official 30:91c1d09ada54 148
mbed_official 30:91c1d09ada54 149 // set divider values
mbed_official 30:91c1d09ada54 150 obj->uart->DLM = (DL >> 8) & 0xFF;
mbed_official 30:91c1d09ada54 151 obj->uart->DLL = (DL >> 0) & 0xFF;
mbed_official 30:91c1d09ada54 152 obj->uart->FDR = (uint32_t) DivAddVal << 0
mbed_official 30:91c1d09ada54 153 | (uint32_t) MulVal << 4;
mbed_official 30:91c1d09ada54 154
mbed_official 30:91c1d09ada54 155 // clear LCR[DLAB]
mbed_official 30:91c1d09ada54 156 obj->uart->LCR &= ~(1 << 7);
mbed_official 30:91c1d09ada54 157 }
mbed_official 30:91c1d09ada54 158
mbed_official 30:91c1d09ada54 159 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
mbed_official 30:91c1d09ada54 160 // 0: 1 stop bits, 1: 2 stop bits
mbed_official 30:91c1d09ada54 161 if (stop_bits != 1 && stop_bits != 2) {
mbed_official 30:91c1d09ada54 162 error("Invalid stop bits specified");
mbed_official 30:91c1d09ada54 163 }
mbed_official 30:91c1d09ada54 164 stop_bits -= 1;
mbed_official 30:91c1d09ada54 165
mbed_official 30:91c1d09ada54 166 // 0: 5 data bits ... 3: 8 data bits
mbed_official 30:91c1d09ada54 167 if (data_bits < 5 || data_bits > 8) {
mbed_official 30:91c1d09ada54 168 error("Invalid number of bits (%d) in serial format, should be 5..8", data_bits);
mbed_official 30:91c1d09ada54 169 }
mbed_official 30:91c1d09ada54 170 data_bits -= 5;
mbed_official 30:91c1d09ada54 171
mbed_official 30:91c1d09ada54 172 int parity_enable, parity_select;
mbed_official 30:91c1d09ada54 173 switch (parity) {
mbed_official 30:91c1d09ada54 174 case ParityNone: parity_enable = 0; parity_select = 0; break;
mbed_official 30:91c1d09ada54 175 case ParityOdd : parity_enable = 1; parity_select = 0; break;
mbed_official 30:91c1d09ada54 176 case ParityEven: parity_enable = 1; parity_select = 1; break;
mbed_official 30:91c1d09ada54 177 case ParityForced1: parity_enable = 1; parity_select = 2; break;
mbed_official 30:91c1d09ada54 178 case ParityForced0: parity_enable = 1; parity_select = 3; break;
mbed_official 30:91c1d09ada54 179 default:
mbed_official 30:91c1d09ada54 180 error("Invalid serial parity setting");
mbed_official 30:91c1d09ada54 181 return;
mbed_official 30:91c1d09ada54 182 }
mbed_official 30:91c1d09ada54 183
mbed_official 30:91c1d09ada54 184 obj->uart->LCR = data_bits << 0
mbed_official 30:91c1d09ada54 185 | stop_bits << 2
mbed_official 30:91c1d09ada54 186 | parity_enable << 3
mbed_official 30:91c1d09ada54 187 | parity_select << 4;
mbed_official 30:91c1d09ada54 188 }
mbed_official 30:91c1d09ada54 189
mbed_official 30:91c1d09ada54 190 /******************************************************************************
mbed_official 30:91c1d09ada54 191 * INTERRUPTS HANDLING
mbed_official 30:91c1d09ada54 192 ******************************************************************************/
mbed_official 30:91c1d09ada54 193 static inline void uart_irq(uint32_t iir, uint32_t index) {
mbed_official 30:91c1d09ada54 194 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
mbed_official 30:91c1d09ada54 195 SerialIrq irq_type;
mbed_official 30:91c1d09ada54 196 switch (iir) {
mbed_official 30:91c1d09ada54 197 case 1: irq_type = TxIrq; break;
mbed_official 30:91c1d09ada54 198 case 2: irq_type = RxIrq; break;
mbed_official 30:91c1d09ada54 199 default: return;
mbed_official 30:91c1d09ada54 200 }
mbed_official 30:91c1d09ada54 201
mbed_official 30:91c1d09ada54 202 if (serial_irq_ids[index] != 0)
mbed_official 30:91c1d09ada54 203 irq_handler(serial_irq_ids[index], irq_type);
mbed_official 30:91c1d09ada54 204 }
mbed_official 30:91c1d09ada54 205
mbed_official 30:91c1d09ada54 206 void uart0_irq() {uart_irq((LPC_UART->IIR >> 1) & 0x7, 0);}
mbed_official 30:91c1d09ada54 207
mbed_official 30:91c1d09ada54 208 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
mbed_official 30:91c1d09ada54 209 irq_handler = handler;
mbed_official 30:91c1d09ada54 210 serial_irq_ids[obj->index] = id;
mbed_official 30:91c1d09ada54 211 }
mbed_official 30:91c1d09ada54 212
mbed_official 30:91c1d09ada54 213 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 30:91c1d09ada54 214 IRQn_Type irq_n = (IRQn_Type)0;
mbed_official 30:91c1d09ada54 215 uint32_t vector = 0;
mbed_official 30:91c1d09ada54 216 switch ((int)obj->uart) {
mbed_official 30:91c1d09ada54 217 case UART_0:
mbed_official 30:91c1d09ada54 218 irq_n=UART_IRQn;
mbed_official 30:91c1d09ada54 219 vector = (uint32_t)&uart0_irq;
mbed_official 30:91c1d09ada54 220 break;
mbed_official 30:91c1d09ada54 221 default:
mbed_official 30:91c1d09ada54 222 return;
mbed_official 30:91c1d09ada54 223 }
mbed_official 30:91c1d09ada54 224
mbed_official 30:91c1d09ada54 225 if (enable) {
mbed_official 30:91c1d09ada54 226 obj->uart->IER |= 1 << irq;
mbed_official 30:91c1d09ada54 227 NVIC_SetVector(irq_n, vector);
mbed_official 30:91c1d09ada54 228 NVIC_EnableIRQ(irq_n);
mbed_official 30:91c1d09ada54 229 } else { // disable
mbed_official 30:91c1d09ada54 230 int all_disabled = 0;
mbed_official 30:91c1d09ada54 231 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
mbed_official 30:91c1d09ada54 232
mbed_official 30:91c1d09ada54 233 obj->uart->IER &= ~(1 << irq);
mbed_official 30:91c1d09ada54 234 all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
mbed_official 30:91c1d09ada54 235
mbed_official 30:91c1d09ada54 236 if (all_disabled)
mbed_official 30:91c1d09ada54 237 NVIC_DisableIRQ(irq_n);
mbed_official 30:91c1d09ada54 238 }
mbed_official 30:91c1d09ada54 239 }
mbed_official 30:91c1d09ada54 240
mbed_official 30:91c1d09ada54 241 /******************************************************************************
mbed_official 30:91c1d09ada54 242 * READ/WRITE
mbed_official 30:91c1d09ada54 243 ******************************************************************************/
mbed_official 30:91c1d09ada54 244 int serial_getc(serial_t *obj) {
mbed_official 30:91c1d09ada54 245 while (!serial_readable(obj));
mbed_official 30:91c1d09ada54 246 return obj->uart->RBR;
mbed_official 30:91c1d09ada54 247 }
mbed_official 30:91c1d09ada54 248
mbed_official 30:91c1d09ada54 249 void serial_putc(serial_t *obj, int c) {
mbed_official 30:91c1d09ada54 250 while (!serial_writable(obj));
mbed_official 30:91c1d09ada54 251 obj->uart->THR = c;
mbed_official 30:91c1d09ada54 252 }
mbed_official 30:91c1d09ada54 253
mbed_official 30:91c1d09ada54 254 int serial_readable(serial_t *obj) {
mbed_official 30:91c1d09ada54 255 return obj->uart->LSR & 0x01;
mbed_official 30:91c1d09ada54 256 }
mbed_official 30:91c1d09ada54 257
mbed_official 30:91c1d09ada54 258 int serial_writable(serial_t *obj) {
mbed_official 30:91c1d09ada54 259 return obj->uart->LSR & 0x20;
mbed_official 30:91c1d09ada54 260 }
mbed_official 30:91c1d09ada54 261
mbed_official 30:91c1d09ada54 262 void serial_clear(serial_t *obj) {
mbed_official 30:91c1d09ada54 263 obj->uart->FCR = 1 << 1 // rx FIFO reset
mbed_official 30:91c1d09ada54 264 | 1 << 2 // tx FIFO reset
mbed_official 30:91c1d09ada54 265 | 0 << 6; // interrupt depth
mbed_official 30:91c1d09ada54 266 }
mbed_official 30:91c1d09ada54 267
mbed_official 30:91c1d09ada54 268 void serial_pinout_tx(PinName tx) {
mbed_official 30:91c1d09ada54 269 pinmap_pinout(tx, PinMap_UART_TX);
mbed_official 30:91c1d09ada54 270 }
mbed_official 30:91c1d09ada54 271
mbed_official 30:91c1d09ada54 272 void serial_break_clear(serial_t *obj) {
mbed_official 30:91c1d09ada54 273 obj->uart->LCR &= ~(1 << 6);
mbed_official 30:91c1d09ada54 274 }
mbed_official 30:91c1d09ada54 275
mbed_official 30:91c1d09ada54 276 void serial_break_set(serial_t *obj) {
mbed_official 30:91c1d09ada54 277 obj->uart->LCR |= 1 << 6;
mbed_official 30:91c1d09ada54 278 }