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:
Mon May 19 18:30:07 2014 +0100
Revision:
199:aeeefa19f7de
Parent:
140:ca60b7a31055
Child:
227:7bd0639b8911
Synchronized with git revision e686ab92240f88ab3e42f7421cea75c56a49e1a6

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

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