mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

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

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Wed Jun 11 16:00:09 2014 +0100
Revision:
227:7bd0639b8911
Parent:
140:ca60b7a31055
Child:
253:fd34e7cf1b98
Synchronized with git revision d58d532ebc0e0a96f4fffb8edefc082b71b964af

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
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;
bogdanm 13:0645d8841f51 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);
bogdanm 13:0645d8841f51 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
bogdanm 13:0645d8841f51 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);
bogdanm 13:0645d8841f51 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);
bogdanm 13:0645d8841f51 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);
bogdanm 13:0645d8841f51 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);
bogdanm 13:0645d8841f51 135
bogdanm 13:0645d8841f51 136 is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
bogdanm 13:0645d8841f51 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 }
bogdanm 13:0645d8841f51 169
bogdanm 13:0645d8841f51 170 uint32_t PCLK = SystemCoreClock;
bogdanm 13:0645d8841f51 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 }
bogdanm 13:0645d8841f51 232
bogdanm 13:0645d8841f51 233 // set LCR[DLAB] to enable writing to divider registers
bogdanm 13:0645d8841f51 234 obj->uart->LCR |= (1 << 7);
bogdanm 13:0645d8841f51 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;
bogdanm 13:0645d8841f51 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 227:7bd0639b8911 263 break;
bogdanm 13:0645d8841f51 264 }
bogdanm 13:0645d8841f51 265
bogdanm 13:0645d8841f51 266 obj->uart->LCR = data_bits << 0
bogdanm 13:0645d8841f51 267 | stop_bits << 2
bogdanm 13:0645d8841f51 268 | parity_enable << 3
bogdanm 13:0645d8841f51 269 | parity_select << 4;
bogdanm 13:0645d8841f51 270 }
bogdanm 13:0645d8841f51 271
bogdanm 13:0645d8841f51 272 /******************************************************************************
bogdanm 13:0645d8841f51 273 * INTERRUPTS HANDLING
bogdanm 13:0645d8841f51 274 ******************************************************************************/
mbed_official 64:7b352733b00a 275 static inline void uart_irq(uint32_t iir, uint32_t index, LPC_UART_TypeDef *puart) {
bogdanm 13:0645d8841f51 276 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
bogdanm 13:0645d8841f51 277 SerialIrq irq_type;
bogdanm 13:0645d8841f51 278 switch (iir) {
bogdanm 13:0645d8841f51 279 case 1: irq_type = TxIrq; break;
bogdanm 13:0645d8841f51 280 case 2: irq_type = RxIrq; break;
bogdanm 13:0645d8841f51 281 default: return;
bogdanm 13:0645d8841f51 282 }
mbed_official 64:7b352733b00a 283 if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) {
mbed_official 64:7b352733b00a 284 gpio_write(&uart_data[index].sw_rts, 1);
mbed_official 64:7b352733b00a 285 // Disable interrupt if it wasn't enabled by other part of the application
mbed_official 64:7b352733b00a 286 if (!uart_data[index].rx_irq_set_api)
mbed_official 64:7b352733b00a 287 puart->IER &= ~(1 << RxIrq);
mbed_official 64:7b352733b00a 288 }
mbed_official 64:7b352733b00a 289 if (uart_data[index].serial_irq_id != 0)
mbed_official 64:7b352733b00a 290 if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api))
mbed_official 64:7b352733b00a 291 irq_handler(uart_data[index].serial_irq_id, irq_type);
bogdanm 13:0645d8841f51 292 }
bogdanm 13:0645d8841f51 293
mbed_official 64:7b352733b00a 294 void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0, (LPC_UART_TypeDef*)LPC_UART0);}
mbed_official 64:7b352733b00a 295 void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1, (LPC_UART_TypeDef*)LPC_UART1);}
mbed_official 64:7b352733b00a 296 void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2, (LPC_UART_TypeDef*)LPC_UART2);}
mbed_official 64:7b352733b00a 297 void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3, (LPC_UART_TypeDef*)LPC_UART3);}
bogdanm 13:0645d8841f51 298
bogdanm 13:0645d8841f51 299 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
bogdanm 13:0645d8841f51 300 irq_handler = handler;
mbed_official 64:7b352733b00a 301 uart_data[obj->index].serial_irq_id = id;
bogdanm 13:0645d8841f51 302 }
bogdanm 13:0645d8841f51 303
mbed_official 64:7b352733b00a 304 static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) {
bogdanm 13:0645d8841f51 305 IRQn_Type irq_n = (IRQn_Type)0;
bogdanm 13:0645d8841f51 306 uint32_t vector = 0;
bogdanm 13:0645d8841f51 307 switch ((int)obj->uart) {
bogdanm 13:0645d8841f51 308 case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
bogdanm 13:0645d8841f51 309 case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
bogdanm 13:0645d8841f51 310 case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
bogdanm 13:0645d8841f51 311 case UART_3: irq_n=UART3_IRQn; vector = (uint32_t)&uart3_irq; break;
bogdanm 13:0645d8841f51 312 }
bogdanm 13:0645d8841f51 313
bogdanm 13:0645d8841f51 314 if (enable) {
bogdanm 13:0645d8841f51 315 obj->uart->IER |= 1 << irq;
bogdanm 13:0645d8841f51 316 NVIC_SetVector(irq_n, vector);
bogdanm 13:0645d8841f51 317 NVIC_EnableIRQ(irq_n);
mbed_official 64:7b352733b00a 318 } 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 319 int all_disabled = 0;
bogdanm 13:0645d8841f51 320 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
bogdanm 13:0645d8841f51 321 obj->uart->IER &= ~(1 << irq);
bogdanm 13:0645d8841f51 322 all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
bogdanm 13:0645d8841f51 323 if (all_disabled)
bogdanm 13:0645d8841f51 324 NVIC_DisableIRQ(irq_n);
bogdanm 13:0645d8841f51 325 }
bogdanm 13:0645d8841f51 326 }
bogdanm 13:0645d8841f51 327
mbed_official 64:7b352733b00a 328 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 64:7b352733b00a 329 if (RxIrq == irq)
mbed_official 64:7b352733b00a 330 uart_data[obj->index].rx_irq_set_api = enable;
mbed_official 64:7b352733b00a 331 serial_irq_set_internal(obj, irq, enable);
mbed_official 64:7b352733b00a 332 }
mbed_official 64:7b352733b00a 333
mbed_official 64:7b352733b00a 334 static void serial_flow_irq_set(serial_t *obj, uint32_t enable) {
mbed_official 64:7b352733b00a 335 uart_data[obj->index].rx_irq_set_flow = enable;
mbed_official 64:7b352733b00a 336 serial_irq_set_internal(obj, RxIrq, enable);
mbed_official 64:7b352733b00a 337 }
mbed_official 64:7b352733b00a 338
bogdanm 13:0645d8841f51 339 /******************************************************************************
bogdanm 13:0645d8841f51 340 * READ/WRITE
bogdanm 13:0645d8841f51 341 ******************************************************************************/
bogdanm 13:0645d8841f51 342 int serial_getc(serial_t *obj) {
bogdanm 13:0645d8841f51 343 while (!serial_readable(obj));
mbed_official 64:7b352733b00a 344 int data = obj->uart->RBR;
mbed_official 64:7b352733b00a 345 if (NC != uart_data[obj->index].sw_rts.pin) {
mbed_official 64:7b352733b00a 346 gpio_write(&uart_data[obj->index].sw_rts, 0);
mbed_official 64:7b352733b00a 347 obj->uart->IER |= 1 << RxIrq;
mbed_official 64:7b352733b00a 348 }
mbed_official 64:7b352733b00a 349 return data;
bogdanm 13:0645d8841f51 350 }
bogdanm 13:0645d8841f51 351
bogdanm 13:0645d8841f51 352 void serial_putc(serial_t *obj, int c) {
bogdanm 13:0645d8841f51 353 while (!serial_writable(obj));
bogdanm 13:0645d8841f51 354 obj->uart->THR = c;
mbed_official 122:6790158fd562 355 uart_data[obj->index].count++;
bogdanm 13:0645d8841f51 356 }
bogdanm 13:0645d8841f51 357
bogdanm 13:0645d8841f51 358 int serial_readable(serial_t *obj) {
bogdanm 13:0645d8841f51 359 return obj->uart->LSR & 0x01;
bogdanm 13:0645d8841f51 360 }
bogdanm 13:0645d8841f51 361
bogdanm 13:0645d8841f51 362 int serial_writable(serial_t *obj) {
mbed_official 122:6790158fd562 363 int isWritable = 1;
mbed_official 64:7b352733b00a 364 if (NC != uart_data[obj->index].sw_cts.pin)
mbed_official 122:6790158fd562 365 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 366 else {
mbed_official 122:6790158fd562 367 if (obj->uart->LSR & 0x20)
mbed_official 122:6790158fd562 368 uart_data[obj->index].count = 0;
mbed_official 122:6790158fd562 369 else if (uart_data[obj->index].count >= 16)
mbed_official 122:6790158fd562 370 isWritable = 0;
mbed_official 122:6790158fd562 371 }
mbed_official 122:6790158fd562 372 return isWritable;
bogdanm 13:0645d8841f51 373 }
bogdanm 13:0645d8841f51 374
bogdanm 13:0645d8841f51 375 void serial_clear(serial_t *obj) {
bogdanm 20:4263a77256ae 376 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
bogdanm 20:4263a77256ae 377 | 1 << 1 // rx FIFO reset
bogdanm 13:0645d8841f51 378 | 1 << 2 // tx FIFO reset
bogdanm 13:0645d8841f51 379 | 0 << 6; // interrupt depth
bogdanm 13:0645d8841f51 380 }
bogdanm 13:0645d8841f51 381
bogdanm 13:0645d8841f51 382 void serial_pinout_tx(PinName tx) {
bogdanm 13:0645d8841f51 383 pinmap_pinout(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 384 }
bogdanm 13:0645d8841f51 385
bogdanm 13:0645d8841f51 386 void serial_break_set(serial_t *obj) {
bogdanm 13:0645d8841f51 387 obj->uart->LCR |= (1 << 6);
bogdanm 13:0645d8841f51 388 }
bogdanm 13:0645d8841f51 389
bogdanm 13:0645d8841f51 390 void serial_break_clear(serial_t *obj) {
bogdanm 13:0645d8841f51 391 obj->uart->LCR &= ~(1 << 6);
bogdanm 13:0645d8841f51 392 }
bogdanm 13:0645d8841f51 393
mbed_official 64:7b352733b00a 394 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) {
mbed_official 64:7b352733b00a 395 // Only UART1 has hardware flow control on LPC176x
mbed_official 64:7b352733b00a 396 LPC_UART1_TypeDef *uart1 = (uint32_t)obj->uart == (uint32_t)LPC_UART1 ? LPC_UART1 : NULL;
mbed_official 64:7b352733b00a 397 int index = obj->index;
mbed_official 64:7b352733b00a 398
mbed_official 64:7b352733b00a 399 // First, disable flow control completely
mbed_official 64:7b352733b00a 400 if (uart1)
mbed_official 64:7b352733b00a 401 uart1->MCR = uart1->MCR & ~UART_MCR_FLOWCTRL_MASK;
mbed_official 64:7b352733b00a 402 uart_data[index].sw_rts.pin = uart_data[index].sw_cts.pin = NC;
mbed_official 64:7b352733b00a 403 serial_flow_irq_set(obj, 0);
mbed_official 64:7b352733b00a 404 if (FlowControlNone == type)
mbed_official 64:7b352733b00a 405 return;
mbed_official 64:7b352733b00a 406 // Check type(s) of flow control to use
mbed_official 64:7b352733b00a 407 UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 408 UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 409 if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != txflow)) {
mbed_official 64:7b352733b00a 410 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 411 if ((UART_1 == uart_cts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 412 // Enable auto-CTS mode
mbed_official 64:7b352733b00a 413 uart1->MCR |= UART_MCR_CTSEN_MASK;
mbed_official 64:7b352733b00a 414 pinmap_pinout(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 415 } else {
mbed_official 64:7b352733b00a 416 // Can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 417 gpio_init_in(&uart_data[index].sw_cts, txflow);
mbed_official 64:7b352733b00a 418 }
mbed_official 64:7b352733b00a 419 }
mbed_official 64:7b352733b00a 420 if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != rxflow)) {
mbed_official 64:7b352733b00a 421 // Enable FIFOs, trigger level of 1 char on RX FIFO
mbed_official 64:7b352733b00a 422 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
mbed_official 64:7b352733b00a 423 | 1 << 1 // Rx Fifo Reset
mbed_official 64:7b352733b00a 424 | 1 << 2 // Tx Fifo Reset
mbed_official 64:7b352733b00a 425 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
mbed_official 64:7b352733b00a 426 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 427 if ((UART_1 == uart_rts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 428 // Enable auto-RTS mode
mbed_official 64:7b352733b00a 429 uart1->MCR |= UART_MCR_RTSEN_MASK;
mbed_official 64:7b352733b00a 430 pinmap_pinout(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 431 } else { // can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 432 gpio_init_out_ex(&uart_data[index].sw_rts, rxflow, 0);
mbed_official 64:7b352733b00a 433 // Enable RX interrupt
mbed_official 64:7b352733b00a 434 serial_flow_irq_set(obj, 1);
mbed_official 64:7b352733b00a 435 }
mbed_official 64:7b352733b00a 436 }
mbed_official 64:7b352733b00a 437 }
mbed_official 64:7b352733b00a 438