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 Jul 09 11:00:08 2014 +0100
Revision:
253:fd34e7cf1b98
Parent:
227:7bd0639b8911
Child:
339:40bd4701f3e2
Synchronized with git revision 9413ed9163336a982bd7eaf9d7bece203efdd33d

Full URL: https://github.com/mbedmicro/mbed/commit/9413ed9163336a982bd7eaf9d7bece203efdd33d/

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
bogdanm 13:0645d8841f51 123 pin_mode(tx, PullUp);
bogdanm 13:0645d8841f51 124 pin_mode(rx, PullUp);
mbed_official 253:fd34e7cf1b98 125
bogdanm 13:0645d8841f51 126 switch (uart) {
bogdanm 13:0645d8841f51 127 case UART_0: obj->index = 0; break;
bogdanm 13:0645d8841f51 128 case UART_1: obj->index = 1; break;
bogdanm 13:0645d8841f51 129 case UART_2: obj->index = 2; break;
bogdanm 13:0645d8841f51 130 case UART_3: obj->index = 3; break;
bogdanm 13:0645d8841f51 131 }
mbed_official 64:7b352733b00a 132 uart_data[obj->index].sw_rts.pin = NC;
mbed_official 64:7b352733b00a 133 uart_data[obj->index].sw_cts.pin = NC;
mbed_official 64:7b352733b00a 134 serial_set_flow_control(obj, FlowControlNone, NC, NC);
mbed_official 253:fd34e7cf1b98 135
bogdanm 13:0645d8841f51 136 is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
mbed_official 253:fd34e7cf1b98 137
bogdanm 13:0645d8841f51 138 if (is_stdio_uart) {
bogdanm 13:0645d8841f51 139 stdio_uart_inited = 1;
bogdanm 13:0645d8841f51 140 memcpy(&stdio_uart, obj, sizeof(serial_t));
bogdanm 13:0645d8841f51 141 }
bogdanm 13:0645d8841f51 142 }
bogdanm 13:0645d8841f51 143
bogdanm 13:0645d8841f51 144 void serial_free(serial_t *obj) {
mbed_official 64:7b352733b00a 145 uart_data[obj->index].serial_irq_id = 0;
bogdanm 13:0645d8841f51 146 }
bogdanm 13:0645d8841f51 147
bogdanm 13:0645d8841f51 148 // serial_baud
bogdanm 13:0645d8841f51 149 // set the baud rate, taking in to account the current SystemFrequency
bogdanm 13:0645d8841f51 150 void serial_baud(serial_t *obj, int baudrate) {
mbed_official 227:7bd0639b8911 151 MBED_ASSERT((int)obj->uart <= UART_3);
bogdanm 13:0645d8841f51 152 // The LPC2300 and LPC1700 have a divider and a fractional divider to control the
bogdanm 13:0645d8841f51 153 // baud rate. The formula is:
bogdanm 13:0645d8841f51 154 //
bogdanm 13:0645d8841f51 155 // Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
bogdanm 13:0645d8841f51 156 // where:
bogdanm 13:0645d8841f51 157 // 1 < MulVal <= 15
bogdanm 13:0645d8841f51 158 // 0 <= DivAddVal < 14
bogdanm 13:0645d8841f51 159 // DivAddVal < MulVal
bogdanm 13:0645d8841f51 160 //
bogdanm 13:0645d8841f51 161 // set pclk to /1
bogdanm 13:0645d8841f51 162 switch ((int)obj->uart) {
bogdanm 13:0645d8841f51 163 case UART_0: LPC_SC->PCLKSEL0 &= ~(0x3 << 6); LPC_SC->PCLKSEL0 |= (0x1 << 6); break;
bogdanm 13:0645d8841f51 164 case UART_1: LPC_SC->PCLKSEL0 &= ~(0x3 << 8); LPC_SC->PCLKSEL0 |= (0x1 << 8); break;
bogdanm 13:0645d8841f51 165 case UART_2: LPC_SC->PCLKSEL1 &= ~(0x3 << 16); LPC_SC->PCLKSEL1 |= (0x1 << 16); break;
bogdanm 13:0645d8841f51 166 case UART_3: LPC_SC->PCLKSEL1 &= ~(0x3 << 18); LPC_SC->PCLKSEL1 |= (0x1 << 18); break;
mbed_official 227:7bd0639b8911 167 default: break;
bogdanm 13:0645d8841f51 168 }
mbed_official 253:fd34e7cf1b98 169
bogdanm 13:0645d8841f51 170 uint32_t PCLK = SystemCoreClock;
mbed_official 253:fd34e7cf1b98 171
bogdanm 13:0645d8841f51 172 // First we check to see if the basic divide with no DivAddVal/MulVal
bogdanm 13:0645d8841f51 173 // ratio gives us an integer result. If it does, we set DivAddVal = 0,
bogdanm 13:0645d8841f51 174 // MulVal = 1. Otherwise, we search the valid ratio value range to find
bogdanm 13:0645d8841f51 175 // the closest match. This could be more elegant, using search methods
bogdanm 13:0645d8841f51 176 // and/or lookup tables, but the brute force method is not that much
bogdanm 13:0645d8841f51 177 // slower, and is more maintainable.
bogdanm 13:0645d8841f51 178 uint16_t DL = PCLK / (16 * baudrate);
bogdanm 13:0645d8841f51 179
bogdanm 13:0645d8841f51 180 uint8_t DivAddVal = 0;
bogdanm 13:0645d8841f51 181 uint8_t MulVal = 1;
bogdanm 13:0645d8841f51 182 int hit = 0;
bogdanm 13:0645d8841f51 183 uint16_t dlv;
bogdanm 13:0645d8841f51 184 uint8_t mv, dav;
bogdanm 13:0645d8841f51 185 if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder
mbed_official 51:7838415c99e7 186 int err_best = baudrate, b;
mbed_official 51:7838415c99e7 187 for (mv = 1; mv < 16 && !hit; mv++)
mbed_official 51:7838415c99e7 188 {
mbed_official 51:7838415c99e7 189 for (dav = 0; dav < mv; dav++)
mbed_official 51:7838415c99e7 190 {
mbed_official 51:7838415c99e7 191 // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul))
mbed_official 51:7838415c99e7 192 // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul))
mbed_official 51:7838415c99e7 193 // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding
mbed_official 51:7838415c99e7 194 // 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 195 // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding
mbed_official 51:7838415c99e7 196
mbed_official 51:7838415c99e7 197 if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom
mbed_official 51:7838415c99e7 198 dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2;
mbed_official 51:7838415c99e7 199 else // 2 bits headroom, use more precision
mbed_official 51:7838415c99e7 200 dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2;
mbed_official 51:7838415c99e7 201
mbed_official 51:7838415c99e7 202 // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood
mbed_official 51:7838415c99e7 203 if (dlv == 0)
mbed_official 51:7838415c99e7 204 dlv = 1;
mbed_official 51:7838415c99e7 205
mbed_official 51:7838415c99e7 206 // datasheet says if dav > 0 then DL must be >= 2
mbed_official 51:7838415c99e7 207 if ((dav > 0) && (dlv < 2))
mbed_official 51:7838415c99e7 208 dlv = 2;
mbed_official 51:7838415c99e7 209
mbed_official 51:7838415c99e7 210 // integer rearrangement of the baudrate equation (with rounding)
mbed_official 51:7838415c99e7 211 b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2;
mbed_official 51:7838415c99e7 212
mbed_official 51:7838415c99e7 213 // check to see how we went
mbed_official 51:7838415c99e7 214 b = abs(b - baudrate);
mbed_official 51:7838415c99e7 215 if (b < err_best)
mbed_official 51:7838415c99e7 216 {
mbed_official 51:7838415c99e7 217 err_best = b;
mbed_official 51:7838415c99e7 218
mbed_official 51:7838415c99e7 219 DL = dlv;
mbed_official 51:7838415c99e7 220 MulVal = mv;
mbed_official 51:7838415c99e7 221 DivAddVal = dav;
mbed_official 51:7838415c99e7 222
mbed_official 51:7838415c99e7 223 if (b == baudrate)
mbed_official 51:7838415c99e7 224 {
mbed_official 51:7838415c99e7 225 hit = 1;
mbed_official 51:7838415c99e7 226 break;
bogdanm 13:0645d8841f51 227 }
bogdanm 13:0645d8841f51 228 }
bogdanm 13:0645d8841f51 229 }
bogdanm 13:0645d8841f51 230 }
bogdanm 13:0645d8841f51 231 }
mbed_official 253:fd34e7cf1b98 232
bogdanm 13:0645d8841f51 233 // set LCR[DLAB] to enable writing to divider registers
bogdanm 13:0645d8841f51 234 obj->uart->LCR |= (1 << 7);
mbed_official 253:fd34e7cf1b98 235
bogdanm 13:0645d8841f51 236 // set divider values
bogdanm 13:0645d8841f51 237 obj->uart->DLM = (DL >> 8) & 0xFF;
bogdanm 13:0645d8841f51 238 obj->uart->DLL = (DL >> 0) & 0xFF;
bogdanm 13:0645d8841f51 239 obj->uart->FDR = (uint32_t) DivAddVal << 0
bogdanm 13:0645d8841f51 240 | (uint32_t) MulVal << 4;
mbed_official 253:fd34e7cf1b98 241
bogdanm 13:0645d8841f51 242 // clear LCR[DLAB]
bogdanm 13:0645d8841f51 243 obj->uart->LCR &= ~(1 << 7);
bogdanm 13:0645d8841f51 244 }
bogdanm 13:0645d8841f51 245
bogdanm 13:0645d8841f51 246 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
mbed_official 227:7bd0639b8911 247 MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); // 0: 1 stop bits, 1: 2 stop bits
mbed_official 227:7bd0639b8911 248 MBED_ASSERT((data_bits > 4) && (data_bits < 9)); // 0: 5 data bits ... 3: 8 data bits
mbed_official 227:7bd0639b8911 249 MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven) ||
mbed_official 227:7bd0639b8911 250 (parity == ParityForced1) || (parity == ParityForced0));
mbed_official 227:7bd0639b8911 251
bogdanm 13:0645d8841f51 252 stop_bits -= 1;
bogdanm 13:0645d8841f51 253 data_bits -= 5;
bogdanm 13:0645d8841f51 254
bogdanm 13:0645d8841f51 255 int parity_enable, parity_select;
bogdanm 13:0645d8841f51 256 switch (parity) {
bogdanm 13:0645d8841f51 257 case ParityNone: parity_enable = 0; parity_select = 0; break;
bogdanm 13:0645d8841f51 258 case ParityOdd : parity_enable = 1; parity_select = 0; break;
bogdanm 13:0645d8841f51 259 case ParityEven: parity_enable = 1; parity_select = 1; break;
bogdanm 13:0645d8841f51 260 case ParityForced1: parity_enable = 1; parity_select = 2; break;
bogdanm 13:0645d8841f51 261 case ParityForced0: parity_enable = 1; parity_select = 3; break;
bogdanm 13:0645d8841f51 262 default:
mbed_official 253:fd34e7cf1b98 263 parity_enable = 0, parity_select = 0;
mbed_official 227:7bd0639b8911 264 break;
bogdanm 13:0645d8841f51 265 }
mbed_official 253:fd34e7cf1b98 266
bogdanm 13:0645d8841f51 267 obj->uart->LCR = data_bits << 0
bogdanm 13:0645d8841f51 268 | stop_bits << 2
bogdanm 13:0645d8841f51 269 | parity_enable << 3
bogdanm 13:0645d8841f51 270 | parity_select << 4;
bogdanm 13:0645d8841f51 271 }
bogdanm 13:0645d8841f51 272
bogdanm 13:0645d8841f51 273 /******************************************************************************
bogdanm 13:0645d8841f51 274 * INTERRUPTS HANDLING
bogdanm 13:0645d8841f51 275 ******************************************************************************/
mbed_official 64:7b352733b00a 276 static inline void uart_irq(uint32_t iir, uint32_t index, LPC_UART_TypeDef *puart) {
bogdanm 13:0645d8841f51 277 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
bogdanm 13:0645d8841f51 278 SerialIrq irq_type;
bogdanm 13:0645d8841f51 279 switch (iir) {
bogdanm 13:0645d8841f51 280 case 1: irq_type = TxIrq; break;
bogdanm 13:0645d8841f51 281 case 2: irq_type = RxIrq; break;
bogdanm 13:0645d8841f51 282 default: return;
bogdanm 13:0645d8841f51 283 }
mbed_official 64:7b352733b00a 284 if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) {
mbed_official 64:7b352733b00a 285 gpio_write(&uart_data[index].sw_rts, 1);
mbed_official 64:7b352733b00a 286 // Disable interrupt if it wasn't enabled by other part of the application
mbed_official 64:7b352733b00a 287 if (!uart_data[index].rx_irq_set_api)
mbed_official 64:7b352733b00a 288 puart->IER &= ~(1 << RxIrq);
mbed_official 64:7b352733b00a 289 }
mbed_official 64:7b352733b00a 290 if (uart_data[index].serial_irq_id != 0)
mbed_official 64:7b352733b00a 291 if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api))
mbed_official 64:7b352733b00a 292 irq_handler(uart_data[index].serial_irq_id, irq_type);
bogdanm 13:0645d8841f51 293 }
bogdanm 13:0645d8841f51 294
mbed_official 64:7b352733b00a 295 void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0, (LPC_UART_TypeDef*)LPC_UART0);}
mbed_official 64:7b352733b00a 296 void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1, (LPC_UART_TypeDef*)LPC_UART1);}
mbed_official 64:7b352733b00a 297 void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2, (LPC_UART_TypeDef*)LPC_UART2);}
mbed_official 64:7b352733b00a 298 void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3, (LPC_UART_TypeDef*)LPC_UART3);}
bogdanm 13:0645d8841f51 299
bogdanm 13:0645d8841f51 300 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
bogdanm 13:0645d8841f51 301 irq_handler = handler;
mbed_official 64:7b352733b00a 302 uart_data[obj->index].serial_irq_id = id;
bogdanm 13:0645d8841f51 303 }
bogdanm 13:0645d8841f51 304
mbed_official 64:7b352733b00a 305 static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) {
bogdanm 13:0645d8841f51 306 IRQn_Type irq_n = (IRQn_Type)0;
bogdanm 13:0645d8841f51 307 uint32_t vector = 0;
bogdanm 13:0645d8841f51 308 switch ((int)obj->uart) {
bogdanm 13:0645d8841f51 309 case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
bogdanm 13:0645d8841f51 310 case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
bogdanm 13:0645d8841f51 311 case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
bogdanm 13:0645d8841f51 312 case UART_3: irq_n=UART3_IRQn; vector = (uint32_t)&uart3_irq; break;
bogdanm 13:0645d8841f51 313 }
mbed_official 253:fd34e7cf1b98 314
bogdanm 13:0645d8841f51 315 if (enable) {
bogdanm 13:0645d8841f51 316 obj->uart->IER |= 1 << irq;
bogdanm 13:0645d8841f51 317 NVIC_SetVector(irq_n, vector);
bogdanm 13:0645d8841f51 318 NVIC_EnableIRQ(irq_n);
mbed_official 64:7b352733b00a 319 } 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 320 int all_disabled = 0;
bogdanm 13:0645d8841f51 321 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
bogdanm 13:0645d8841f51 322 obj->uart->IER &= ~(1 << irq);
bogdanm 13:0645d8841f51 323 all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
bogdanm 13:0645d8841f51 324 if (all_disabled)
bogdanm 13:0645d8841f51 325 NVIC_DisableIRQ(irq_n);
bogdanm 13:0645d8841f51 326 }
bogdanm 13:0645d8841f51 327 }
bogdanm 13:0645d8841f51 328
mbed_official 64:7b352733b00a 329 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 64:7b352733b00a 330 if (RxIrq == irq)
mbed_official 64:7b352733b00a 331 uart_data[obj->index].rx_irq_set_api = enable;
mbed_official 64:7b352733b00a 332 serial_irq_set_internal(obj, irq, enable);
mbed_official 64:7b352733b00a 333 }
mbed_official 64:7b352733b00a 334
mbed_official 64:7b352733b00a 335 static void serial_flow_irq_set(serial_t *obj, uint32_t enable) {
mbed_official 64:7b352733b00a 336 uart_data[obj->index].rx_irq_set_flow = enable;
mbed_official 64:7b352733b00a 337 serial_irq_set_internal(obj, RxIrq, enable);
mbed_official 64:7b352733b00a 338 }
mbed_official 64:7b352733b00a 339
bogdanm 13:0645d8841f51 340 /******************************************************************************
bogdanm 13:0645d8841f51 341 * READ/WRITE
bogdanm 13:0645d8841f51 342 ******************************************************************************/
bogdanm 13:0645d8841f51 343 int serial_getc(serial_t *obj) {
bogdanm 13:0645d8841f51 344 while (!serial_readable(obj));
mbed_official 64:7b352733b00a 345 int data = obj->uart->RBR;
mbed_official 64:7b352733b00a 346 if (NC != uart_data[obj->index].sw_rts.pin) {
mbed_official 64:7b352733b00a 347 gpio_write(&uart_data[obj->index].sw_rts, 0);
mbed_official 64:7b352733b00a 348 obj->uart->IER |= 1 << RxIrq;
mbed_official 64:7b352733b00a 349 }
mbed_official 64:7b352733b00a 350 return data;
bogdanm 13:0645d8841f51 351 }
bogdanm 13:0645d8841f51 352
bogdanm 13:0645d8841f51 353 void serial_putc(serial_t *obj, int c) {
bogdanm 13:0645d8841f51 354 while (!serial_writable(obj));
bogdanm 13:0645d8841f51 355 obj->uart->THR = c;
mbed_official 122:6790158fd562 356 uart_data[obj->index].count++;
bogdanm 13:0645d8841f51 357 }
bogdanm 13:0645d8841f51 358
bogdanm 13:0645d8841f51 359 int serial_readable(serial_t *obj) {
bogdanm 13:0645d8841f51 360 return obj->uart->LSR & 0x01;
bogdanm 13:0645d8841f51 361 }
bogdanm 13:0645d8841f51 362
bogdanm 13:0645d8841f51 363 int serial_writable(serial_t *obj) {
mbed_official 122:6790158fd562 364 int isWritable = 1;
mbed_official 64:7b352733b00a 365 if (NC != uart_data[obj->index].sw_cts.pin)
mbed_official 122:6790158fd562 366 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 367 else {
mbed_official 122:6790158fd562 368 if (obj->uart->LSR & 0x20)
mbed_official 122:6790158fd562 369 uart_data[obj->index].count = 0;
mbed_official 122:6790158fd562 370 else if (uart_data[obj->index].count >= 16)
mbed_official 122:6790158fd562 371 isWritable = 0;
mbed_official 122:6790158fd562 372 }
mbed_official 122:6790158fd562 373 return isWritable;
bogdanm 13:0645d8841f51 374 }
bogdanm 13:0645d8841f51 375
bogdanm 13:0645d8841f51 376 void serial_clear(serial_t *obj) {
bogdanm 20:4263a77256ae 377 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
bogdanm 20:4263a77256ae 378 | 1 << 1 // rx FIFO reset
bogdanm 13:0645d8841f51 379 | 1 << 2 // tx FIFO reset
bogdanm 13:0645d8841f51 380 | 0 << 6; // interrupt depth
bogdanm 13:0645d8841f51 381 }
bogdanm 13:0645d8841f51 382
bogdanm 13:0645d8841f51 383 void serial_pinout_tx(PinName tx) {
bogdanm 13:0645d8841f51 384 pinmap_pinout(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 385 }
bogdanm 13:0645d8841f51 386
bogdanm 13:0645d8841f51 387 void serial_break_set(serial_t *obj) {
bogdanm 13:0645d8841f51 388 obj->uart->LCR |= (1 << 6);
bogdanm 13:0645d8841f51 389 }
bogdanm 13:0645d8841f51 390
bogdanm 13:0645d8841f51 391 void serial_break_clear(serial_t *obj) {
bogdanm 13:0645d8841f51 392 obj->uart->LCR &= ~(1 << 6);
bogdanm 13:0645d8841f51 393 }
bogdanm 13:0645d8841f51 394
mbed_official 64:7b352733b00a 395 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) {
mbed_official 64:7b352733b00a 396 // Only UART1 has hardware flow control on LPC176x
mbed_official 64:7b352733b00a 397 LPC_UART1_TypeDef *uart1 = (uint32_t)obj->uart == (uint32_t)LPC_UART1 ? LPC_UART1 : NULL;
mbed_official 64:7b352733b00a 398 int index = obj->index;
mbed_official 64:7b352733b00a 399
mbed_official 64:7b352733b00a 400 // First, disable flow control completely
mbed_official 64:7b352733b00a 401 if (uart1)
mbed_official 64:7b352733b00a 402 uart1->MCR = uart1->MCR & ~UART_MCR_FLOWCTRL_MASK;
mbed_official 64:7b352733b00a 403 uart_data[index].sw_rts.pin = uart_data[index].sw_cts.pin = NC;
mbed_official 64:7b352733b00a 404 serial_flow_irq_set(obj, 0);
mbed_official 64:7b352733b00a 405 if (FlowControlNone == type)
mbed_official 64:7b352733b00a 406 return;
mbed_official 64:7b352733b00a 407 // Check type(s) of flow control to use
mbed_official 64:7b352733b00a 408 UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 409 UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 410 if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != txflow)) {
mbed_official 64:7b352733b00a 411 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 412 if ((UART_1 == uart_cts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 413 // Enable auto-CTS mode
mbed_official 64:7b352733b00a 414 uart1->MCR |= UART_MCR_CTSEN_MASK;
mbed_official 64:7b352733b00a 415 pinmap_pinout(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 416 } else {
mbed_official 64:7b352733b00a 417 // Can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 418 gpio_init_in(&uart_data[index].sw_cts, txflow);
mbed_official 64:7b352733b00a 419 }
mbed_official 64:7b352733b00a 420 }
mbed_official 64:7b352733b00a 421 if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != rxflow)) {
mbed_official 64:7b352733b00a 422 // Enable FIFOs, trigger level of 1 char on RX FIFO
mbed_official 64:7b352733b00a 423 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
mbed_official 64:7b352733b00a 424 | 1 << 1 // Rx Fifo Reset
mbed_official 64:7b352733b00a 425 | 1 << 2 // Tx Fifo Reset
mbed_official 64:7b352733b00a 426 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
mbed_official 64:7b352733b00a 427 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 428 if ((UART_1 == uart_rts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 429 // Enable auto-RTS mode
mbed_official 64:7b352733b00a 430 uart1->MCR |= UART_MCR_RTSEN_MASK;
mbed_official 64:7b352733b00a 431 pinmap_pinout(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 432 } else { // can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 433 gpio_init_out_ex(&uart_data[index].sw_rts, rxflow, 0);
mbed_official 64:7b352733b00a 434 // Enable RX interrupt
mbed_official 64:7b352733b00a 435 serial_flow_irq_set(obj, 1);
mbed_official 64:7b352733b00a 436 }
mbed_official 64:7b352733b00a 437 }
mbed_official 64:7b352733b00a 438 }
mbed_official 64:7b352733b00a 439