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 Mar 10 11:30:07 2014 +0000
Revision:
113:65a335a675de
Parent:
109:bc5f94f2a67f
Child:
122:6790158fd562
Synchronized with git revision 423ddcb86e83e2e0d599ca7106d436eb3c47e6dd

Full URL: https://github.com/mbedmicro/mbed/commit/423ddcb86e83e2e0d599ca7106d436eb3c47e6dd/

proposed change of gpio_api (new update pull request)

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>
bogdanm 13:0645d8841f51 19
bogdanm 13:0645d8841f51 20 #include "serial_api.h"
bogdanm 13:0645d8841f51 21 #include "cmsis.h"
bogdanm 13:0645d8841f51 22 #include "pinmap.h"
bogdanm 13:0645d8841f51 23 #include "error.h"
mbed_official 64:7b352733b00a 24 #include "gpio_api.h"
bogdanm 13:0645d8841f51 25
bogdanm 13:0645d8841f51 26 /******************************************************************************
bogdanm 13:0645d8841f51 27 * INITIALIZATION
bogdanm 13:0645d8841f51 28 ******************************************************************************/
bogdanm 13:0645d8841f51 29 #define UART_NUM 4
bogdanm 13:0645d8841f51 30
bogdanm 13:0645d8841f51 31 static const PinMap PinMap_UART_TX[] = {
bogdanm 13:0645d8841f51 32 {P0_0, UART_3, 2},
bogdanm 13:0645d8841f51 33 {P0_2, UART_0, 1},
bogdanm 13:0645d8841f51 34 {P0_10, UART_2, 1},
bogdanm 13:0645d8841f51 35 {P0_15, UART_1, 1},
bogdanm 13:0645d8841f51 36 {P0_25, UART_3, 3},
bogdanm 13:0645d8841f51 37 {P2_0 , UART_1, 2},
bogdanm 13:0645d8841f51 38 {P2_8 , UART_2, 2},
bogdanm 13:0645d8841f51 39 {P4_28, UART_3, 3},
bogdanm 13:0645d8841f51 40 {NC , NC , 0}
bogdanm 13:0645d8841f51 41 };
bogdanm 13:0645d8841f51 42
bogdanm 13:0645d8841f51 43 static const PinMap PinMap_UART_RX[] = {
bogdanm 13:0645d8841f51 44 {P0_1 , UART_3, 2},
bogdanm 13:0645d8841f51 45 {P0_3 , UART_0, 1},
bogdanm 13:0645d8841f51 46 {P0_11, UART_2, 1},
bogdanm 13:0645d8841f51 47 {P0_16, UART_1, 1},
bogdanm 13:0645d8841f51 48 {P0_26, UART_3, 3},
bogdanm 13:0645d8841f51 49 {P2_1 , UART_1, 2},
bogdanm 13:0645d8841f51 50 {P2_9 , UART_2, 2},
bogdanm 13:0645d8841f51 51 {P4_29, UART_3, 3},
bogdanm 13:0645d8841f51 52 {NC , NC , 0}
bogdanm 13:0645d8841f51 53 };
bogdanm 13:0645d8841f51 54
mbed_official 64:7b352733b00a 55 static const PinMap PinMap_UART_RTS[] = {
mbed_official 64:7b352733b00a 56 {P0_22, UART_1, 1},
mbed_official 64:7b352733b00a 57 {P2_7, UART_1, 2},
mbed_official 64:7b352733b00a 58 {NC, NC, 0}
mbed_official 64:7b352733b00a 59 };
mbed_official 64:7b352733b00a 60
mbed_official 64:7b352733b00a 61 static const PinMap PinMap_UART_CTS[] = {
mbed_official 64:7b352733b00a 62 {P0_17, UART_1, 1},
mbed_official 64:7b352733b00a 63 {P2_2, UART_1, 2},
mbed_official 64:7b352733b00a 64 {NC, NC, 0}
mbed_official 64:7b352733b00a 65 };
mbed_official 64:7b352733b00a 66
mbed_official 64:7b352733b00a 67 #define UART_MCR_RTSEN_MASK (1 << 6)
mbed_official 64:7b352733b00a 68 #define UART_MCR_CTSEN_MASK (1 << 7)
mbed_official 64:7b352733b00a 69 #define UART_MCR_FLOWCTRL_MASK (UART_MCR_RTSEN_MASK | UART_MCR_CTSEN_MASK)
mbed_official 64:7b352733b00a 70
bogdanm 13:0645d8841f51 71 static uart_irq_handler irq_handler;
bogdanm 13:0645d8841f51 72
bogdanm 13:0645d8841f51 73 int stdio_uart_inited = 0;
bogdanm 13:0645d8841f51 74 serial_t stdio_uart;
bogdanm 13:0645d8841f51 75
mbed_official 64:7b352733b00a 76 struct serial_global_data_s {
mbed_official 64:7b352733b00a 77 uint32_t serial_irq_id;
mbed_official 64:7b352733b00a 78 gpio_t sw_rts, sw_cts;
mbed_official 113:65a335a675de 79 uint8_t rx_irq_set_flow, rx_irq_set_api;
mbed_official 64:7b352733b00a 80 };
mbed_official 64:7b352733b00a 81
mbed_official 64:7b352733b00a 82 static struct serial_global_data_s uart_data[UART_NUM];
mbed_official 64:7b352733b00a 83
bogdanm 13:0645d8841f51 84 void serial_init(serial_t *obj, PinName tx, PinName rx) {
bogdanm 13:0645d8841f51 85 int is_stdio_uart = 0;
bogdanm 13:0645d8841f51 86
bogdanm 13:0645d8841f51 87 // determine the UART to use
bogdanm 13:0645d8841f51 88 UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 89 UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
bogdanm 13:0645d8841f51 90 UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
bogdanm 13:0645d8841f51 91 if ((int)uart == NC) {
bogdanm 13:0645d8841f51 92 error("Serial pinout mapping failed");
bogdanm 13:0645d8841f51 93 }
bogdanm 13:0645d8841f51 94
bogdanm 13:0645d8841f51 95 obj->uart = (LPC_UART_TypeDef *)uart;
bogdanm 13:0645d8841f51 96 // enable power
bogdanm 13:0645d8841f51 97 switch (uart) {
bogdanm 13:0645d8841f51 98 case UART_0: LPC_SC->PCONP |= 1 << 3; break;
bogdanm 13:0645d8841f51 99 case UART_1: LPC_SC->PCONP |= 1 << 4; break;
bogdanm 13:0645d8841f51 100 case UART_2: LPC_SC->PCONP |= 1 << 24; break;
bogdanm 13:0645d8841f51 101 case UART_3: LPC_SC->PCONP |= 1 << 25; break;
bogdanm 13:0645d8841f51 102 }
bogdanm 13:0645d8841f51 103
bogdanm 13:0645d8841f51 104 // enable fifos and default rx trigger level
bogdanm 13:0645d8841f51 105 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
bogdanm 13:0645d8841f51 106 | 0 << 1 // Rx Fifo Reset
bogdanm 13:0645d8841f51 107 | 0 << 2 // Tx Fifo Reset
bogdanm 13:0645d8841f51 108 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
bogdanm 13:0645d8841f51 109
bogdanm 13:0645d8841f51 110 // disable irqs
bogdanm 13:0645d8841f51 111 obj->uart->IER = 0 << 0 // Rx Data available irq enable
bogdanm 13:0645d8841f51 112 | 0 << 1 // Tx Fifo empty irq enable
bogdanm 13:0645d8841f51 113 | 0 << 2; // Rx Line Status irq enable
bogdanm 13:0645d8841f51 114
bogdanm 13:0645d8841f51 115 // set default baud rate and format
bogdanm 13:0645d8841f51 116 serial_baud (obj, 9600);
bogdanm 13:0645d8841f51 117 serial_format(obj, 8, ParityNone, 1);
bogdanm 13:0645d8841f51 118
bogdanm 13:0645d8841f51 119 // pinout the chosen uart
bogdanm 13:0645d8841f51 120 pinmap_pinout(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 121 pinmap_pinout(rx, PinMap_UART_RX);
bogdanm 13:0645d8841f51 122
bogdanm 13:0645d8841f51 123 // set rx/tx pins in PullUp mode
bogdanm 13:0645d8841f51 124 pin_mode(tx, PullUp);
bogdanm 13:0645d8841f51 125 pin_mode(rx, PullUp);
bogdanm 13:0645d8841f51 126
bogdanm 13:0645d8841f51 127 switch (uart) {
bogdanm 13:0645d8841f51 128 case UART_0: obj->index = 0; break;
bogdanm 13:0645d8841f51 129 case UART_1: obj->index = 1; break;
bogdanm 13:0645d8841f51 130 case UART_2: obj->index = 2; break;
bogdanm 13:0645d8841f51 131 case UART_3: obj->index = 3; break;
bogdanm 13:0645d8841f51 132 }
mbed_official 64:7b352733b00a 133 uart_data[obj->index].sw_rts.pin = NC;
mbed_official 64:7b352733b00a 134 uart_data[obj->index].sw_cts.pin = NC;
mbed_official 64:7b352733b00a 135 serial_set_flow_control(obj, FlowControlNone, NC, NC);
bogdanm 13:0645d8841f51 136
bogdanm 13:0645d8841f51 137 is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
bogdanm 13:0645d8841f51 138
bogdanm 13:0645d8841f51 139 if (is_stdio_uart) {
bogdanm 13:0645d8841f51 140 stdio_uart_inited = 1;
bogdanm 13:0645d8841f51 141 memcpy(&stdio_uart, obj, sizeof(serial_t));
bogdanm 13:0645d8841f51 142 }
bogdanm 13:0645d8841f51 143 }
bogdanm 13:0645d8841f51 144
bogdanm 13:0645d8841f51 145 void serial_free(serial_t *obj) {
mbed_official 64:7b352733b00a 146 uart_data[obj->index].serial_irq_id = 0;
bogdanm 13:0645d8841f51 147 }
bogdanm 13:0645d8841f51 148
bogdanm 13:0645d8841f51 149 // serial_baud
bogdanm 13:0645d8841f51 150 // set the baud rate, taking in to account the current SystemFrequency
bogdanm 13:0645d8841f51 151 void serial_baud(serial_t *obj, int baudrate) {
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;
bogdanm 13:0645d8841f51 167 default: error("serial_baud"); 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) {
bogdanm 13:0645d8841f51 247 // 0: 1 stop bits, 1: 2 stop bits
bogdanm 13:0645d8841f51 248 if (stop_bits != 1 && stop_bits != 2) {
bogdanm 13:0645d8841f51 249 error("Invalid stop bits specified");
bogdanm 13:0645d8841f51 250 }
bogdanm 13:0645d8841f51 251 stop_bits -= 1;
bogdanm 13:0645d8841f51 252
bogdanm 13:0645d8841f51 253 // 0: 5 data bits ... 3: 8 data bits
bogdanm 13:0645d8841f51 254 if (data_bits < 5 || data_bits > 8) {
bogdanm 13:0645d8841f51 255 error("Invalid number of bits (%d) in serial format, should be 5..8", data_bits);
bogdanm 13:0645d8841f51 256 }
bogdanm 13:0645d8841f51 257 data_bits -= 5;
bogdanm 13:0645d8841f51 258
bogdanm 13:0645d8841f51 259 int parity_enable, parity_select;
bogdanm 13:0645d8841f51 260 switch (parity) {
bogdanm 13:0645d8841f51 261 case ParityNone: parity_enable = 0; parity_select = 0; break;
bogdanm 13:0645d8841f51 262 case ParityOdd : parity_enable = 1; parity_select = 0; break;
bogdanm 13:0645d8841f51 263 case ParityEven: parity_enable = 1; parity_select = 1; break;
bogdanm 13:0645d8841f51 264 case ParityForced1: parity_enable = 1; parity_select = 2; break;
bogdanm 13:0645d8841f51 265 case ParityForced0: parity_enable = 1; parity_select = 3; break;
bogdanm 13:0645d8841f51 266 default:
bogdanm 13:0645d8841f51 267 error("Invalid serial parity setting");
bogdanm 13:0645d8841f51 268 return;
bogdanm 13:0645d8841f51 269 }
bogdanm 13:0645d8841f51 270
bogdanm 13:0645d8841f51 271 obj->uart->LCR = data_bits << 0
bogdanm 13:0645d8841f51 272 | stop_bits << 2
bogdanm 13:0645d8841f51 273 | parity_enable << 3
bogdanm 13:0645d8841f51 274 | parity_select << 4;
bogdanm 13:0645d8841f51 275 }
bogdanm 13:0645d8841f51 276
bogdanm 13:0645d8841f51 277 /******************************************************************************
bogdanm 13:0645d8841f51 278 * INTERRUPTS HANDLING
bogdanm 13:0645d8841f51 279 ******************************************************************************/
mbed_official 64:7b352733b00a 280 static inline void uart_irq(uint32_t iir, uint32_t index, LPC_UART_TypeDef *puart) {
bogdanm 13:0645d8841f51 281 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
bogdanm 13:0645d8841f51 282 SerialIrq irq_type;
bogdanm 13:0645d8841f51 283 switch (iir) {
bogdanm 13:0645d8841f51 284 case 1: irq_type = TxIrq; break;
bogdanm 13:0645d8841f51 285 case 2: irq_type = RxIrq; break;
bogdanm 13:0645d8841f51 286 default: return;
bogdanm 13:0645d8841f51 287 }
mbed_official 64:7b352733b00a 288 if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) {
mbed_official 64:7b352733b00a 289 gpio_write(&uart_data[index].sw_rts, 1);
mbed_official 64:7b352733b00a 290 // Disable interrupt if it wasn't enabled by other part of the application
mbed_official 64:7b352733b00a 291 if (!uart_data[index].rx_irq_set_api)
mbed_official 64:7b352733b00a 292 puart->IER &= ~(1 << RxIrq);
mbed_official 64:7b352733b00a 293 }
mbed_official 64:7b352733b00a 294 if (uart_data[index].serial_irq_id != 0)
mbed_official 64:7b352733b00a 295 if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api))
mbed_official 64:7b352733b00a 296 irq_handler(uart_data[index].serial_irq_id, irq_type);
bogdanm 13:0645d8841f51 297 }
bogdanm 13:0645d8841f51 298
mbed_official 64:7b352733b00a 299 void uart0_irq() {uart_irq((LPC_UART0->IIR >> 1) & 0x7, 0, (LPC_UART_TypeDef*)LPC_UART0);}
mbed_official 64:7b352733b00a 300 void uart1_irq() {uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1, (LPC_UART_TypeDef*)LPC_UART1);}
mbed_official 64:7b352733b00a 301 void uart2_irq() {uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2, (LPC_UART_TypeDef*)LPC_UART2);}
mbed_official 64:7b352733b00a 302 void uart3_irq() {uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3, (LPC_UART_TypeDef*)LPC_UART3);}
bogdanm 13:0645d8841f51 303
bogdanm 13:0645d8841f51 304 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
bogdanm 13:0645d8841f51 305 irq_handler = handler;
mbed_official 64:7b352733b00a 306 uart_data[obj->index].serial_irq_id = id;
bogdanm 13:0645d8841f51 307 }
bogdanm 13:0645d8841f51 308
mbed_official 64:7b352733b00a 309 static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) {
bogdanm 13:0645d8841f51 310 IRQn_Type irq_n = (IRQn_Type)0;
bogdanm 13:0645d8841f51 311 uint32_t vector = 0;
bogdanm 13:0645d8841f51 312 switch ((int)obj->uart) {
bogdanm 13:0645d8841f51 313 case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
bogdanm 13:0645d8841f51 314 case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
bogdanm 13:0645d8841f51 315 case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
bogdanm 13:0645d8841f51 316 case UART_3: irq_n=UART3_IRQn; vector = (uint32_t)&uart3_irq; break;
bogdanm 13:0645d8841f51 317 }
bogdanm 13:0645d8841f51 318
bogdanm 13:0645d8841f51 319 if (enable) {
bogdanm 13:0645d8841f51 320 obj->uart->IER |= 1 << irq;
bogdanm 13:0645d8841f51 321 NVIC_SetVector(irq_n, vector);
bogdanm 13:0645d8841f51 322 NVIC_EnableIRQ(irq_n);
mbed_official 64:7b352733b00a 323 } else if ((TxIrq == irq) || (uart_data[obj->index].rx_irq_set_api + uart_data[obj->index].rx_irq_set_flow == 0)) { // disable
bogdanm 13:0645d8841f51 324 int all_disabled = 0;
bogdanm 13:0645d8841f51 325 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
bogdanm 13:0645d8841f51 326 obj->uart->IER &= ~(1 << irq);
bogdanm 13:0645d8841f51 327 all_disabled = (obj->uart->IER & (1 << other_irq)) == 0;
bogdanm 13:0645d8841f51 328 if (all_disabled)
bogdanm 13:0645d8841f51 329 NVIC_DisableIRQ(irq_n);
bogdanm 13:0645d8841f51 330 }
bogdanm 13:0645d8841f51 331 }
bogdanm 13:0645d8841f51 332
mbed_official 64:7b352733b00a 333 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
mbed_official 64:7b352733b00a 334 if (RxIrq == irq)
mbed_official 64:7b352733b00a 335 uart_data[obj->index].rx_irq_set_api = enable;
mbed_official 64:7b352733b00a 336 serial_irq_set_internal(obj, irq, enable);
mbed_official 64:7b352733b00a 337 }
mbed_official 64:7b352733b00a 338
mbed_official 64:7b352733b00a 339 static void serial_flow_irq_set(serial_t *obj, uint32_t enable) {
mbed_official 64:7b352733b00a 340 uart_data[obj->index].rx_irq_set_flow = enable;
mbed_official 64:7b352733b00a 341 serial_irq_set_internal(obj, RxIrq, enable);
mbed_official 64:7b352733b00a 342 }
mbed_official 64:7b352733b00a 343
bogdanm 13:0645d8841f51 344 /******************************************************************************
bogdanm 13:0645d8841f51 345 * READ/WRITE
bogdanm 13:0645d8841f51 346 ******************************************************************************/
bogdanm 13:0645d8841f51 347 int serial_getc(serial_t *obj) {
bogdanm 13:0645d8841f51 348 while (!serial_readable(obj));
mbed_official 64:7b352733b00a 349 int data = obj->uart->RBR;
mbed_official 64:7b352733b00a 350 if (NC != uart_data[obj->index].sw_rts.pin) {
mbed_official 64:7b352733b00a 351 gpio_write(&uart_data[obj->index].sw_rts, 0);
mbed_official 64:7b352733b00a 352 obj->uart->IER |= 1 << RxIrq;
mbed_official 64:7b352733b00a 353 }
mbed_official 64:7b352733b00a 354 return data;
bogdanm 13:0645d8841f51 355 }
bogdanm 13:0645d8841f51 356
bogdanm 13:0645d8841f51 357 void serial_putc(serial_t *obj, int c) {
bogdanm 13:0645d8841f51 358 while (!serial_writable(obj));
bogdanm 13:0645d8841f51 359 obj->uart->THR = c;
bogdanm 13:0645d8841f51 360 }
bogdanm 13:0645d8841f51 361
bogdanm 13:0645d8841f51 362 int serial_readable(serial_t *obj) {
bogdanm 13:0645d8841f51 363 return obj->uart->LSR & 0x01;
bogdanm 13:0645d8841f51 364 }
bogdanm 13:0645d8841f51 365
bogdanm 13:0645d8841f51 366 int serial_writable(serial_t *obj) {
mbed_official 64:7b352733b00a 367 if (NC != uart_data[obj->index].sw_cts.pin)
mbed_official 113:65a335a675de 368 return (gpio_read(&uart_data[obj->index].sw_cts) == 0) && (obj->uart->LSR & 0x40); //If flow control: writable if CTS low + UART done
mbed_official 113:65a335a675de 369 else
mbed_official 113:65a335a675de 370 return obj->uart->LSR & 0x20; //No flow control: writable if space in holding register
bogdanm 13:0645d8841f51 371 }
bogdanm 13:0645d8841f51 372
bogdanm 13:0645d8841f51 373 void serial_clear(serial_t *obj) {
bogdanm 20:4263a77256ae 374 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
bogdanm 20:4263a77256ae 375 | 1 << 1 // rx FIFO reset
bogdanm 13:0645d8841f51 376 | 1 << 2 // tx FIFO reset
bogdanm 13:0645d8841f51 377 | 0 << 6; // interrupt depth
bogdanm 13:0645d8841f51 378 }
bogdanm 13:0645d8841f51 379
bogdanm 13:0645d8841f51 380 void serial_pinout_tx(PinName tx) {
bogdanm 13:0645d8841f51 381 pinmap_pinout(tx, PinMap_UART_TX);
bogdanm 13:0645d8841f51 382 }
bogdanm 13:0645d8841f51 383
bogdanm 13:0645d8841f51 384 void serial_break_set(serial_t *obj) {
bogdanm 13:0645d8841f51 385 obj->uart->LCR |= (1 << 6);
bogdanm 13:0645d8841f51 386 }
bogdanm 13:0645d8841f51 387
bogdanm 13:0645d8841f51 388 void serial_break_clear(serial_t *obj) {
bogdanm 13:0645d8841f51 389 obj->uart->LCR &= ~(1 << 6);
bogdanm 13:0645d8841f51 390 }
bogdanm 13:0645d8841f51 391
mbed_official 64:7b352733b00a 392 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) {
mbed_official 64:7b352733b00a 393 // Only UART1 has hardware flow control on LPC176x
mbed_official 64:7b352733b00a 394 LPC_UART1_TypeDef *uart1 = (uint32_t)obj->uart == (uint32_t)LPC_UART1 ? LPC_UART1 : NULL;
mbed_official 64:7b352733b00a 395 int index = obj->index;
mbed_official 64:7b352733b00a 396
mbed_official 64:7b352733b00a 397 // First, disable flow control completely
mbed_official 64:7b352733b00a 398 if (uart1)
mbed_official 64:7b352733b00a 399 uart1->MCR = uart1->MCR & ~UART_MCR_FLOWCTRL_MASK;
mbed_official 64:7b352733b00a 400 uart_data[index].sw_rts.pin = uart_data[index].sw_cts.pin = NC;
mbed_official 64:7b352733b00a 401 serial_flow_irq_set(obj, 0);
mbed_official 64:7b352733b00a 402 if (FlowControlNone == type)
mbed_official 64:7b352733b00a 403 return;
mbed_official 64:7b352733b00a 404 // Check type(s) of flow control to use
mbed_official 64:7b352733b00a 405 UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 406 UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 407 if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != txflow)) {
mbed_official 64:7b352733b00a 408 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 409 if ((UART_1 == uart_cts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 410 // Enable auto-CTS mode
mbed_official 64:7b352733b00a 411 uart1->MCR |= UART_MCR_CTSEN_MASK;
mbed_official 64:7b352733b00a 412 pinmap_pinout(txflow, PinMap_UART_CTS);
mbed_official 64:7b352733b00a 413 } else {
mbed_official 64:7b352733b00a 414 // Can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 415 gpio_init_in(&uart_data[index].sw_cts, txflow);
mbed_official 64:7b352733b00a 416 }
mbed_official 64:7b352733b00a 417 }
mbed_official 64:7b352733b00a 418 if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != rxflow)) {
mbed_official 64:7b352733b00a 419 // Enable FIFOs, trigger level of 1 char on RX FIFO
mbed_official 64:7b352733b00a 420 obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled
mbed_official 64:7b352733b00a 421 | 1 << 1 // Rx Fifo Reset
mbed_official 64:7b352733b00a 422 | 1 << 2 // Tx Fifo Reset
mbed_official 64:7b352733b00a 423 | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars
mbed_official 64:7b352733b00a 424 // Can this be enabled in hardware?
mbed_official 64:7b352733b00a 425 if ((UART_1 == uart_rts) && (NULL != uart1)) {
mbed_official 64:7b352733b00a 426 // Enable auto-RTS mode
mbed_official 64:7b352733b00a 427 uart1->MCR |= UART_MCR_RTSEN_MASK;
mbed_official 64:7b352733b00a 428 pinmap_pinout(rxflow, PinMap_UART_RTS);
mbed_official 64:7b352733b00a 429 } else { // can't enable in hardware, use software emulation
mbed_official 113:65a335a675de 430 gpio_init_out_ex(&uart_data[index].sw_rts, rxflow, 0);
mbed_official 64:7b352733b00a 431 // Enable RX interrupt
mbed_official 64:7b352733b00a 432 serial_flow_irq_set(obj, 1);
mbed_official 64:7b352733b00a 433 }
mbed_official 64:7b352733b00a 434 }
mbed_official 64:7b352733b00a 435 }
mbed_official 64:7b352733b00a 436