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:
Tue Dec 16 08:15:08 2014 +0000
Revision:
440:8a0b45cd594f
Parent:
339:40bd4701f3e2
Synchronized with git revision 67fbbf0b635d0c0d93fbe433306c537c2ad206aa

Full URL: https://github.com/mbedmicro/mbed/commit/67fbbf0b635d0c0d93fbe433306c537c2ad206aa/

Targets: nrf51 - updating app_timer.c from Norid'c SDKv7.1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 13:0645d8841f51 1 /* mbed Microcontroller Library
bogdanm 13:0645d8841f51 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 13:0645d8841f51 3 *
bogdanm 13:0645d8841f51 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 13:0645d8841f51 5 * you may not use this file except in compliance with the License.
bogdanm 13:0645d8841f51 6 * You may obtain a copy of the License at
bogdanm 13:0645d8841f51 7 *
bogdanm 13:0645d8841f51 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 13:0645d8841f51 9 *
bogdanm 13:0645d8841f51 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 13:0645d8841f51 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 13:0645d8841f51 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 13:0645d8841f51 13 * See the License for the specific language governing permissions and
bogdanm 13:0645d8841f51 14 * limitations under the License.
bogdanm 13:0645d8841f51 15 */
bogdanm 13:0645d8841f51 16 // math.h required for floating point operations for baud rate calculation
mbed_official 227:7bd0639b8911 17 #include "mbed_assert.h"
bogdanm 13:0645d8841f51 18 #include <math.h>
bogdanm 13:0645d8841f51 19 #include <string.h>
mbed_official 140:ca60b7a31055 20 #include <stdlib.h>
bogdanm 13:0645d8841f51 21
bogdanm 13:0645d8841f51 22 #include "serial_api.h"
bogdanm 13:0645d8841f51 23 #include "cmsis.h"
bogdanm 13:0645d8841f51 24 #include "pinmap.h"
mbed_official 64:7b352733b00a 25 #include "gpio_api.h"
bogdanm 13:0645d8841f51 26
bogdanm 13:0645d8841f51 27 /******************************************************************************
bogdanm 13:0645d8841f51 28 * INITIALIZATION
bogdanm 13:0645d8841f51 29 ******************************************************************************/
bogdanm 13:0645d8841f51 30 #define UART_NUM 4
bogdanm 13:0645d8841f51 31
bogdanm 13:0645d8841f51 32 static const PinMap PinMap_UART_TX[] = {
bogdanm 13:0645d8841f51 33 {P0_0, UART_3, 2},
bogdanm 13:0645d8841f51 34 {P0_2, UART_0, 1},
bogdanm 13:0645d8841f51 35 {P0_10, UART_2, 1},
bogdanm 13:0645d8841f51 36 {P0_15, UART_1, 1},
bogdanm 13:0645d8841f51 37 {P0_25, UART_3, 3},
bogdanm 13:0645d8841f51 38 {P2_0 , UART_1, 2},
bogdanm 13:0645d8841f51 39 {P2_8 , UART_2, 2},
bogdanm 13:0645d8841f51 40 {P4_28, UART_3, 3},
bogdanm 13:0645d8841f51 41 {NC , NC , 0}
bogdanm 13:0645d8841f51 42 };
bogdanm 13:0645d8841f51 43
bogdanm 13:0645d8841f51 44 static const PinMap PinMap_UART_RX[] = {
bogdanm 13:0645d8841f51 45 {P0_1 , UART_3, 2},
bogdanm 13:0645d8841f51 46 {P0_3 , UART_0, 1},
bogdanm 13:0645d8841f51 47 {P0_11, UART_2, 1},
bogdanm 13:0645d8841f51 48 {P0_16, UART_1, 1},
bogdanm 13:0645d8841f51 49 {P0_26, UART_3, 3},
bogdanm 13:0645d8841f51 50 {P2_1 , UART_1, 2},
bogdanm 13:0645d8841f51 51 {P2_9 , UART_2, 2},
bogdanm 13:0645d8841f51 52 {P4_29, UART_3, 3},
bogdanm 13:0645d8841f51 53 {NC , NC , 0}
bogdanm 13:0645d8841f51 54 };
bogdanm 13:0645d8841f51 55
mbed_official 64:7b352733b00a 56 static const PinMap PinMap_UART_RTS[] = {
mbed_official 64:7b352733b00a 57 {P0_22, UART_1, 1},
mbed_official 64:7b352733b00a 58 {P2_7, UART_1, 2},
mbed_official 64:7b352733b00a 59 {NC, NC, 0}
mbed_official 64:7b352733b00a 60 };
mbed_official 64:7b352733b00a 61
mbed_official 64:7b352733b00a 62 static const PinMap PinMap_UART_CTS[] = {
mbed_official 64:7b352733b00a 63 {P0_17, UART_1, 1},
mbed_official 64:7b352733b00a 64 {P2_2, UART_1, 2},
mbed_official 64:7b352733b00a 65 {NC, NC, 0}
mbed_official 64:7b352733b00a 66 };
mbed_official 64:7b352733b00a 67
mbed_official 64:7b352733b00a 68 #define UART_MCR_RTSEN_MASK (1 << 6)
mbed_official 64:7b352733b00a 69 #define UART_MCR_CTSEN_MASK (1 << 7)
mbed_official 64:7b352733b00a 70 #define UART_MCR_FLOWCTRL_MASK (UART_MCR_RTSEN_MASK | UART_MCR_CTSEN_MASK)
mbed_official 64:7b352733b00a 71
bogdanm 13:0645d8841f51 72 static uart_irq_handler irq_handler;
bogdanm 13:0645d8841f51 73
bogdanm 13:0645d8841f51 74 int stdio_uart_inited = 0;
bogdanm 13:0645d8841f51 75 serial_t stdio_uart;
bogdanm 13:0645d8841f51 76
mbed_official 64:7b352733b00a 77 struct serial_global_data_s {
mbed_official 64:7b352733b00a 78 uint32_t serial_irq_id;
mbed_official 64:7b352733b00a 79 gpio_t sw_rts, sw_cts;
mbed_official 122:6790158fd562 80 uint8_t count, rx_irq_set_flow, rx_irq_set_api;
mbed_official 64:7b352733b00a 81 };
mbed_official 64:7b352733b00a 82
mbed_official 64:7b352733b00a 83 static struct serial_global_data_s uart_data[UART_NUM];
mbed_official 64:7b352733b00a 84
bogdanm 13:0645d8841f51 85 void serial_init(serial_t *obj, PinName tx, PinName rx) {
bogdanm 13:0645d8841f51 86 int is_stdio_uart = 0;
mbed_official 253:fd34e7cf1b98 87
bogdanm 13:0645d8841f51 88 // determine the UART to use
bogdanm 13:0645d8841f51 89 UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 90 UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
bogdanm 13:0645d8841f51 91 UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
mbed_official 227:7bd0639b8911 92 MBED_ASSERT((int)uart != NC);
mbed_official 253:fd34e7cf1b98 93
bogdanm 13:0645d8841f51 94 obj->uart = (LPC_UART_TypeDef *)uart;
bogdanm 13:0645d8841f51 95 // enable power
bogdanm 13:0645d8841f51 96 switch (uart) {
bogdanm 13:0645d8841f51 97 case UART_0: LPC_SC->PCONP |= 1 << 3; break;
bogdanm 13:0645d8841f51 98 case UART_1: LPC_SC->PCONP |= 1 << 4; break;
bogdanm 13:0645d8841f51 99 case UART_2: LPC_SC->PCONP |= 1 << 24; break;
bogdanm 13:0645d8841f51 100 case UART_3: LPC_SC->PCONP |= 1 << 25; break;
bogdanm 13:0645d8841f51 101 }
mbed_official 122:6790158fd562 102
bogdanm 13:0645d8841f51 103 // enable fifos and default rx trigger level
bogdanm 13:0645d8841f51 104 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
bogdanm 13:0645d8841f51 105 | 0 << 1 // Rx Fifo Reset
bogdanm 13:0645d8841f51 106 | 0 << 2 // Tx Fifo Reset
bogdanm 13:0645d8841f51 107 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
bogdanm 13:0645d8841f51 108
bogdanm 13:0645d8841f51 109 // disable irqs
bogdanm 13:0645d8841f51 110 obj->uart->IER = 0 << 0 // Rx Data available irq enable
bogdanm 13:0645d8841f51 111 | 0 << 1 // Tx Fifo empty irq enable
bogdanm 13:0645d8841f51 112 | 0 << 2; // Rx Line Status irq enable
mbed_official 253:fd34e7cf1b98 113
bogdanm 13:0645d8841f51 114 // set default baud rate and format
bogdanm 13:0645d8841f51 115 serial_baud (obj, 9600);
bogdanm 13:0645d8841f51 116 serial_format(obj, 8, ParityNone, 1);
mbed_official 253:fd34e7cf1b98 117
bogdanm 13:0645d8841f51 118 // pinout the chosen uart
bogdanm 13:0645d8841f51 119 pinmap_pinout(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 120 pinmap_pinout(rx, PinMap_UART_RX);
mbed_official 253:fd34e7cf1b98 121
bogdanm 13:0645d8841f51 122 // set rx/tx pins in PullUp mode
mbed_official 339:40bd4701f3e2 123 if (tx != NC) {
mbed_official 339:40bd4701f3e2 124 pin_mode(tx, PullUp);
mbed_official 339:40bd4701f3e2 125 }
mbed_official 339:40bd4701f3e2 126 if (rx != NC) {
mbed_official 339:40bd4701f3e2 127 pin_mode(rx, PullUp);
mbed_official 339:40bd4701f3e2 128 }
mbed_official 253:fd34e7cf1b98 129
bogdanm 13:0645d8841f51 130 switch (uart) {
bogdanm 13:0645d8841f51 131 case UART_0: obj->index = 0; break;
bogdanm 13:0645d8841f51 132 case UART_1: obj->index = 1; break;
bogdanm 13:0645d8841f51 133 case UART_2: obj->index = 2; break;
bogdanm 13:0645d8841f51 134 case UART_3: obj->index = 3; break;
bogdanm 13:0645d8841f51 135 }
mbed_official 64:7b352733b00a 136 uart_data[obj->index].sw_rts.pin = NC;
mbed_official 64:7b352733b00a 137 uart_data[obj->index].sw_cts.pin = NC;
mbed_official 64:7b352733b00a 138 serial_set_flow_control(obj, FlowControlNone, NC, NC);
mbed_official 253:fd34e7cf1b98 139
bogdanm 13:0645d8841f51 140 is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
mbed_official 253:fd34e7cf1b98 141
bogdanm 13:0645d8841f51 142 if (is_stdio_uart) {
bogdanm 13:0645d8841f51 143 stdio_uart_inited = 1;
bogdanm 13:0645d8841f51 144 memcpy(&stdio_uart, obj, sizeof(serial_t));
bogdanm 13:0645d8841f51 145 }
bogdanm 13:0645d8841f51 146 }
bogdanm 13:0645d8841f51 147
bogdanm 13:0645d8841f51 148 void serial_free(serial_t *obj) {
mbed_official 64:7b352733b00a 149 uart_data[obj->index].serial_irq_id = 0;
bogdanm 13:0645d8841f51 150 }
bogdanm 13:0645d8841f51 151
bogdanm 13:0645d8841f51 152 // serial_baud
bogdanm 13:0645d8841f51 153 // set the baud rate, taking in to account the current SystemFrequency
bogdanm 13:0645d8841f51 154 void serial_baud(serial_t *obj, int baudrate) {
mbed_official 227:7bd0639b8911 155 MBED_ASSERT((int)obj->uart <= UART_3);
bogdanm 13:0645d8841f51 156 // The LPC2300 and LPC1700 have a divider and a fractional divider to control the
bogdanm 13:0645d8841f51 157 // baud rate. The formula is:
bogdanm 13:0645d8841f51 158 //
bogdanm 13:0645d8841f51 159 // Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
bogdanm 13:0645d8841f51 160 // where:
bogdanm 13:0645d8841f51 161 // 1 < MulVal <= 15
bogdanm 13:0645d8841f51 162 // 0 <= DivAddVal < 14
bogdanm 13:0645d8841f51 163 // DivAddVal < MulVal
bogdanm 13:0645d8841f51 164 //
bogdanm 13:0645d8841f51 165 // set pclk to /1
bogdanm 13:0645d8841f51 166 switch ((int)obj->uart) {
bogdanm 13:0645d8841f51 167 case UART_0: LPC_SC->PCLKSEL0 &= ~(0x3 << 6); LPC_SC->PCLKSEL0 |= (0x1 << 6); break;
bogdanm 13:0645d8841f51 168 case UART_1: LPC_SC->PCLKSEL0 &= ~(0x3 << 8); LPC_SC->PCLKSEL0 |= (0x1 << 8); break;
bogdanm 13:0645d8841f51 169 case UART_2: LPC_SC->PCLKSEL1 &= ~(0x3 << 16); LPC_SC->PCLKSEL1 |= (0x1 << 16); break;
bogdanm 13:0645d8841f51 170 case UART_3: LPC_SC->PCLKSEL1 &= ~(0x3 << 18); LPC_SC->PCLKSEL1 |= (0x1 << 18); break;
mbed_official 227:7bd0639b8911 171 default: break;
bogdanm 13:0645d8841f51 172 }
mbed_official 253:fd34e7cf1b98 173
bogdanm 13:0645d8841f51 174 uint32_t PCLK = SystemCoreClock;
mbed_official 253:fd34e7cf1b98 175
bogdanm 13:0645d8841f51 176 // First we check to see if the basic divide with no DivAddVal/MulVal
bogdanm 13:0645d8841f51 177 // ratio gives us an integer result. If it does, we set DivAddVal = 0,
bogdanm 13:0645d8841f51 178 // MulVal = 1. Otherwise, we search the valid ratio value range to find
bogdanm 13:0645d8841f51 179 // the closest match. This could be more elegant, using search methods
bogdanm 13:0645d8841f51 180 // and/or lookup tables, but the brute force method is not that much
bogdanm 13:0645d8841f51 181 // slower, and is more maintainable.
bogdanm 13:0645d8841f51 182 uint16_t DL = PCLK / (16 * baudrate);
bogdanm 13:0645d8841f51 183
bogdanm 13:0645d8841f51 184 uint8_t DivAddVal = 0;
bogdanm 13:0645d8841f51 185 uint8_t MulVal = 1;
bogdanm 13:0645d8841f51 186 int hit = 0;
bogdanm 13:0645d8841f51 187 uint16_t dlv;
bogdanm 13:0645d8841f51 188 uint8_t mv, dav;
bogdanm 13:0645d8841f51 189 if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder
mbed_official 51:7838415c99e7 190 int err_best = baudrate, b;
mbed_official 51:7838415c99e7 191 for (mv = 1; mv < 16 && !hit; mv++)
mbed_official 51:7838415c99e7 192 {
mbed_official 51:7838415c99e7 193 for (dav = 0; dav < mv; dav++)
mbed_official 51:7838415c99e7 194 {
mbed_official 51:7838415c99e7 195 // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul))
mbed_official 51:7838415c99e7 196 // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul))
mbed_official 51:7838415c99e7 197 // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding
mbed_official 51:7838415c99e7 198 // 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 199 // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding
mbed_official 51:7838415c99e7 200
mbed_official 51:7838415c99e7 201 if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom
mbed_official 51:7838415c99e7 202 dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2;
mbed_official 51:7838415c99e7 203 else // 2 bits headroom, use more precision
mbed_official 51:7838415c99e7 204 dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2;
mbed_official 51:7838415c99e7 205
mbed_official 51:7838415c99e7 206 // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood
mbed_official 51:7838415c99e7 207 if (dlv == 0)
mbed_official 51:7838415c99e7 208 dlv = 1;
mbed_official 51:7838415c99e7 209
mbed_official 51:7838415c99e7 210 // datasheet says if dav > 0 then DL must be >= 2
mbed_official 51:7838415c99e7 211 if ((dav > 0) && (dlv < 2))
mbed_official 51:7838415c99e7 212 dlv = 2;
mbed_official 51:7838415c99e7 213
mbed_official 51:7838415c99e7 214 // integer rearrangement of the baudrate equation (with rounding)
mbed_official 51:7838415c99e7 215 b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2;
mbed_official 51:7838415c99e7 216
mbed_official 51:7838415c99e7 217 // check to see how we went
mbed_official 51:7838415c99e7 218 b = abs(b - baudrate);
mbed_official 51:7838415c99e7 219 if (b < err_best)
mbed_official 51:7838415c99e7 220 {
mbed_official 51:7838415c99e7 221 err_best = b;
mbed_official 51:7838415c99e7 222
mbed_official 51:7838415c99e7 223 DL = dlv;
mbed_official 51:7838415c99e7 224 MulVal = mv;
mbed_official 51:7838415c99e7 225 DivAddVal = dav;
mbed_official 51:7838415c99e7 226
mbed_official 51:7838415c99e7 227 if (b == baudrate)
mbed_official 51:7838415c99e7 228 {
mbed_official 51:7838415c99e7 229 hit = 1;
mbed_official 51:7838415c99e7 230 break;
bogdanm 13:0645d8841f51 231 }
bogdanm 13:0645d8841f51 232 }
bogdanm 13:0645d8841f51 233 }
bogdanm 13:0645d8841f51 234 }
bogdanm 13:0645d8841f51 235 }
mbed_official 253:fd34e7cf1b98 236
bogdanm 13:0645d8841f51 237 // set LCR[DLAB] to enable writing to divider registers
bogdanm 13:0645d8841f51 238 obj->uart->LCR |= (1 << 7);
mbed_official 253:fd34e7cf1b98 239
bogdanm 13:0645d8841f51 240 // set divider values
bogdanm 13:0645d8841f51 241 obj->uart->DLM = (DL >> 8) & 0xFF;
bogdanm 13:0645d8841f51 242 obj->uart->DLL = (DL >> 0) & 0xFF;
bogdanm 13:0645d8841f51 243 obj->uart->FDR = (uint32_t) DivAddVal << 0
bogdanm 13:0645d8841f51 244 | (uint32_t) MulVal << 4;
mbed_official 253:fd34e7cf1b98 245
bogdanm 13:0645d8841f51 246 // clear LCR[DLAB]
bogdanm 13:0645d8841f51 247 obj->uart->LCR &= ~(1 << 7);
bogdanm 13:0645d8841f51 248 }
bogdanm 13:0645d8841f51 249
bogdanm 13:0645d8841f51 250 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
mbed_official 227:7bd0639b8911 251 MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); // 0: 1 stop bits, 1: 2 stop bits
mbed_official 227:7bd0639b8911 252 MBED_ASSERT((data_bits > 4) && (data_bits < 9)); // 0: 5 data bits ... 3: 8 data bits
mbed_official 227:7bd0639b8911 253 MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven) ||
mbed_official 227:7bd0639b8911 254 (parity == ParityForced1) || (parity == ParityForced0));
mbed_official 227:7bd0639b8911 255
bogdanm 13:0645d8841f51 256 stop_bits -= 1;
bogdanm 13:0645d8841f51 257 data_bits -= 5;
bogdanm 13:0645d8841f51 258
bogdanm 13:0645d8841f51 259 int parity_enable, parity_select;
bogdanm 13:0645d8841f51 260 switch (parity) {
bogdanm 13:0645d8841f51 261 case ParityNone: parity_enable = 0; parity_select = 0; break;
bogdanm 13:0645d8841f51 262 case ParityOdd : parity_enable = 1; parity_select = 0; break;
bogdanm 13:0645d8841f51 263 case ParityEven: parity_enable = 1; parity_select = 1; break;
bogdanm 13:0645d8841f51 264 case ParityForced1: parity_enable = 1; parity_select = 2; break;
bogdanm 13:0645d8841f51 265 case ParityForced0: parity_enable = 1; parity_select = 3; break;
bogdanm 13:0645d8841f51 266 default:
mbed_official 253:fd34e7cf1b98 267 parity_enable = 0, parity_select = 0;
mbed_official 227:7bd0639b8911 268 break;
bogdanm 13:0645d8841f51 269 }
mbed_official 253:fd34e7cf1b98 270
bogdanm 13:0645d8841f51 271 obj->uart->LCR = data_bits << 0
bogdanm 13:0645d8841f51 272 | stop_bits << 2
bogdanm 13:0645d8841f51 273 | parity_enable << 3
bogdanm 13:0645d8841f51 274 | parity_select << 4;
bogdanm 13:0645d8841f51 275 }
bogdanm 13:0645d8841f51 276
bogdanm 13:0645d8841f51 277 /******************************************************************************
bogdanm 13:0645d8841f51 278 * INTERRUPTS HANDLING
bogdanm 13:0645d8841f51 279 ******************************************************************************/
mbed_official 64:7b352733b00a 280 static inline void uart_irq(uint32_t iir, uint32_t index, LPC_UART_TypeDef *puart) {
bogdanm 13:0645d8841f51 281 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
bogdanm 13:0645d8841f51 282 SerialIrq irq_type;
bogdanm 13:0645d8841f51 283 switch (iir) {
bogdanm 13:0645d8841f51 284 case 1: irq_type = TxIrq; break;
bogdanm 13:0645d8841f51 285 case 2: irq_type = RxIrq; break;
bogdanm 13:0645d8841f51 286 default: return;
bogdanm 13:0645d8841f51 287 }
mbed_official 64:7b352733b00a 288 if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) {
mbed_official 64:7b352733b00a 289 gpio_write(&uart_data[index].sw_rts, 1);
mbed_official 64:7b352733b00a 290 // Disable interrupt if it wasn't enabled by other part of the application
mbed_official 64:7b352733b00a 291 if (!uart_data[index].rx_irq_set_api)
mbed_official 64:7b352733b00a 292 puart->IER &= ~(1 << RxIrq);
mbed_official 64:7b352733b00a 293 }
mbed_official 64:7b352733b00a 294 if (uart_data[index].serial_irq_id != 0)
mbed_official 64:7b352733b00a 295 if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api))
mbed_official 64:7b352733b00a 296 irq_handler(uart_data[index].serial_irq_id, irq_type);
bogdanm 13:0645d8841f51 297 }
bogdanm 13:0645d8841f51 298
mbed_official 64:7b352733b00a 299 void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0, (LPC_UART_TypeDef*)LPC_UART0);}
mbed_official 64:7b352733b00a 300 void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1, (LPC_UART_TypeDef*)LPC_UART1);}
mbed_official 64:7b352733b00a 301 void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2, (LPC_UART_TypeDef*)LPC_UART2);}
mbed_official 64:7b352733b00a 302 void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3, (LPC_UART_TypeDef*)LPC_UART3);}
bogdanm 13:0645d8841f51 303
bogdanm 13:0645d8841f51 304 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
bogdanm 13:0645d8841f51 305 irq_handler = handler;
mbed_official 64:7b352733b00a 306 uart_data[obj->index].serial_irq_id = id;
bogdanm 13:0645d8841f51 307 }
bogdanm 13:0645d8841f51 308
mbed_official 64:7b352733b00a 309 static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) {
bogdanm 13:0645d8841f51 310 IRQn_Type irq_n = (IRQn_Type)0;
bogdanm 13:0645d8841f51 311 uint32_t vector = 0;
bogdanm 13:0645d8841f51 312 switch ((int)obj->uart) {
bogdanm 13:0645d8841f51 313 case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
bogdanm 13:0645d8841f51 314 case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
bogdanm 13:0645d8841f51 315 case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
bogdanm 13:0645d8841f51 316 case UART_3: irq_n=UART3_IRQn; vector = (uint32_t)&uart3_irq; break;
bogdanm 13:0645d8841f51 317 }
mbed_official 253:fd34e7cf1b98 318
bogdanm 13:0645d8841f51 319 if (enable) {
bogdanm 13:0645d8841f51 320 obj->uart->IER |= 1 << irq;
bogdanm 13:0645d8841f51 321 NVIC_SetVector(irq_n, vector);
bogdanm 13:0645d8841f51 322 NVIC_EnableIRQ(irq_n);
mbed_official 64:7b352733b00a 323 } else if ((TxIrq == irq) || (uart_data[obj->index].rx_irq_set_api + uart_data[obj->index].rx_irq_set_flow == 0)) { // disable
bogdanm 13:0645d8841f51 324 int all_disabled = 0;
bogdanm 13:0645d8841f51 325 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
bogdanm 13:0645d8841f51 326 obj->uart->IER &= ~(1 << irq);
bogdanm 13:0645d8841f51 327 all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
bogdanm 13:0645d8841f51 328 if (all_disabled)
bogdanm 13:0645d8841f51 329 NVIC_DisableIRQ(irq_n);
bogdanm 13:0645d8841f51 330 }
bogdanm 13:0645d8841f51 331 }
bogdanm 13:0645d8841f51 332
mbed_official 64:7b352733b00a 333 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 64:7b352733b00a 334 if (RxIrq == irq)
mbed_official 64:7b352733b00a 335 uart_data[obj->index].rx_irq_set_api = enable;
mbed_official 64:7b352733b00a 336 serial_irq_set_internal(obj, irq, enable);
mbed_official 64:7b352733b00a 337 }
mbed_official 64:7b352733b00a 338
mbed_official 64:7b352733b00a 339 static void serial_flow_irq_set(serial_t *obj, uint32_t enable) {
mbed_official 64:7b352733b00a 340 uart_data[obj->index].rx_irq_set_flow = enable;
mbed_official 64:7b352733b00a 341 serial_irq_set_internal(obj, RxIrq, enable);
mbed_official 64:7b352733b00a 342 }
mbed_official 64:7b352733b00a 343
bogdanm 13:0645d8841f51 344 /******************************************************************************
bogdanm 13:0645d8841f51 345 * READ/WRITE
bogdanm 13:0645d8841f51 346 ******************************************************************************/
bogdanm 13:0645d8841f51 347 int serial_getc(serial_t *obj) {
bogdanm 13:0645d8841f51 348 while (!serial_readable(obj));
mbed_official 64:7b352733b00a 349 int data = obj->uart->RBR;
mbed_official 64:7b352733b00a 350 if (NC != uart_data[obj->index].sw_rts.pin) {
mbed_official 64:7b352733b00a 351 gpio_write(&uart_data[obj->index].sw_rts, 0);
mbed_official 64:7b352733b00a 352 obj->uart->IER |= 1 << RxIrq;
mbed_official 64:7b352733b00a 353 }
mbed_official 64:7b352733b00a 354 return data;
bogdanm 13:0645d8841f51 355 }
bogdanm 13:0645d8841f51 356
bogdanm 13:0645d8841f51 357 void serial_putc(serial_t *obj, int c) {
bogdanm 13:0645d8841f51 358 while (!serial_writable(obj));
bogdanm 13:0645d8841f51 359 obj->uart->THR = c;
mbed_official 122:6790158fd562 360 uart_data[obj->index].count++;
bogdanm 13:0645d8841f51 361 }
bogdanm 13:0645d8841f51 362
bogdanm 13:0645d8841f51 363 int serial_readable(serial_t *obj) {
bogdanm 13:0645d8841f51 364 return obj->uart->LSR & 0x01;
bogdanm 13:0645d8841f51 365 }
bogdanm 13:0645d8841f51 366
bogdanm 13:0645d8841f51 367 int serial_writable(serial_t *obj) {
mbed_official 122:6790158fd562 368 int isWritable = 1;
mbed_official 64:7b352733b00a 369 if (NC != uart_data[obj->index].sw_cts.pin)
mbed_official 122:6790158fd562 370 isWritable = (gpio_read(&uart_data[obj->index].sw_cts) == 0) && (obj->uart->LSR & 0x40); //If flow control: writable if CTS low + UART done
mbed_official 122:6790158fd562 371 else {
mbed_official 122:6790158fd562 372 if (obj->uart->LSR & 0x20)
mbed_official 122:6790158fd562 373 uart_data[obj->index].count = 0;
mbed_official 122:6790158fd562 374 else if (uart_data[obj->index].count >= 16)
mbed_official 122:6790158fd562 375 isWritable = 0;
mbed_official 122:6790158fd562 376 }
mbed_official 122:6790158fd562 377 return isWritable;
bogdanm 13:0645d8841f51 378 }
bogdanm 13:0645d8841f51 379
bogdanm 13:0645d8841f51 380 void serial_clear(serial_t *obj) {
bogdanm 20:4263a77256ae 381 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
bogdanm 20:4263a77256ae 382 | 1 << 1 // rx FIFO reset
bogdanm 13:0645d8841f51 383 | 1 << 2 // tx FIFO reset
bogdanm 13:0645d8841f51 384 | 0 << 6; // interrupt depth
bogdanm 13:0645d8841f51 385 }
bogdanm 13:0645d8841f51 386
bogdanm 13:0645d8841f51 387 void serial_pinout_tx(PinName tx) {
bogdanm 13:0645d8841f51 388 pinmap_pinout(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 389 }
bogdanm 13:0645d8841f51 390
bogdanm 13:0645d8841f51 391 void serial_break_set(serial_t *obj) {
bogdanm 13:0645d8841f51 392 obj->uart->LCR |= (1 << 6);
bogdanm 13:0645d8841f51 393 }
bogdanm 13:0645d8841f51 394
bogdanm 13:0645d8841f51 395 void serial_break_clear(serial_t *obj) {
bogdanm 13:0645d8841f51 396 obj->uart->LCR &= ~(1 << 6);
bogdanm 13:0645d8841f51 397 }
bogdanm 13:0645d8841f51 398
mbed_official 64:7b352733b00a 399 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) {
mbed_official 64:7b352733b00a 400 // Only UART1 has hardware flow control on LPC176x
mbed_official 64:7b352733b00a 401 LPC_UART1_TypeDef *uart1 = (uint32_t)obj->uart == (uint32_t)LPC_UART1 ? LPC_UART1 : NULL;
mbed_official 64:7b352733b00a 402 int index = obj->index;
mbed_official 64:7b352733b00a 403
mbed_official 64:7b352733b00a 404 // First, disable flow control completely
mbed_official 64:7b352733b00a 405 if (uart1)
mbed_official 64:7b352733b00a 406 uart1->MCR = uart1->MCR & ~UART_MCR_FLOWCTRL_MASK;
mbed_official 64:7b352733b00a 407 uart_data[index].sw_rts.pin = uart_data[index].sw_cts.pin = NC;
mbed_official 64:7b352733b00a 408 serial_flow_irq_set(obj, 0);
mbed_official 64:7b352733b00a 409 if (FlowControlNone == type)
mbed_official 64:7b352733b00a 410 return;
mbed_official 64:7b352733b00a 411 // Check type(s) of flow control to use
mbed_official 64:7b352733b00a 412 UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 413 UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 414 if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != txflow)) {
mbed_official 64:7b352733b00a 415 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 416 if ((UART_1 == uart_cts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 417 // Enable auto-CTS mode
mbed_official 64:7b352733b00a 418 uart1->MCR |= UART_MCR_CTSEN_MASK;
mbed_official 64:7b352733b00a 419 pinmap_pinout(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 420 } else {
mbed_official 64:7b352733b00a 421 // Can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 422 gpio_init_in(&uart_data[index].sw_cts, txflow);
mbed_official 64:7b352733b00a 423 }
mbed_official 64:7b352733b00a 424 }
mbed_official 64:7b352733b00a 425 if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != rxflow)) {
mbed_official 64:7b352733b00a 426 // Enable FIFOs, trigger level of 1 char on RX FIFO
mbed_official 64:7b352733b00a 427 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
mbed_official 64:7b352733b00a 428 | 1 << 1 // Rx Fifo Reset
mbed_official 64:7b352733b00a 429 | 1 << 2 // Tx Fifo Reset
mbed_official 64:7b352733b00a 430 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
mbed_official 64:7b352733b00a 431 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 432 if ((UART_1 == uart_rts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 433 // Enable auto-RTS mode
mbed_official 64:7b352733b00a 434 uart1->MCR |= UART_MCR_RTSEN_MASK;
mbed_official 64:7b352733b00a 435 pinmap_pinout(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 436 } else { // can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 437 gpio_init_out_ex(&uart_data[index].sw_rts, rxflow, 0);
mbed_official 64:7b352733b00a 438 // Enable RX interrupt
mbed_official 64:7b352733b00a 439 serial_flow_irq_set(obj, 1);
mbed_official 64:7b352733b00a 440 }
mbed_official 64:7b352733b00a 441 }
mbed_official 64:7b352733b00a 442 }
mbed_official 64:7b352733b00a 443