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:
Mon Dec 02 10:00:04 2013 +0000
Revision:
51:7838415c99e7
Parent:
30:91c1d09ada54
Synchronized with git revision 6aaa1345164ad42bf681b857dc768b1b65a07595

Full URL: https://github.com/mbedmicro/mbed/commit/6aaa1345164ad42bf681b857dc768b1b65a07595/

Added (deep)sleep to KL25Z

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 51:7838415c99e7 124 int err_best = baudrate, b;
mbed_official 51:7838415c99e7 125 for (mv = 1; mv < 16 && !hit; mv++)
mbed_official 51:7838415c99e7 126 {
mbed_official 51:7838415c99e7 127 for (dav = 0; dav < mv; dav++)
mbed_official 51:7838415c99e7 128 {
mbed_official 51:7838415c99e7 129 // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul))
mbed_official 51:7838415c99e7 130 // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul))
mbed_official 51:7838415c99e7 131 // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding
mbed_official 51:7838415c99e7 132 // 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 133 // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding
mbed_official 51:7838415c99e7 134
mbed_official 51:7838415c99e7 135 if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom
mbed_official 51:7838415c99e7 136 dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2;
mbed_official 51:7838415c99e7 137 else // 2 bits headroom, use more precision
mbed_official 51:7838415c99e7 138 dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2;
mbed_official 51:7838415c99e7 139
mbed_official 51:7838415c99e7 140 // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood
mbed_official 51:7838415c99e7 141 if (dlv == 0)
mbed_official 51:7838415c99e7 142 dlv = 1;
mbed_official 51:7838415c99e7 143
mbed_official 51:7838415c99e7 144 // datasheet says if dav > 0 then DL must be >= 2
mbed_official 51:7838415c99e7 145 if ((dav > 0) && (dlv < 2))
mbed_official 51:7838415c99e7 146 dlv = 2;
mbed_official 51:7838415c99e7 147
mbed_official 51:7838415c99e7 148 // integer rearrangement of the baudrate equation (with rounding)
mbed_official 51:7838415c99e7 149 b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2;
mbed_official 51:7838415c99e7 150
mbed_official 51:7838415c99e7 151 // check to see how we went
mbed_official 51:7838415c99e7 152 b = abs(b - baudrate);
mbed_official 51:7838415c99e7 153 if (b < err_best)
mbed_official 51:7838415c99e7 154 {
mbed_official 51:7838415c99e7 155 err_best = b;
mbed_official 51:7838415c99e7 156
mbed_official 51:7838415c99e7 157 DL = dlv;
mbed_official 51:7838415c99e7 158 MulVal = mv;
mbed_official 51:7838415c99e7 159 DivAddVal = dav;
mbed_official 51:7838415c99e7 160
mbed_official 51:7838415c99e7 161 if (b == baudrate)
mbed_official 51:7838415c99e7 162 {
mbed_official 51:7838415c99e7 163 hit = 1;
mbed_official 51:7838415c99e7 164 break;
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
mbed_official 30:91c1d09ada54 171 // set LCR[DLAB] to enable writing to divider registers
mbed_official 30:91c1d09ada54 172 obj->uart->LCR |= (1 << 7);
mbed_official 30:91c1d09ada54 173
mbed_official 30:91c1d09ada54 174 // set divider values
mbed_official 30:91c1d09ada54 175 obj->uart->DLM = (DL >> 8) & 0xFF;
mbed_official 30:91c1d09ada54 176 obj->uart->DLL = (DL >> 0) & 0xFF;
mbed_official 30:91c1d09ada54 177 obj->uart->FDR = (uint32_t) DivAddVal << 0
mbed_official 30:91c1d09ada54 178 | (uint32_t) MulVal << 4;
mbed_official 30:91c1d09ada54 179
mbed_official 30:91c1d09ada54 180 // clear LCR[DLAB]
mbed_official 30:91c1d09ada54 181 obj->uart->LCR &= ~(1 << 7);
mbed_official 30:91c1d09ada54 182 }
mbed_official 30:91c1d09ada54 183
mbed_official 30:91c1d09ada54 184 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
mbed_official 30:91c1d09ada54 185 // 0: 1 stop bits, 1: 2 stop bits
mbed_official 30:91c1d09ada54 186 if (stop_bits != 1 && stop_bits != 2) {
mbed_official 30:91c1d09ada54 187 error("Invalid stop bits specified");
mbed_official 30:91c1d09ada54 188 }
mbed_official 30:91c1d09ada54 189 stop_bits -= 1;
mbed_official 30:91c1d09ada54 190
mbed_official 30:91c1d09ada54 191 // 0: 5 data bits ... 3: 8 data bits
mbed_official 30:91c1d09ada54 192 if (data_bits < 5 || data_bits > 8) {
mbed_official 30:91c1d09ada54 193 error("Invalid number of bits (%d) in serial format, should be 5..8", data_bits);
mbed_official 30:91c1d09ada54 194 }
mbed_official 30:91c1d09ada54 195 data_bits -= 5;
mbed_official 30:91c1d09ada54 196
mbed_official 30:91c1d09ada54 197 int parity_enable, parity_select;
mbed_official 30:91c1d09ada54 198 switch (parity) {
mbed_official 30:91c1d09ada54 199 case ParityNone: parity_enable = 0; parity_select = 0; break;
mbed_official 30:91c1d09ada54 200 case ParityOdd : parity_enable = 1; parity_select = 0; break;
mbed_official 30:91c1d09ada54 201 case ParityEven: parity_enable = 1; parity_select = 1; break;
mbed_official 30:91c1d09ada54 202 case ParityForced1: parity_enable = 1; parity_select = 2; break;
mbed_official 30:91c1d09ada54 203 case ParityForced0: parity_enable = 1; parity_select = 3; break;
mbed_official 30:91c1d09ada54 204 default:
mbed_official 30:91c1d09ada54 205 error("Invalid serial parity setting");
mbed_official 30:91c1d09ada54 206 return;
mbed_official 30:91c1d09ada54 207 }
mbed_official 30:91c1d09ada54 208
mbed_official 30:91c1d09ada54 209 obj->uart->LCR = data_bits << 0
mbed_official 30:91c1d09ada54 210 | stop_bits << 2
mbed_official 30:91c1d09ada54 211 | parity_enable << 3
mbed_official 30:91c1d09ada54 212 | parity_select << 4;
mbed_official 30:91c1d09ada54 213 }
mbed_official 30:91c1d09ada54 214
mbed_official 30:91c1d09ada54 215 /******************************************************************************
mbed_official 30:91c1d09ada54 216 * INTERRUPTS HANDLING
mbed_official 30:91c1d09ada54 217 ******************************************************************************/
mbed_official 30:91c1d09ada54 218 static inline void uart_irq(uint32_t iir, uint32_t index) {
mbed_official 30:91c1d09ada54 219 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
mbed_official 30:91c1d09ada54 220 SerialIrq irq_type;
mbed_official 30:91c1d09ada54 221 switch (iir) {
mbed_official 30:91c1d09ada54 222 case 1: irq_type = TxIrq; break;
mbed_official 30:91c1d09ada54 223 case 2: irq_type = RxIrq; break;
mbed_official 30:91c1d09ada54 224 default: return;
mbed_official 30:91c1d09ada54 225 }
mbed_official 30:91c1d09ada54 226
mbed_official 30:91c1d09ada54 227 if (serial_irq_ids[index] != 0)
mbed_official 30:91c1d09ada54 228 irq_handler(serial_irq_ids[index], irq_type);
mbed_official 30:91c1d09ada54 229 }
mbed_official 30:91c1d09ada54 230
mbed_official 30:91c1d09ada54 231 void uart0_irq() {uart_irq((LPC_UART->IIR >> 1) & 0x7, 0);}
mbed_official 30:91c1d09ada54 232
mbed_official 30:91c1d09ada54 233 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
mbed_official 30:91c1d09ada54 234 irq_handler = handler;
mbed_official 30:91c1d09ada54 235 serial_irq_ids[obj->index] = id;
mbed_official 30:91c1d09ada54 236 }
mbed_official 30:91c1d09ada54 237
mbed_official 30:91c1d09ada54 238 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 30:91c1d09ada54 239 IRQn_Type irq_n = (IRQn_Type)0;
mbed_official 30:91c1d09ada54 240 uint32_t vector = 0;
mbed_official 30:91c1d09ada54 241 switch ((int)obj->uart) {
mbed_official 30:91c1d09ada54 242 case UART_0:
mbed_official 30:91c1d09ada54 243 irq_n=UART_IRQn;
mbed_official 30:91c1d09ada54 244 vector = (uint32_t)&uart0_irq;
mbed_official 30:91c1d09ada54 245 break;
mbed_official 30:91c1d09ada54 246 default:
mbed_official 30:91c1d09ada54 247 return;
mbed_official 30:91c1d09ada54 248 }
mbed_official 30:91c1d09ada54 249
mbed_official 30:91c1d09ada54 250 if (enable) {
mbed_official 30:91c1d09ada54 251 obj->uart->IER |= 1 << irq;
mbed_official 30:91c1d09ada54 252 NVIC_SetVector(irq_n, vector);
mbed_official 30:91c1d09ada54 253 NVIC_EnableIRQ(irq_n);
mbed_official 30:91c1d09ada54 254 } else { // disable
mbed_official 30:91c1d09ada54 255 int all_disabled = 0;
mbed_official 30:91c1d09ada54 256 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
mbed_official 30:91c1d09ada54 257
mbed_official 30:91c1d09ada54 258 obj->uart->IER &= ~(1 << irq);
mbed_official 30:91c1d09ada54 259 all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
mbed_official 30:91c1d09ada54 260
mbed_official 30:91c1d09ada54 261 if (all_disabled)
mbed_official 30:91c1d09ada54 262 NVIC_DisableIRQ(irq_n);
mbed_official 30:91c1d09ada54 263 }
mbed_official 30:91c1d09ada54 264 }
mbed_official 30:91c1d09ada54 265
mbed_official 30:91c1d09ada54 266 /******************************************************************************
mbed_official 30:91c1d09ada54 267 * READ/WRITE
mbed_official 30:91c1d09ada54 268 ******************************************************************************/
mbed_official 30:91c1d09ada54 269 int serial_getc(serial_t *obj) {
mbed_official 30:91c1d09ada54 270 while (!serial_readable(obj));
mbed_official 30:91c1d09ada54 271 return obj->uart->RBR;
mbed_official 30:91c1d09ada54 272 }
mbed_official 30:91c1d09ada54 273
mbed_official 30:91c1d09ada54 274 void serial_putc(serial_t *obj, int c) {
mbed_official 30:91c1d09ada54 275 while (!serial_writable(obj));
mbed_official 30:91c1d09ada54 276 obj->uart->THR = c;
mbed_official 30:91c1d09ada54 277 }
mbed_official 30:91c1d09ada54 278
mbed_official 30:91c1d09ada54 279 int serial_readable(serial_t *obj) {
mbed_official 30:91c1d09ada54 280 return obj->uart->LSR & 0x01;
mbed_official 30:91c1d09ada54 281 }
mbed_official 30:91c1d09ada54 282
mbed_official 30:91c1d09ada54 283 int serial_writable(serial_t *obj) {
mbed_official 30:91c1d09ada54 284 return obj->uart->LSR & 0x20;
mbed_official 30:91c1d09ada54 285 }
mbed_official 30:91c1d09ada54 286
mbed_official 30:91c1d09ada54 287 void serial_clear(serial_t *obj) {
mbed_official 30:91c1d09ada54 288 obj->uart->FCR = 1 << 1 // rx FIFO reset
mbed_official 30:91c1d09ada54 289 | 1 << 2 // tx FIFO reset
mbed_official 30:91c1d09ada54 290 | 0 << 6; // interrupt depth
mbed_official 30:91c1d09ada54 291 }
mbed_official 30:91c1d09ada54 292
mbed_official 30:91c1d09ada54 293 void serial_pinout_tx(PinName tx) {
mbed_official 30:91c1d09ada54 294 pinmap_pinout(tx, PinMap_UART_TX);
mbed_official 30:91c1d09ada54 295 }
mbed_official 30:91c1d09ada54 296
mbed_official 30:91c1d09ada54 297 void serial_break_clear(serial_t *obj) {
mbed_official 30:91c1d09ada54 298 obj->uart->LCR &= ~(1 << 6);
mbed_official 30:91c1d09ada54 299 }
mbed_official 30:91c1d09ada54 300
mbed_official 30:91c1d09ada54 301 void serial_break_set(serial_t *obj) {
mbed_official 30:91c1d09ada54 302 obj->uart->LCR |= 1 << 6;
mbed_official 30:91c1d09ada54 303 }