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 Feb 03 17:00:07 2015 +0000
Revision:
463:5c73c3744533
Parent:
339:40bd4701f3e2
Synchronized with git revision 134a67aab259d410373367cb96b73420b390d385

Full URL: https://github.com/mbedmicro/mbed/commit/134a67aab259d410373367cb96b73420b390d385/

Who changed what in which revision?

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