Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-src by
targets/hal/TARGET_NXP/TARGET_LPC11U6X/serial_api.c@220:aa774fb95d17, 2014-06-03 (annotated)
- Committer:
- mbed_official
- Date:
- Tue Jun 03 10:30:56 2014 +0100
- Revision:
- 220:aa774fb95d17
- Parent:
- 186:2e805bf06ee4
- Child:
- 227:7bd0639b8911
Synchronized with git revision 850e3c4d3d402724860d0adae966ac05c9a8ed16
Full URL: https://github.com/mbedmicro/mbed/commit/850e3c4d3d402724860d0adae966ac05c9a8ed16/
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbed_official | 174:8bb9f3a33240 | 1 | /* mbed Microcontroller Library |
mbed_official | 174:8bb9f3a33240 | 2 | * Copyright (c) 2006-2013 ARM Limited |
mbed_official | 174:8bb9f3a33240 | 3 | * |
mbed_official | 174:8bb9f3a33240 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
mbed_official | 174:8bb9f3a33240 | 5 | * you may not use this file except in compliance with the License. |
mbed_official | 174:8bb9f3a33240 | 6 | * You may obtain a copy of the License at |
mbed_official | 174:8bb9f3a33240 | 7 | * |
mbed_official | 174:8bb9f3a33240 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
mbed_official | 174:8bb9f3a33240 | 9 | * |
mbed_official | 174:8bb9f3a33240 | 10 | * Unless required by applicable law or agreed to in writing, software |
mbed_official | 174:8bb9f3a33240 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
mbed_official | 174:8bb9f3a33240 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
mbed_official | 174:8bb9f3a33240 | 13 | * See the License for the specific language governing permissions and |
mbed_official | 174:8bb9f3a33240 | 14 | * limitations under the License. |
mbed_official | 174:8bb9f3a33240 | 15 | */ |
mbed_official | 220:aa774fb95d17 | 16 | |
mbed_official | 174:8bb9f3a33240 | 17 | // math.h required for floating point operations for baud rate calculation |
mbed_official | 174:8bb9f3a33240 | 18 | #include <math.h> |
mbed_official | 174:8bb9f3a33240 | 19 | #include <string.h> |
mbed_official | 174:8bb9f3a33240 | 20 | #include <stdlib.h> |
mbed_official | 174:8bb9f3a33240 | 21 | |
mbed_official | 174:8bb9f3a33240 | 22 | #include "serial_api.h" |
mbed_official | 174:8bb9f3a33240 | 23 | #include "cmsis.h" |
mbed_official | 174:8bb9f3a33240 | 24 | #include "pinmap.h" |
mbed_official | 174:8bb9f3a33240 | 25 | #include "error.h" |
mbed_official | 174:8bb9f3a33240 | 26 | |
mbed_official | 174:8bb9f3a33240 | 27 | #if DEVICE_SERIAL |
mbed_official | 220:aa774fb95d17 | 28 | |
mbed_official | 174:8bb9f3a33240 | 29 | /****************************************************************************** |
mbed_official | 174:8bb9f3a33240 | 30 | * INITIALIZATION |
mbed_official | 174:8bb9f3a33240 | 31 | ******************************************************************************/ |
mbed_official | 174:8bb9f3a33240 | 32 | |
mbed_official | 220:aa774fb95d17 | 33 | #define UART_NUM 5 |
mbed_official | 220:aa774fb95d17 | 34 | |
mbed_official | 220:aa774fb95d17 | 35 | // CFG |
mbed_official | 220:aa774fb95d17 | 36 | #define UART_EN (0x01<<0) |
mbed_official | 220:aa774fb95d17 | 37 | |
mbed_official | 220:aa774fb95d17 | 38 | // CTL |
mbed_official | 220:aa774fb95d17 | 39 | #define TXBRKEN (0x01<<1) |
mbed_official | 220:aa774fb95d17 | 40 | |
mbed_official | 220:aa774fb95d17 | 41 | // STAT |
mbed_official | 220:aa774fb95d17 | 42 | #define RXRDY (0x01<<0) |
mbed_official | 220:aa774fb95d17 | 43 | #define TXRDY (0x01<<2) |
mbed_official | 220:aa774fb95d17 | 44 | #define DELTACTS (0x01<<5) |
mbed_official | 220:aa774fb95d17 | 45 | #define RXBRK (0x01<<10) |
mbed_official | 220:aa774fb95d17 | 46 | #define DELTARXBRK (0x01<<11) |
mbed_official | 174:8bb9f3a33240 | 47 | |
mbed_official | 174:8bb9f3a33240 | 48 | static const PinMap PinMap_UART_TX[] = { |
mbed_official | 174:8bb9f3a33240 | 49 | {P0_19, UART_0, 1}, |
mbed_official | 174:8bb9f3a33240 | 50 | {P1_18, UART_0, 2}, |
mbed_official | 174:8bb9f3a33240 | 51 | {P1_27, UART_0, 2}, |
mbed_official | 220:aa774fb95d17 | 52 | {P1_8 , UART_1, 2}, |
mbed_official | 220:aa774fb95d17 | 53 | {P1_0 , UART_2, 3}, |
mbed_official | 220:aa774fb95d17 | 54 | {P1_23, UART_2, 3}, |
mbed_official | 220:aa774fb95d17 | 55 | {P2_4 , UART_3, 1}, |
mbed_official | 220:aa774fb95d17 | 56 | {P2_12, UART_4, 1}, |
mbed_official | 174:8bb9f3a33240 | 57 | { NC , NC , 0} |
mbed_official | 174:8bb9f3a33240 | 58 | }; |
mbed_official | 174:8bb9f3a33240 | 59 | |
mbed_official | 174:8bb9f3a33240 | 60 | static const PinMap PinMap_UART_RX[] = { |
mbed_official | 174:8bb9f3a33240 | 61 | {P0_18, UART_0, 1}, |
mbed_official | 174:8bb9f3a33240 | 62 | {P1_17, UART_0, 2}, |
mbed_official | 174:8bb9f3a33240 | 63 | {P1_26, UART_0, 2}, |
mbed_official | 220:aa774fb95d17 | 64 | {P1_2 , UART_1, 3}, |
mbed_official | 220:aa774fb95d17 | 65 | {P0_20, UART_2, 2}, |
mbed_official | 220:aa774fb95d17 | 66 | {P1_6 , UART_2, 2}, |
mbed_official | 220:aa774fb95d17 | 67 | {P2_3 , UART_3, 1}, |
mbed_official | 220:aa774fb95d17 | 68 | {P2_11, UART_4, 1}, |
mbed_official | 174:8bb9f3a33240 | 69 | {NC , NC , 0} |
mbed_official | 174:8bb9f3a33240 | 70 | }; |
mbed_official | 174:8bb9f3a33240 | 71 | |
mbed_official | 174:8bb9f3a33240 | 72 | static uint32_t serial_irq_ids[UART_NUM] = {0}; |
mbed_official | 174:8bb9f3a33240 | 73 | static uart_irq_handler irq_handler; |
mbed_official | 174:8bb9f3a33240 | 74 | |
mbed_official | 174:8bb9f3a33240 | 75 | int stdio_uart_inited = 0; |
mbed_official | 174:8bb9f3a33240 | 76 | serial_t stdio_uart; |
mbed_official | 174:8bb9f3a33240 | 77 | |
mbed_official | 174:8bb9f3a33240 | 78 | void serial_init(serial_t *obj, PinName tx, PinName rx) { |
mbed_official | 174:8bb9f3a33240 | 79 | int is_stdio_uart = 0; |
mbed_official | 174:8bb9f3a33240 | 80 | |
mbed_official | 174:8bb9f3a33240 | 81 | // determine the UART to use |
mbed_official | 174:8bb9f3a33240 | 82 | UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); |
mbed_official | 174:8bb9f3a33240 | 83 | UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); |
mbed_official | 174:8bb9f3a33240 | 84 | UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); |
mbed_official | 174:8bb9f3a33240 | 85 | if ((int)uart == NC) { |
mbed_official | 174:8bb9f3a33240 | 86 | error("Serial pinout mapping failed"); |
mbed_official | 174:8bb9f3a33240 | 87 | } |
mbed_official | 174:8bb9f3a33240 | 88 | |
mbed_official | 220:aa774fb95d17 | 89 | switch (uart) { |
mbed_official | 220:aa774fb95d17 | 90 | case UART_0: |
mbed_official | 220:aa774fb95d17 | 91 | obj->index = 0; |
mbed_official | 220:aa774fb95d17 | 92 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 12); |
mbed_official | 220:aa774fb95d17 | 93 | break; |
mbed_official | 220:aa774fb95d17 | 94 | case UART_1: |
mbed_official | 220:aa774fb95d17 | 95 | obj->index = 1; |
mbed_official | 220:aa774fb95d17 | 96 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 20); |
mbed_official | 220:aa774fb95d17 | 97 | LPC_SYSCON->PRESETCTRL |= (1 << 5); |
mbed_official | 220:aa774fb95d17 | 98 | break; |
mbed_official | 220:aa774fb95d17 | 99 | case UART_2: |
mbed_official | 220:aa774fb95d17 | 100 | obj->index = 2; |
mbed_official | 220:aa774fb95d17 | 101 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 21); |
mbed_official | 220:aa774fb95d17 | 102 | LPC_SYSCON->PRESETCTRL |= (1 << 6); |
mbed_official | 220:aa774fb95d17 | 103 | break; |
mbed_official | 220:aa774fb95d17 | 104 | case UART_3: |
mbed_official | 220:aa774fb95d17 | 105 | obj->index = 3; |
mbed_official | 220:aa774fb95d17 | 106 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 22); |
mbed_official | 220:aa774fb95d17 | 107 | LPC_SYSCON->PRESETCTRL |= (1 << 7); |
mbed_official | 220:aa774fb95d17 | 108 | break; |
mbed_official | 220:aa774fb95d17 | 109 | case UART_4: |
mbed_official | 220:aa774fb95d17 | 110 | obj->index = 4; |
mbed_official | 220:aa774fb95d17 | 111 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 22); |
mbed_official | 220:aa774fb95d17 | 112 | LPC_SYSCON->PRESETCTRL |= (1 << 8); |
mbed_official | 220:aa774fb95d17 | 113 | break; |
mbed_official | 220:aa774fb95d17 | 114 | } |
mbed_official | 174:8bb9f3a33240 | 115 | |
mbed_official | 220:aa774fb95d17 | 116 | if (obj->index == 0) |
mbed_official | 220:aa774fb95d17 | 117 | obj->uart = (LPC_USART0_Type *)uart; |
mbed_official | 220:aa774fb95d17 | 118 | else |
mbed_official | 220:aa774fb95d17 | 119 | obj->mini_uart = (LPC_USART4_Type *)uart; |
mbed_official | 174:8bb9f3a33240 | 120 | |
mbed_official | 220:aa774fb95d17 | 121 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 122 | // enable fifos and default rx trigger level |
mbed_official | 220:aa774fb95d17 | 123 | obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled |
mbed_official | 220:aa774fb95d17 | 124 | | 0 << 1 // Rx Fifo Clear |
mbed_official | 220:aa774fb95d17 | 125 | | 0 << 2 // Tx Fifo Clear |
mbed_official | 220:aa774fb95d17 | 126 | | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars |
mbed_official | 220:aa774fb95d17 | 127 | // disable irqs |
mbed_official | 220:aa774fb95d17 | 128 | obj->uart->IER = 0 << 0 // Rx Data available irq enable |
mbed_official | 220:aa774fb95d17 | 129 | | 0 << 1 // Tx Fifo empty irq enable |
mbed_official | 220:aa774fb95d17 | 130 | | 0 << 2; // Rx Line Status irq enable |
mbed_official | 220:aa774fb95d17 | 131 | } |
mbed_official | 220:aa774fb95d17 | 132 | else { |
mbed_official | 220:aa774fb95d17 | 133 | // Clear all status bits |
mbed_official | 220:aa774fb95d17 | 134 | obj->mini_uart->STAT = (DELTACTS | DELTARXBRK); |
mbed_official | 220:aa774fb95d17 | 135 | // Enable UART |
mbed_official | 220:aa774fb95d17 | 136 | obj->mini_uart->CFG |= UART_EN; |
mbed_official | 220:aa774fb95d17 | 137 | } |
mbed_official | 174:8bb9f3a33240 | 138 | // set default baud rate and format |
mbed_official | 174:8bb9f3a33240 | 139 | serial_baud (obj, 9600); |
mbed_official | 174:8bb9f3a33240 | 140 | serial_format(obj, 8, ParityNone, 1); |
mbed_official | 174:8bb9f3a33240 | 141 | |
mbed_official | 174:8bb9f3a33240 | 142 | // pinout the chosen uart |
mbed_official | 174:8bb9f3a33240 | 143 | pinmap_pinout(tx, PinMap_UART_TX); |
mbed_official | 174:8bb9f3a33240 | 144 | pinmap_pinout(rx, PinMap_UART_RX); |
mbed_official | 174:8bb9f3a33240 | 145 | |
mbed_official | 174:8bb9f3a33240 | 146 | // set rx/tx pins in PullUp mode |
mbed_official | 174:8bb9f3a33240 | 147 | pin_mode(tx, PullUp); |
mbed_official | 174:8bb9f3a33240 | 148 | pin_mode(rx, PullUp); |
mbed_official | 174:8bb9f3a33240 | 149 | |
mbed_official | 174:8bb9f3a33240 | 150 | is_stdio_uart = (uart == STDIO_UART) ? (1) : (0); |
mbed_official | 174:8bb9f3a33240 | 151 | |
mbed_official | 220:aa774fb95d17 | 152 | if (is_stdio_uart && (obj->index == 0)) { |
mbed_official | 174:8bb9f3a33240 | 153 | stdio_uart_inited = 1; |
mbed_official | 174:8bb9f3a33240 | 154 | memcpy(&stdio_uart, obj, sizeof(serial_t)); |
mbed_official | 174:8bb9f3a33240 | 155 | } |
mbed_official | 174:8bb9f3a33240 | 156 | } |
mbed_official | 174:8bb9f3a33240 | 157 | |
mbed_official | 174:8bb9f3a33240 | 158 | void serial_free(serial_t *obj) { |
mbed_official | 174:8bb9f3a33240 | 159 | serial_irq_ids[obj->index] = 0; |
mbed_official | 174:8bb9f3a33240 | 160 | } |
mbed_official | 174:8bb9f3a33240 | 161 | |
mbed_official | 174:8bb9f3a33240 | 162 | // serial_baud |
mbed_official | 174:8bb9f3a33240 | 163 | // set the baud rate, taking in to account the current SystemFrequency |
mbed_official | 174:8bb9f3a33240 | 164 | void serial_baud(serial_t *obj, int baudrate) { |
mbed_official | 220:aa774fb95d17 | 165 | LPC_SYSCON->USART0CLKDIV = 1; |
mbed_official | 220:aa774fb95d17 | 166 | LPC_SYSCON->FRGCLKDIV = 1; |
mbed_official | 220:aa774fb95d17 | 167 | |
mbed_official | 220:aa774fb95d17 | 168 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 169 | uint32_t PCLK = SystemCoreClock; |
mbed_official | 220:aa774fb95d17 | 170 | // First we check to see if the basic divide with no DivAddVal/MulVal |
mbed_official | 220:aa774fb95d17 | 171 | // ratio gives us an integer result. If it does, we set DivAddVal = 0, |
mbed_official | 220:aa774fb95d17 | 172 | // MulVal = 1. Otherwise, we search the valid ratio value range to find |
mbed_official | 220:aa774fb95d17 | 173 | // the closest match. This could be more elegant, using search methods |
mbed_official | 220:aa774fb95d17 | 174 | // and/or lookup tables, but the brute force method is not that much |
mbed_official | 220:aa774fb95d17 | 175 | // slower, and is more maintainable. |
mbed_official | 220:aa774fb95d17 | 176 | uint16_t DL = PCLK / (16 * baudrate); |
mbed_official | 220:aa774fb95d17 | 177 | |
mbed_official | 220:aa774fb95d17 | 178 | uint8_t DivAddVal = 0; |
mbed_official | 220:aa774fb95d17 | 179 | uint8_t MulVal = 1; |
mbed_official | 220:aa774fb95d17 | 180 | int hit = 0; |
mbed_official | 220:aa774fb95d17 | 181 | uint16_t dlv; |
mbed_official | 220:aa774fb95d17 | 182 | uint8_t mv, dav; |
mbed_official | 220:aa774fb95d17 | 183 | if ((PCLK % (16 * baudrate)) != 0) { // Checking for zero remainder |
mbed_official | 220:aa774fb95d17 | 184 | int err_best = baudrate, b; |
mbed_official | 220:aa774fb95d17 | 185 | for (mv = 1; mv < 16 && !hit; mv++) |
mbed_official | 174:8bb9f3a33240 | 186 | { |
mbed_official | 220:aa774fb95d17 | 187 | for (dav = 0; dav < mv; dav++) |
mbed_official | 220:aa774fb95d17 | 188 | { |
mbed_official | 220:aa774fb95d17 | 189 | // baudrate = PCLK / (16 * dlv * (1 + (DivAdd / Mul)) |
mbed_official | 220:aa774fb95d17 | 190 | // solving for dlv, we get dlv = mul * PCLK / (16 * baudrate * (divadd + mul)) |
mbed_official | 220:aa774fb95d17 | 191 | // mul has 4 bits, PCLK has 27 so we have 1 bit headroom which can be used for rounding |
mbed_official | 220:aa774fb95d17 | 192 | // for many values of mul and PCLK we have 2 or more bits of headroom which can be used to improve precision |
mbed_official | 220:aa774fb95d17 | 193 | // note: X / 32 doesn't round correctly. Instead, we use ((X / 16) + 1) / 2 for correct rounding |
mbed_official | 174:8bb9f3a33240 | 194 | |
mbed_official | 220:aa774fb95d17 | 195 | if ((mv * PCLK * 2) & 0x80000000) // 1 bit headroom |
mbed_official | 220:aa774fb95d17 | 196 | dlv = ((((2 * mv * PCLK) / (baudrate * (dav + mv))) / 16) + 1) / 2; |
mbed_official | 220:aa774fb95d17 | 197 | else // 2 bits headroom, use more precision |
mbed_official | 220:aa774fb95d17 | 198 | dlv = ((((4 * mv * PCLK) / (baudrate * (dav + mv))) / 32) + 1) / 2; |
mbed_official | 174:8bb9f3a33240 | 199 | |
mbed_official | 220:aa774fb95d17 | 200 | // datasheet says if DLL==DLM==0, then 1 is used instead since divide by zero is ungood |
mbed_official | 220:aa774fb95d17 | 201 | if (dlv == 0) |
mbed_official | 220:aa774fb95d17 | 202 | dlv = 1; |
mbed_official | 174:8bb9f3a33240 | 203 | |
mbed_official | 220:aa774fb95d17 | 204 | // datasheet says if dav > 0 then DL must be >= 2 |
mbed_official | 220:aa774fb95d17 | 205 | if ((dav > 0) && (dlv < 2)) |
mbed_official | 220:aa774fb95d17 | 206 | dlv = 2; |
mbed_official | 220:aa774fb95d17 | 207 | |
mbed_official | 220:aa774fb95d17 | 208 | // integer rearrangement of the baudrate equation (with rounding) |
mbed_official | 220:aa774fb95d17 | 209 | b = ((PCLK * mv / (dlv * (dav + mv) * 8)) + 1) / 2; |
mbed_official | 174:8bb9f3a33240 | 210 | |
mbed_official | 220:aa774fb95d17 | 211 | // check to see how we went |
mbed_official | 220:aa774fb95d17 | 212 | b = abs(b - baudrate); |
mbed_official | 220:aa774fb95d17 | 213 | if (b < err_best) |
mbed_official | 220:aa774fb95d17 | 214 | { |
mbed_official | 220:aa774fb95d17 | 215 | err_best = b; |
mbed_official | 174:8bb9f3a33240 | 216 | |
mbed_official | 220:aa774fb95d17 | 217 | DL = dlv; |
mbed_official | 220:aa774fb95d17 | 218 | MulVal = mv; |
mbed_official | 220:aa774fb95d17 | 219 | DivAddVal = dav; |
mbed_official | 174:8bb9f3a33240 | 220 | |
mbed_official | 220:aa774fb95d17 | 221 | if (b == baudrate) |
mbed_official | 220:aa774fb95d17 | 222 | { |
mbed_official | 220:aa774fb95d17 | 223 | hit = 1; |
mbed_official | 220:aa774fb95d17 | 224 | break; |
mbed_official | 220:aa774fb95d17 | 225 | } |
mbed_official | 174:8bb9f3a33240 | 226 | } |
mbed_official | 174:8bb9f3a33240 | 227 | } |
mbed_official | 174:8bb9f3a33240 | 228 | } |
mbed_official | 174:8bb9f3a33240 | 229 | } |
mbed_official | 220:aa774fb95d17 | 230 | |
mbed_official | 220:aa774fb95d17 | 231 | // set LCR[DLAB] to enable writing to divider registers |
mbed_official | 220:aa774fb95d17 | 232 | obj->uart->LCR |= (1 << 7); |
mbed_official | 220:aa774fb95d17 | 233 | |
mbed_official | 220:aa774fb95d17 | 234 | // set divider values |
mbed_official | 220:aa774fb95d17 | 235 | obj->uart->DLM = (DL >> 8) & 0xFF; |
mbed_official | 220:aa774fb95d17 | 236 | obj->uart->DLL = (DL >> 0) & 0xFF; |
mbed_official | 220:aa774fb95d17 | 237 | obj->uart->FDR = (uint32_t) DivAddVal << 0 |
mbed_official | 220:aa774fb95d17 | 238 | | (uint32_t) MulVal << 4; |
mbed_official | 220:aa774fb95d17 | 239 | |
mbed_official | 220:aa774fb95d17 | 240 | // clear LCR[DLAB] |
mbed_official | 220:aa774fb95d17 | 241 | obj->uart->LCR &= ~(1 << 7); |
mbed_official | 174:8bb9f3a33240 | 242 | } |
mbed_official | 220:aa774fb95d17 | 243 | else { |
mbed_official | 220:aa774fb95d17 | 244 | uint32_t UARTSysClk = SystemCoreClock / LPC_SYSCON->FRGCLKDIV; |
mbed_official | 220:aa774fb95d17 | 245 | obj->mini_uart->BRG = UARTSysClk / 16 / baudrate - 1; |
mbed_official | 220:aa774fb95d17 | 246 | |
mbed_official | 220:aa774fb95d17 | 247 | LPC_SYSCON->UARTFRGDIV = 0xFF; |
mbed_official | 220:aa774fb95d17 | 248 | LPC_SYSCON->UARTFRGMULT = ( ((UARTSysClk / 16) * (LPC_SYSCON->UARTFRGDIV + 1)) / |
mbed_official | 220:aa774fb95d17 | 249 | (baudrate * (obj->mini_uart->BRG + 1)) |
mbed_official | 220:aa774fb95d17 | 250 | ) - (LPC_SYSCON->UARTFRGDIV + 1); |
mbed_official | 220:aa774fb95d17 | 251 | } |
mbed_official | 174:8bb9f3a33240 | 252 | } |
mbed_official | 174:8bb9f3a33240 | 253 | |
mbed_official | 174:8bb9f3a33240 | 254 | void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { |
mbed_official | 174:8bb9f3a33240 | 255 | // 0: 1 stop bits, 1: 2 stop bits |
mbed_official | 174:8bb9f3a33240 | 256 | if (stop_bits != 1 && stop_bits != 2) { |
mbed_official | 174:8bb9f3a33240 | 257 | error("Invalid stop bits specified"); |
mbed_official | 174:8bb9f3a33240 | 258 | } |
mbed_official | 174:8bb9f3a33240 | 259 | stop_bits -= 1; |
mbed_official | 174:8bb9f3a33240 | 260 | |
mbed_official | 220:aa774fb95d17 | 261 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 262 | // 0: 5 data bits ... 3: 8 data bits |
mbed_official | 220:aa774fb95d17 | 263 | if (data_bits < 5 || data_bits > 8) { |
mbed_official | 220:aa774fb95d17 | 264 | error("Invalid number of bits (%d) in serial format, should be 5..8", data_bits); |
mbed_official | 220:aa774fb95d17 | 265 | } |
mbed_official | 220:aa774fb95d17 | 266 | data_bits -= 5; |
mbed_official | 220:aa774fb95d17 | 267 | |
mbed_official | 220:aa774fb95d17 | 268 | int parity_enable, parity_select; |
mbed_official | 220:aa774fb95d17 | 269 | switch (parity) { |
mbed_official | 220:aa774fb95d17 | 270 | case ParityNone: parity_enable = 0; parity_select = 0; break; |
mbed_official | 220:aa774fb95d17 | 271 | case ParityOdd : parity_enable = 1; parity_select = 0; break; |
mbed_official | 220:aa774fb95d17 | 272 | case ParityEven: parity_enable = 1; parity_select = 1; break; |
mbed_official | 220:aa774fb95d17 | 273 | case ParityForced1: parity_enable = 1; parity_select = 2; break; |
mbed_official | 220:aa774fb95d17 | 274 | case ParityForced0: parity_enable = 1; parity_select = 3; break; |
mbed_official | 220:aa774fb95d17 | 275 | default: |
mbed_official | 220:aa774fb95d17 | 276 | error("Invalid serial parity setting"); |
mbed_official | 220:aa774fb95d17 | 277 | return; |
mbed_official | 220:aa774fb95d17 | 278 | } |
mbed_official | 220:aa774fb95d17 | 279 | |
mbed_official | 220:aa774fb95d17 | 280 | obj->uart->LCR = data_bits << 0 |
mbed_official | 220:aa774fb95d17 | 281 | | stop_bits << 2 |
mbed_official | 220:aa774fb95d17 | 282 | | parity_enable << 3 |
mbed_official | 220:aa774fb95d17 | 283 | | parity_select << 4; |
mbed_official | 174:8bb9f3a33240 | 284 | } |
mbed_official | 220:aa774fb95d17 | 285 | else { |
mbed_official | 220:aa774fb95d17 | 286 | // 0: 7 data bits ... 2: 9 data bits |
mbed_official | 220:aa774fb95d17 | 287 | if (data_bits < 7 || data_bits > 9) { |
mbed_official | 220:aa774fb95d17 | 288 | error("Invalid number of bits (%d) in serial format, should be 7..9", data_bits); |
mbed_official | 220:aa774fb95d17 | 289 | } |
mbed_official | 220:aa774fb95d17 | 290 | data_bits -= 7; |
mbed_official | 220:aa774fb95d17 | 291 | |
mbed_official | 220:aa774fb95d17 | 292 | int paritysel; |
mbed_official | 220:aa774fb95d17 | 293 | switch (parity) { |
mbed_official | 220:aa774fb95d17 | 294 | case ParityNone: paritysel = 0; break; |
mbed_official | 220:aa774fb95d17 | 295 | case ParityEven: paritysel = 2; break; |
mbed_official | 220:aa774fb95d17 | 296 | case ParityOdd : paritysel = 3; break; |
mbed_official | 220:aa774fb95d17 | 297 | default: |
mbed_official | 220:aa774fb95d17 | 298 | error("Invalid serial parity setting"); |
mbed_official | 220:aa774fb95d17 | 299 | return; |
mbed_official | 220:aa774fb95d17 | 300 | } |
mbed_official | 220:aa774fb95d17 | 301 | obj->mini_uart->CFG = (data_bits << 2) |
mbed_official | 220:aa774fb95d17 | 302 | | (paritysel << 4) |
mbed_official | 220:aa774fb95d17 | 303 | | (stop_bits << 6) |
mbed_official | 220:aa774fb95d17 | 304 | | UART_EN; |
mbed_official | 174:8bb9f3a33240 | 305 | } |
mbed_official | 174:8bb9f3a33240 | 306 | } |
mbed_official | 174:8bb9f3a33240 | 307 | |
mbed_official | 174:8bb9f3a33240 | 308 | /****************************************************************************** |
mbed_official | 174:8bb9f3a33240 | 309 | * INTERRUPTS HANDLING |
mbed_official | 174:8bb9f3a33240 | 310 | ******************************************************************************/ |
mbed_official | 174:8bb9f3a33240 | 311 | static inline void uart_irq(uint32_t iir, uint32_t index) { |
mbed_official | 174:8bb9f3a33240 | 312 | SerialIrq irq_type; |
mbed_official | 174:8bb9f3a33240 | 313 | switch (iir) { |
mbed_official | 174:8bb9f3a33240 | 314 | case 1: irq_type = TxIrq; break; |
mbed_official | 174:8bb9f3a33240 | 315 | case 2: irq_type = RxIrq; break; |
mbed_official | 174:8bb9f3a33240 | 316 | default: return; |
mbed_official | 174:8bb9f3a33240 | 317 | } |
mbed_official | 174:8bb9f3a33240 | 318 | |
mbed_official | 174:8bb9f3a33240 | 319 | if (serial_irq_ids[index] != 0) |
mbed_official | 174:8bb9f3a33240 | 320 | irq_handler(serial_irq_ids[index], irq_type); |
mbed_official | 174:8bb9f3a33240 | 321 | } |
mbed_official | 174:8bb9f3a33240 | 322 | |
mbed_official | 174:8bb9f3a33240 | 323 | void uart0_irq() |
mbed_official | 174:8bb9f3a33240 | 324 | { |
mbed_official | 174:8bb9f3a33240 | 325 | uart_irq((LPC_USART0->IIR >> 1) & 0x7, 0); |
mbed_official | 174:8bb9f3a33240 | 326 | } |
mbed_official | 174:8bb9f3a33240 | 327 | |
mbed_official | 174:8bb9f3a33240 | 328 | void uart1_irq() |
mbed_official | 174:8bb9f3a33240 | 329 | { |
mbed_official | 220:aa774fb95d17 | 330 | uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 1); |
mbed_official | 174:8bb9f3a33240 | 331 | } |
mbed_official | 174:8bb9f3a33240 | 332 | |
mbed_official | 174:8bb9f3a33240 | 333 | void uart2_irq() |
mbed_official | 174:8bb9f3a33240 | 334 | { |
mbed_official | 220:aa774fb95d17 | 335 | uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 2); |
mbed_official | 174:8bb9f3a33240 | 336 | } |
mbed_official | 174:8bb9f3a33240 | 337 | |
mbed_official | 174:8bb9f3a33240 | 338 | void uart3_irq() |
mbed_official | 174:8bb9f3a33240 | 339 | { |
mbed_official | 220:aa774fb95d17 | 340 | uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 3); |
mbed_official | 174:8bb9f3a33240 | 341 | } |
mbed_official | 174:8bb9f3a33240 | 342 | |
mbed_official | 174:8bb9f3a33240 | 343 | void uart4_irq() |
mbed_official | 174:8bb9f3a33240 | 344 | { |
mbed_official | 220:aa774fb95d17 | 345 | uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 4); |
mbed_official | 174:8bb9f3a33240 | 346 | } |
mbed_official | 174:8bb9f3a33240 | 347 | |
mbed_official | 174:8bb9f3a33240 | 348 | void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { |
mbed_official | 174:8bb9f3a33240 | 349 | irq_handler = handler; |
mbed_official | 174:8bb9f3a33240 | 350 | serial_irq_ids[obj->index] = id; |
mbed_official | 174:8bb9f3a33240 | 351 | } |
mbed_official | 174:8bb9f3a33240 | 352 | |
mbed_official | 174:8bb9f3a33240 | 353 | void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { |
mbed_official | 174:8bb9f3a33240 | 354 | IRQn_Type irq_n = (IRQn_Type)0; |
mbed_official | 174:8bb9f3a33240 | 355 | uint32_t vector = 0; |
mbed_official | 174:8bb9f3a33240 | 356 | switch ((int)obj->uart) { |
mbed_official | 174:8bb9f3a33240 | 357 | case UART_0: irq_n = USART0_IRQn; vector = (uint32_t)&uart0_irq; break; |
mbed_official | 174:8bb9f3a33240 | 358 | case UART_1: irq_n = USART1_4_IRQn; vector = (uint32_t)&uart1_irq; break; |
mbed_official | 174:8bb9f3a33240 | 359 | case UART_2: irq_n = USART2_3_IRQn; vector = (uint32_t)&uart2_irq; break; |
mbed_official | 174:8bb9f3a33240 | 360 | case UART_3: irq_n = USART2_3_IRQn; vector = (uint32_t)&uart3_irq; break; |
mbed_official | 174:8bb9f3a33240 | 361 | case UART_4: irq_n = USART1_4_IRQn; vector = (uint32_t)&uart4_irq; break; |
mbed_official | 174:8bb9f3a33240 | 362 | } |
mbed_official | 174:8bb9f3a33240 | 363 | |
mbed_official | 174:8bb9f3a33240 | 364 | if (enable) { |
mbed_official | 220:aa774fb95d17 | 365 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 366 | obj->uart->IER |= (1 << irq); |
mbed_official | 220:aa774fb95d17 | 367 | } |
mbed_official | 220:aa774fb95d17 | 368 | else { |
mbed_official | 220:aa774fb95d17 | 369 | obj->mini_uart->INTENSET = (1 << ((irq == RxIrq) ? 0 : 2)); |
mbed_official | 220:aa774fb95d17 | 370 | } |
mbed_official | 174:8bb9f3a33240 | 371 | NVIC_SetVector(irq_n, vector); |
mbed_official | 174:8bb9f3a33240 | 372 | NVIC_EnableIRQ(irq_n); |
mbed_official | 174:8bb9f3a33240 | 373 | } else { // disable |
mbed_official | 174:8bb9f3a33240 | 374 | int all_disabled = 0; |
mbed_official | 174:8bb9f3a33240 | 375 | SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq); |
mbed_official | 174:8bb9f3a33240 | 376 | |
mbed_official | 220:aa774fb95d17 | 377 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 378 | obj->uart->IER &= ~(1 << irq); |
mbed_official | 220:aa774fb95d17 | 379 | all_disabled = (obj->uart->IER & (1 << other_irq)) == 0; |
mbed_official | 220:aa774fb95d17 | 380 | } |
mbed_official | 220:aa774fb95d17 | 381 | else { |
mbed_official | 220:aa774fb95d17 | 382 | obj->mini_uart->INTENSET &= ~(1 << ((irq == RxIrq) ? 0 : 2)); |
mbed_official | 220:aa774fb95d17 | 383 | all_disabled = (obj->mini_uart->INTENSET & (1 << ((other_irq == RxIrq) ? 0 : 2))) == 0; |
mbed_official | 220:aa774fb95d17 | 384 | } |
mbed_official | 220:aa774fb95d17 | 385 | |
mbed_official | 174:8bb9f3a33240 | 386 | if (all_disabled) |
mbed_official | 174:8bb9f3a33240 | 387 | NVIC_DisableIRQ(irq_n); |
mbed_official | 174:8bb9f3a33240 | 388 | } |
mbed_official | 174:8bb9f3a33240 | 389 | } |
mbed_official | 174:8bb9f3a33240 | 390 | |
mbed_official | 174:8bb9f3a33240 | 391 | /****************************************************************************** |
mbed_official | 174:8bb9f3a33240 | 392 | * READ/WRITE |
mbed_official | 174:8bb9f3a33240 | 393 | ******************************************************************************/ |
mbed_official | 174:8bb9f3a33240 | 394 | int serial_getc(serial_t *obj) { |
mbed_official | 174:8bb9f3a33240 | 395 | while (!serial_readable(obj)); |
mbed_official | 220:aa774fb95d17 | 396 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 397 | return obj->uart->RBR; |
mbed_official | 220:aa774fb95d17 | 398 | } |
mbed_official | 220:aa774fb95d17 | 399 | else { |
mbed_official | 220:aa774fb95d17 | 400 | return obj->mini_uart->RXDAT; |
mbed_official | 220:aa774fb95d17 | 401 | } |
mbed_official | 174:8bb9f3a33240 | 402 | } |
mbed_official | 174:8bb9f3a33240 | 403 | |
mbed_official | 174:8bb9f3a33240 | 404 | void serial_putc(serial_t *obj, int c) { |
mbed_official | 174:8bb9f3a33240 | 405 | while (!serial_writable(obj)); |
mbed_official | 220:aa774fb95d17 | 406 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 407 | obj->uart->THR = c; |
mbed_official | 220:aa774fb95d17 | 408 | } |
mbed_official | 220:aa774fb95d17 | 409 | else { |
mbed_official | 220:aa774fb95d17 | 410 | obj->mini_uart->TXDAT = c; |
mbed_official | 220:aa774fb95d17 | 411 | } |
mbed_official | 174:8bb9f3a33240 | 412 | } |
mbed_official | 174:8bb9f3a33240 | 413 | |
mbed_official | 174:8bb9f3a33240 | 414 | int serial_readable(serial_t *obj) { |
mbed_official | 220:aa774fb95d17 | 415 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 416 | return obj->uart->LSR & 0x01; |
mbed_official | 220:aa774fb95d17 | 417 | } |
mbed_official | 220:aa774fb95d17 | 418 | else { |
mbed_official | 220:aa774fb95d17 | 419 | return obj->mini_uart->STAT & RXRDY; |
mbed_official | 220:aa774fb95d17 | 420 | } |
mbed_official | 174:8bb9f3a33240 | 421 | } |
mbed_official | 174:8bb9f3a33240 | 422 | |
mbed_official | 174:8bb9f3a33240 | 423 | int serial_writable(serial_t *obj) { |
mbed_official | 220:aa774fb95d17 | 424 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 425 | return obj->uart->LSR & 0x20; |
mbed_official | 220:aa774fb95d17 | 426 | } |
mbed_official | 220:aa774fb95d17 | 427 | else { |
mbed_official | 220:aa774fb95d17 | 428 | return obj->mini_uart->STAT & TXRDY; |
mbed_official | 220:aa774fb95d17 | 429 | } |
mbed_official | 174:8bb9f3a33240 | 430 | } |
mbed_official | 174:8bb9f3a33240 | 431 | |
mbed_official | 174:8bb9f3a33240 | 432 | void serial_clear(serial_t *obj) { |
mbed_official | 220:aa774fb95d17 | 433 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 434 | obj->uart->FCR = 1 << 1 // rx FIFO reset |
mbed_official | 220:aa774fb95d17 | 435 | | 1 << 2 // tx FIFO reset |
mbed_official | 220:aa774fb95d17 | 436 | | 0 << 6; // interrupt depth |
mbed_official | 220:aa774fb95d17 | 437 | } |
mbed_official | 220:aa774fb95d17 | 438 | else { |
mbed_official | 220:aa774fb95d17 | 439 | obj->mini_uart->STAT = 0; |
mbed_official | 220:aa774fb95d17 | 440 | } |
mbed_official | 174:8bb9f3a33240 | 441 | } |
mbed_official | 174:8bb9f3a33240 | 442 | |
mbed_official | 174:8bb9f3a33240 | 443 | void serial_pinout_tx(PinName tx) { |
mbed_official | 174:8bb9f3a33240 | 444 | pinmap_pinout(tx, PinMap_UART_TX); |
mbed_official | 174:8bb9f3a33240 | 445 | } |
mbed_official | 174:8bb9f3a33240 | 446 | |
mbed_official | 174:8bb9f3a33240 | 447 | void serial_break_set(serial_t *obj) { |
mbed_official | 220:aa774fb95d17 | 448 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 449 | obj->uart->LCR |= (1 << 6); |
mbed_official | 220:aa774fb95d17 | 450 | } |
mbed_official | 220:aa774fb95d17 | 451 | else { |
mbed_official | 220:aa774fb95d17 | 452 | obj->mini_uart->CTL |= TXBRKEN; |
mbed_official | 220:aa774fb95d17 | 453 | } |
mbed_official | 174:8bb9f3a33240 | 454 | } |
mbed_official | 174:8bb9f3a33240 | 455 | |
mbed_official | 174:8bb9f3a33240 | 456 | void serial_break_clear(serial_t *obj) { |
mbed_official | 220:aa774fb95d17 | 457 | if (obj->index == 0) { |
mbed_official | 220:aa774fb95d17 | 458 | obj->uart->LCR &= ~(1 << 6); |
mbed_official | 220:aa774fb95d17 | 459 | } |
mbed_official | 220:aa774fb95d17 | 460 | else { |
mbed_official | 220:aa774fb95d17 | 461 | obj->mini_uart->CTL &= ~TXBRKEN; |
mbed_official | 220:aa774fb95d17 | 462 | } |
mbed_official | 174:8bb9f3a33240 | 463 | } |
mbed_official | 174:8bb9f3a33240 | 464 | |
mbed_official | 174:8bb9f3a33240 | 465 | |
mbed_official | 174:8bb9f3a33240 | 466 | #endif |