mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

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 Jun 11 16:00:09 2014 +0100
Revision:
227:7bd0639b8911
Parent:
140:ca60b7a31055
Child:
339:40bd4701f3e2
Synchronized with git revision d58d532ebc0e0a96f4fffb8edefc082b71b964af

Full URL: https://github.com/mbedmicro/mbed/commit/d58d532ebc0e0a96f4fffb8edefc082b71b964af/

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 227:7bd0639b8911 17 #include "mbed_assert.h"
mbed_official 30:91c1d09ada54 18 #include <math.h>
mbed_official 30:91c1d09ada54 19 #include <string.h>
mbed_official 140:ca60b7a31055 20 #include <stdlib.h>
mbed_official 30:91c1d09ada54 21
mbed_official 30:91c1d09ada54 22 #include "serial_api.h"
mbed_official 30:91c1d09ada54 23 #include "cmsis.h"
mbed_official 30:91c1d09ada54 24 #include "pinmap.h"
mbed_official 30:91c1d09ada54 25
mbed_official 30:91c1d09ada54 26 /******************************************************************************
mbed_official 30:91c1d09ada54 27 * INITIALIZATION
mbed_official 30:91c1d09ada54 28 ******************************************************************************/
mbed_official 30:91c1d09ada54 29 #define UART_NUM 1
mbed_official 30:91c1d09ada54 30
mbed_official 30:91c1d09ada54 31 static const PinMap PinMap_UART_TX[] = {
mbed_official 30:91c1d09ada54 32 {P2_8 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 33 {P3_5 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 34 {P3_0 , UART_0, 0x03},
mbed_official 30:91c1d09ada54 35 {P1_7 , UART_0, 0x01},
mbed_official 30:91c1d09ada54 36 {NC , NC , 0x00}
mbed_official 30:91c1d09ada54 37 };
mbed_official 30:91c1d09ada54 38
mbed_official 30:91c1d09ada54 39 static const PinMap PinMap_UART_RX[] = {
mbed_official 30:91c1d09ada54 40 {P2_7 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 41 {P3_4 , UART_0, 0x02},
mbed_official 30:91c1d09ada54 42 {P3_1 , UART_0, 0x03},
mbed_official 30:91c1d09ada54 43 {P1_6 , UART_0, 0x01},
mbed_official 30:91c1d09ada54 44 {NC , NC , 0x00}
mbed_official 30:91c1d09ada54 45 };
mbed_official 30:91c1d09ada54 46
mbed_official 30:91c1d09ada54 47 static uint32_t serial_irq_ids[UART_NUM] = {0};
mbed_official 30:91c1d09ada54 48 static uart_irq_handler irq_handler;
mbed_official 30:91c1d09ada54 49
mbed_official 30:91c1d09ada54 50 int stdio_uart_inited = 0;
mbed_official 30:91c1d09ada54 51 serial_t stdio_uart;
mbed_official 30:91c1d09ada54 52
mbed_official 30:91c1d09ada54 53 void serial_init(serial_t *obj, PinName tx, PinName rx) {
mbed_official 30:91c1d09ada54 54 int is_stdio_uart = 0;
mbed_official 30:91c1d09ada54 55
mbed_official 30:91c1d09ada54 56 // determine the UART to use
mbed_official 30:91c1d09ada54 57 UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
mbed_official 30:91c1d09ada54 58 UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
mbed_official 30:91c1d09ada54 59 UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
mbed_official 227:7bd0639b8911 60 MBED_ASSERT((int)uart != NC);
mbed_official 30:91c1d09ada54 61
mbed_official 30:91c1d09ada54 62 obj->uart = (LPC_UART_TypeDef *)uart;
mbed_official 30:91c1d09ada54 63 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
mbed_official 30:91c1d09ada54 64
mbed_official 30:91c1d09ada54 65 // enable fifos and default rx trigger level
mbed_official 30:91c1d09ada54 66 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
mbed_official 30:91c1d09ada54 67 | 0 << 1 // Rx Fifo Reset
mbed_official 30:91c1d09ada54 68 | 0 << 2 // Tx Fifo Reset
mbed_official 30:91c1d09ada54 69 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
mbed_official 30:91c1d09ada54 70
mbed_official 30:91c1d09ada54 71 // disable irqs
mbed_official 30:91c1d09ada54 72 obj->uart->IER = 0 << 0 // Rx Data available irq enable
mbed_official 30:91c1d09ada54 73 | 0 << 1 // Tx Fifo empty irq enable
mbed_official 30:91c1d09ada54 74 | 0 << 2; // Rx Line Status irq enable
mbed_official 30:91c1d09ada54 75
mbed_official 30:91c1d09ada54 76 // set default baud rate and format
mbed_official 30:91c1d09ada54 77 serial_baud (obj, 9600);
mbed_official 30:91c1d09ada54 78 serial_format(obj, 8, ParityNone, 1);
mbed_official 30:91c1d09ada54 79
mbed_official 30:91c1d09ada54 80 // pinout the chosen uart
mbed_official 30:91c1d09ada54 81 pinmap_pinout(tx, PinMap_UART_TX);
mbed_official 30:91c1d09ada54 82 pinmap_pinout(rx, PinMap_UART_RX);
mbed_official 30:91c1d09ada54 83
mbed_official 30:91c1d09ada54 84 // set rx/tx pins in PullUp mode
mbed_official 30:91c1d09ada54 85 pin_mode(tx, PullUp);
mbed_official 30:91c1d09ada54 86 pin_mode(rx, PullUp);
mbed_official 30:91c1d09ada54 87
mbed_official 30:91c1d09ada54 88 switch (uart) {
mbed_official 30:91c1d09ada54 89 case UART_0: obj->index = 0; break;
mbed_official 30:91c1d09ada54 90 }
mbed_official 30:91c1d09ada54 91
mbed_official 30:91c1d09ada54 92 is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
mbed_official 30:91c1d09ada54 93
mbed_official 30:91c1d09ada54 94 if (is_stdio_uart) {
mbed_official 30:91c1d09ada54 95 stdio_uart_inited = 1;
mbed_official 30:91c1d09ada54 96 memcpy(&stdio_uart, obj, sizeof(serial_t));
mbed_official 30:91c1d09ada54 97 }
mbed_official 30:91c1d09ada54 98 }
mbed_official 30:91c1d09ada54 99
mbed_official 30:91c1d09ada54 100 void serial_free(serial_t *obj) {
mbed_official 30:91c1d09ada54 101 serial_irq_ids[obj->index] = 0;
mbed_official 30:91c1d09ada54 102 }
mbed_official 30:91c1d09ada54 103
mbed_official 30:91c1d09ada54 104 // serial_baud
mbed_official 30:91c1d09ada54 105 // set the baud rate, taking in to account the current SystemFrequency
mbed_official 30:91c1d09ada54 106 void serial_baud(serial_t *obj, int baudrate) {
mbed_official 30:91c1d09ada54 107 LPC_SYSCON->UARTCLKDIV = 0x1;
mbed_official 30:91c1d09ada54 108 uint32_t PCLK = SystemCoreClock;
mbed_official 30:91c1d09ada54 109 // First we check to see if the basic divide with no DivAddVal/MulVal
mbed_official 30:91c1d09ada54 110 // ratio gives us an integer result. If it does, we set DivAddVal = 0,
mbed_official 30:91c1d09ada54 111 // MulVal = 1. Otherwise, we search the valid ratio value range to find
mbed_official 30:91c1d09ada54 112 // the closest match. This could be more elegant, using search methods
mbed_official 30:91c1d09ada54 113 // and/or lookup tables, but the brute force method is not that much
mbed_official 30:91c1d09ada54 114 // slower, and is more maintainable.
mbed_official 30:91c1d09ada54 115 uint16_t DL = PCLK / (16 * baudrate);
mbed_official 30:91c1d09ada54 116
mbed_official 30:91c1d09ada54 117 uint8_t DivAddVal = 0;
mbed_official 30:91c1d09ada54 118 uint8_t MulVal = 1;
mbed_official 30:91c1d09ada54 119 int hit = 0;
mbed_official 30:91c1d09ada54 120 uint16_t dlv;
mbed_official 30:91c1d09ada54 121 uint8_t mv, dav;
mbed_official 30:91c1d09ada54 122 if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder
mbed_official 51:7838415c99e7 123 int err_best = baudrate, b;
mbed_official 51:7838415c99e7 124 for (mv = 1; mv < 16 && !hit; mv++)
mbed_official 51:7838415c99e7 125 {
mbed_official 51:7838415c99e7 126 for (dav = 0; dav < mv; dav++)
mbed_official 51:7838415c99e7 127 {
mbed_official 51:7838415c99e7 128 // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul))
mbed_official 51:7838415c99e7 129 // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul))
mbed_official 51:7838415c99e7 130 // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding
mbed_official 51:7838415c99e7 131 // for many values of mul and PCLK we have 2 or more bits of headroom which can be used to improve precision
mbed_official 51:7838415c99e7 132 // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding
mbed_official 51:7838415c99e7 133
mbed_official 51:7838415c99e7 134 if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom
mbed_official 51:7838415c99e7 135 dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2;
mbed_official 51:7838415c99e7 136 else // 2 bits headroom, use more precision
mbed_official 51:7838415c99e7 137 dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2;
mbed_official 51:7838415c99e7 138
mbed_official 51:7838415c99e7 139 // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood
mbed_official 51:7838415c99e7 140 if (dlv == 0)
mbed_official 51:7838415c99e7 141 dlv = 1;
mbed_official 51:7838415c99e7 142
mbed_official 51:7838415c99e7 143 // datasheet says if dav > 0 then DL must be >= 2
mbed_official 51:7838415c99e7 144 if ((dav > 0) && (dlv < 2))
mbed_official 51:7838415c99e7 145 dlv = 2;
mbed_official 51:7838415c99e7 146
mbed_official 51:7838415c99e7 147 // integer rearrangement of the baudrate equation (with rounding)
mbed_official 51:7838415c99e7 148 b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2;
mbed_official 51:7838415c99e7 149
mbed_official 51:7838415c99e7 150 // check to see how we went
mbed_official 51:7838415c99e7 151 b = abs(b - baudrate);
mbed_official 51:7838415c99e7 152 if (b < err_best)
mbed_official 51:7838415c99e7 153 {
mbed_official 51:7838415c99e7 154 err_best = b;
mbed_official 51:7838415c99e7 155
mbed_official 51:7838415c99e7 156 DL = dlv;
mbed_official 51:7838415c99e7 157 MulVal = mv;
mbed_official 51:7838415c99e7 158 DivAddVal = dav;
mbed_official 51:7838415c99e7 159
mbed_official 51:7838415c99e7 160 if (b == baudrate)
mbed_official 51:7838415c99e7 161 {
mbed_official 51:7838415c99e7 162 hit = 1;
mbed_official 51:7838415c99e7 163 break;
mbed_official 30:91c1d09ada54 164 }
mbed_official 30:91c1d09ada54 165 }
mbed_official 30:91c1d09ada54 166 }
mbed_official 30:91c1d09ada54 167 }
mbed_official 30:91c1d09ada54 168 }
mbed_official 30:91c1d09ada54 169
mbed_official 30:91c1d09ada54 170 // set LCR[DLAB] to enable writing to divider registers
mbed_official 30:91c1d09ada54 171 obj->uart->LCR |= (1 << 7);
mbed_official 30:91c1d09ada54 172
mbed_official 30:91c1d09ada54 173 // set divider values
mbed_official 30:91c1d09ada54 174 obj->uart->DLM = (DL >> 8) & 0xFF;
mbed_official 30:91c1d09ada54 175 obj->uart->DLL = (DL >> 0) & 0xFF;
mbed_official 30:91c1d09ada54 176 obj->uart->FDR = (uint32_t) DivAddVal << 0
mbed_official 30:91c1d09ada54 177 | (uint32_t) MulVal << 4;
mbed_official 30:91c1d09ada54 178
mbed_official 30:91c1d09ada54 179 // clear LCR[DLAB]
mbed_official 30:91c1d09ada54 180 obj->uart->LCR &= ~(1 << 7);
mbed_official 30:91c1d09ada54 181 }
mbed_official 30:91c1d09ada54 182
mbed_official 30:91c1d09ada54 183 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
mbed_official 227:7bd0639b8911 184 MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); // 0: 1 stop bits, 1: 2 stop bits
mbed_official 227:7bd0639b8911 185 MBED_ASSERT((data_bits > 4) && (data_bits < 9)); // 0: 5 data bits ... 3: 8 data bits
mbed_official 227:7bd0639b8911 186 MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven) ||
mbed_official 227:7bd0639b8911 187 (parity == ParityForced1) || (parity == ParityForced0));
mbed_official 227:7bd0639b8911 188
mbed_official 30:91c1d09ada54 189 stop_bits -= 1;
mbed_official 30:91c1d09ada54 190 data_bits -= 5;
mbed_official 30:91c1d09ada54 191
mbed_official 30:91c1d09ada54 192 int parity_enable, parity_select;
mbed_official 30:91c1d09ada54 193 switch (parity) {
mbed_official 30:91c1d09ada54 194 case ParityNone: parity_enable = 0; parity_select = 0; break;
mbed_official 30:91c1d09ada54 195 case ParityOdd : parity_enable = 1; parity_select = 0; break;
mbed_official 30:91c1d09ada54 196 case ParityEven: parity_enable = 1; parity_select = 1; break;
mbed_official 30:91c1d09ada54 197 case ParityForced1: parity_enable = 1; parity_select = 2; break;
mbed_official 30:91c1d09ada54 198 case ParityForced0: parity_enable = 1; parity_select = 3; break;
mbed_official 30:91c1d09ada54 199 default:
mbed_official 227:7bd0639b8911 200 break;
mbed_official 30:91c1d09ada54 201 }
mbed_official 30:91c1d09ada54 202
mbed_official 30:91c1d09ada54 203 obj->uart->LCR = data_bits << 0
mbed_official 30:91c1d09ada54 204 | stop_bits << 2
mbed_official 30:91c1d09ada54 205 | parity_enable << 3
mbed_official 30:91c1d09ada54 206 | parity_select << 4;
mbed_official 30:91c1d09ada54 207 }
mbed_official 30:91c1d09ada54 208
mbed_official 30:91c1d09ada54 209 /******************************************************************************
mbed_official 30:91c1d09ada54 210 * INTERRUPTS HANDLING
mbed_official 30:91c1d09ada54 211 ******************************************************************************/
mbed_official 30:91c1d09ada54 212 static inline void uart_irq(uint32_t iir, uint32_t index) {
mbed_official 30:91c1d09ada54 213 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
mbed_official 30:91c1d09ada54 214 SerialIrq irq_type;
mbed_official 30:91c1d09ada54 215 switch (iir) {
mbed_official 30:91c1d09ada54 216 case 1: irq_type = TxIrq; break;
mbed_official 30:91c1d09ada54 217 case 2: irq_type = RxIrq; break;
mbed_official 30:91c1d09ada54 218 default: return;
mbed_official 30:91c1d09ada54 219 }
mbed_official 30:91c1d09ada54 220
mbed_official 30:91c1d09ada54 221 if (serial_irq_ids[index] != 0)
mbed_official 30:91c1d09ada54 222 irq_handler(serial_irq_ids[index], irq_type);
mbed_official 30:91c1d09ada54 223 }
mbed_official 30:91c1d09ada54 224
mbed_official 30:91c1d09ada54 225 void uart0_irq() {uart_irq((LPC_UART->IIR >> 1) & 0x7, 0);}
mbed_official 30:91c1d09ada54 226
mbed_official 30:91c1d09ada54 227 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
mbed_official 30:91c1d09ada54 228 irq_handler = handler;
mbed_official 30:91c1d09ada54 229 serial_irq_ids[obj->index] = id;
mbed_official 30:91c1d09ada54 230 }
mbed_official 30:91c1d09ada54 231
mbed_official 30:91c1d09ada54 232 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 30:91c1d09ada54 233 IRQn_Type irq_n = (IRQn_Type)0;
mbed_official 30:91c1d09ada54 234 uint32_t vector = 0;
mbed_official 30:91c1d09ada54 235 switch ((int)obj->uart) {
mbed_official 30:91c1d09ada54 236 case UART_0:
mbed_official 30:91c1d09ada54 237 irq_n=UART_IRQn;
mbed_official 30:91c1d09ada54 238 vector = (uint32_t)&uart0_irq;
mbed_official 30:91c1d09ada54 239 break;
mbed_official 30:91c1d09ada54 240 default:
mbed_official 30:91c1d09ada54 241 return;
mbed_official 30:91c1d09ada54 242 }
mbed_official 30:91c1d09ada54 243
mbed_official 30:91c1d09ada54 244 if (enable) {
mbed_official 30:91c1d09ada54 245 obj->uart->IER |= 1 << irq;
mbed_official 30:91c1d09ada54 246 NVIC_SetVector(irq_n, vector);
mbed_official 30:91c1d09ada54 247 NVIC_EnableIRQ(irq_n);
mbed_official 30:91c1d09ada54 248 } else { // disable
mbed_official 30:91c1d09ada54 249 int all_disabled = 0;
mbed_official 30:91c1d09ada54 250 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
mbed_official 30:91c1d09ada54 251
mbed_official 30:91c1d09ada54 252 obj->uart->IER &= ~(1 << irq);
mbed_official 30:91c1d09ada54 253 all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
mbed_official 30:91c1d09ada54 254
mbed_official 30:91c1d09ada54 255 if (all_disabled)
mbed_official 30:91c1d09ada54 256 NVIC_DisableIRQ(irq_n);
mbed_official 30:91c1d09ada54 257 }
mbed_official 30:91c1d09ada54 258 }
mbed_official 30:91c1d09ada54 259
mbed_official 30:91c1d09ada54 260 /******************************************************************************
mbed_official 30:91c1d09ada54 261 * READ/WRITE
mbed_official 30:91c1d09ada54 262 ******************************************************************************/
mbed_official 30:91c1d09ada54 263 int serial_getc(serial_t *obj) {
mbed_official 30:91c1d09ada54 264 while (!serial_readable(obj));
mbed_official 30:91c1d09ada54 265 return obj->uart->RBR;
mbed_official 30:91c1d09ada54 266 }
mbed_official 30:91c1d09ada54 267
mbed_official 30:91c1d09ada54 268 void serial_putc(serial_t *obj, int c) {
mbed_official 30:91c1d09ada54 269 while (!serial_writable(obj));
mbed_official 30:91c1d09ada54 270 obj->uart->THR = c;
mbed_official 30:91c1d09ada54 271 }
mbed_official 30:91c1d09ada54 272
mbed_official 30:91c1d09ada54 273 int serial_readable(serial_t *obj) {
mbed_official 30:91c1d09ada54 274 return obj->uart->LSR & 0x01;
mbed_official 30:91c1d09ada54 275 }
mbed_official 30:91c1d09ada54 276
mbed_official 30:91c1d09ada54 277 int serial_writable(serial_t *obj) {
mbed_official 30:91c1d09ada54 278 return obj->uart->LSR & 0x20;
mbed_official 30:91c1d09ada54 279 }
mbed_official 30:91c1d09ada54 280
mbed_official 30:91c1d09ada54 281 void serial_clear(serial_t *obj) {
mbed_official 30:91c1d09ada54 282 obj->uart->FCR = 1 << 1 // rx FIFO reset
mbed_official 30:91c1d09ada54 283 | 1 << 2 // tx FIFO reset
mbed_official 30:91c1d09ada54 284 | 0 << 6; // interrupt depth
mbed_official 30:91c1d09ada54 285 }
mbed_official 30:91c1d09ada54 286
mbed_official 30:91c1d09ada54 287 void serial_pinout_tx(PinName tx) {
mbed_official 30:91c1d09ada54 288 pinmap_pinout(tx, PinMap_UART_TX);
mbed_official 30:91c1d09ada54 289 }
mbed_official 30:91c1d09ada54 290
mbed_official 30:91c1d09ada54 291 void serial_break_clear(serial_t *obj) {
mbed_official 30:91c1d09ada54 292 obj->uart->LCR &= ~(1 << 6);
mbed_official 30:91c1d09ada54 293 }
mbed_official 30:91c1d09ada54 294
mbed_official 30:91c1d09ada54 295 void serial_break_set(serial_t *obj) {
mbed_official 30:91c1d09ada54 296 obj->uart->LCR |= 1 << 6;
mbed_official 30:91c1d09ada54 297 }