mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Tue Nov 08 17:45:16 2016 +0000
Revision:
150:02e0a0aed4ec
This updates the lib to the mbed lib v129

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 150:02e0a0aed4ec 1 /* mbed Microcontroller Library
<> 150:02e0a0aed4ec 2 * Copyright (c) 2016 u-blox
<> 150:02e0a0aed4ec 3 *
<> 150:02e0a0aed4ec 4 * Licensed under the Apache License, Version 2.0 (the "License");
<> 150:02e0a0aed4ec 5 * you may not use this file except in compliance with the License.
<> 150:02e0a0aed4ec 6 * You may obtain a copy of the License at
<> 150:02e0a0aed4ec 7 *
<> 150:02e0a0aed4ec 8 * http://www.apache.org/licenses/LICENSE-2.0
<> 150:02e0a0aed4ec 9 *
<> 150:02e0a0aed4ec 10 * Unless required by applicable law or agreed to in writing, software
<> 150:02e0a0aed4ec 11 * distributed under the License is distributed on an "AS IS" BASIS,
<> 150:02e0a0aed4ec 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 150:02e0a0aed4ec 13 * See the License for the specific language governing permissions and
<> 150:02e0a0aed4ec 14 * limitations under the License.
<> 150:02e0a0aed4ec 15 */
<> 150:02e0a0aed4ec 16
<> 150:02e0a0aed4ec 17 /* The serial driver connects UART HW to mbed and also associates the UART
<> 150:02e0a0aed4ec 18 * HW with physical pins. Any physical pin can be linked to any UART,
<> 150:02e0a0aed4ec 19 * however the mbed serial port initialisation API makes no mention of
<> 150:02e0a0aed4ec 20 * which UART HW is to be used (only the pins) and hence the driver needs
<> 150:02e0a0aed4ec 21 * to make some decisions for itself.
<> 150:02e0a0aed4ec 22 *
<> 150:02e0a0aed4ec 23 * There are two and a half UARTs on the chip: UART0, UART1 and a
<> 150:02e0a0aed4ec 24 * lower-power, receive-only UART that is clocked from 32 kHz and can
<> 150:02e0a0aed4ec 25 * therefore be awake while the rest of the chip is sleeping peacefully.
<> 150:02e0a0aed4ec 26 * This provides maximal power saving, however the LP UART can only run
<> 150:02e0a0aed4ec 27 * at 9600 bits/s (which is quite sufficient for all NB-IoT needs).
<> 150:02e0a0aed4ec 28 *
<> 150:02e0a0aed4ec 29 * So, if the baud rate is 9600 the driver code configures the LP UART
<> 150:02e0a0aed4ec 30 * for Rx and UART0 for Tx. If the baud rate is not 9600 then it configures
<> 150:02e0a0aed4ec 31 * UART0 for both Rx and Tx. Unless... the Tx pin is the pin UART1_TX (it
<> 150:02e0a0aed4ec 32 * is an mbed convention to use the Tx pin), which is p6, in which case UART1
<> 150:02e0a0aed4ec 33 * is configured instead. This latter is not the normal case as this pin
<> 150:02e0a0aed4ec 34 * is intended to be used as a GPIO.
<> 150:02e0a0aed4ec 35 *
<> 150:02e0a0aed4ec 36 * If the baud rate is changed the driver reconfigures to match.
<> 150:02e0a0aed4ec 37 *
<> 150:02e0a0aed4ec 38 * TODO: implement asynchronous and flow control APIs.
<> 150:02e0a0aed4ec 39 */
<> 150:02e0a0aed4ec 40
<> 150:02e0a0aed4ec 41 #include "mbed_assert.h"
<> 150:02e0a0aed4ec 42 #include "serial_api.h"
<> 150:02e0a0aed4ec 43 #include "pinmap.h"
<> 150:02e0a0aed4ec 44
<> 150:02e0a0aed4ec 45 #include "cmsis.h"
<> 150:02e0a0aed4ec 46
<> 150:02e0a0aed4ec 47 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 48 * MACROS
<> 150:02e0a0aed4ec 49 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 50
<> 150:02e0a0aed4ec 51 /* Registers banks for the standard UARTs */
<> 150:02e0a0aed4ec 52 #define UART0_REG (*(volatile uart_ctrl_t *) UART0_BASE)
<> 150:02e0a0aed4ec 53 #define UART1_REG (*(volatile uart_ctrl_t *) UART1_BASE)
<> 150:02e0a0aed4ec 54
<> 150:02e0a0aed4ec 55 /* Masks for the UART control bits in the reset and clock enable registers */
<> 150:02e0a0aed4ec 56 #define UART0_CTRL (1 << 3)
<> 150:02e0a0aed4ec 57 #define UART1_CTRL (1 << 4)
<> 150:02e0a0aed4ec 58 #define UARTLP_CTRL (1 << 6)
<> 150:02e0a0aed4ec 59
<> 150:02e0a0aed4ec 60 /* Convert number of data bits to register values */
<> 150:02e0a0aed4ec 61 #define MIN_NUM_UART_DATA_BITS 5
<> 150:02e0a0aed4ec 62 #define MAX_NUM_UART_DATA_BITS 8
<> 150:02e0a0aed4ec 63 #define REGISTER_DATA_BITS(x) ((x) - MIN_NUM_UART_DATA_BITS)
<> 150:02e0a0aed4ec 64
<> 150:02e0a0aed4ec 65 /* Number of stop bits */
<> 150:02e0a0aed4ec 66 #define NUM_UART_STOP_BITS_1 1
<> 150:02e0a0aed4ec 67 #define NUM_UART_STOP_BITS_2 2
<> 150:02e0a0aed4ec 68
<> 150:02e0a0aed4ec 69 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 70 * TYPES
<> 150:02e0a0aed4ec 71 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 72
<> 150:02e0a0aed4ec 73 /* Enum to identify the interrupt to the UART handler */
<> 150:02e0a0aed4ec 74 typedef enum {
<> 150:02e0a0aed4ec 75 IRQ_UART_ID_0_AND_LP,
<> 150:02e0a0aed4ec 76 IRQ_UART_ID_1,
<> 150:02e0a0aed4ec 77 NUM_IRQ_IDS
<> 150:02e0a0aed4ec 78 } irq_uart_id_t;
<> 150:02e0a0aed4ec 79
<> 150:02e0a0aed4ec 80 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 81 * GLOBAL VARIABLES
<> 150:02e0a0aed4ec 82 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 83
<> 150:02e0a0aed4ec 84 /* The IRQ configuration variables, set up and named by mbed */
<> 150:02e0a0aed4ec 85 static uint32_t serial_irq_ids[NUM_IRQ_IDS] = {0};
<> 150:02e0a0aed4ec 86 static uart_irq_handler irq_handler = NULL;
<> 150:02e0a0aed4ec 87
<> 150:02e0a0aed4ec 88 /* RTX needs these */
<> 150:02e0a0aed4ec 89 int stdio_uart_inited = 0;
<> 150:02e0a0aed4ec 90 serial_t stdio_uart;
<> 150:02e0a0aed4ec 91
<> 150:02e0a0aed4ec 92 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 93 * FUNCTION PROTOTYPES
<> 150:02e0a0aed4ec 94 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 95
<> 150:02e0a0aed4ec 96 static void init_config(serial_t *obj);
<> 150:02e0a0aed4ec 97 static void deinit_config(serial_t *obj);
<> 150:02e0a0aed4ec 98 static void set_baud(serial_t *obj, uint32_t baud_rate);
<> 150:02e0a0aed4ec 99 static void irq_enable(serial_t *obj);
<> 150:02e0a0aed4ec 100 static void irq_disable(serial_t *obj);
<> 150:02e0a0aed4ec 101
<> 150:02e0a0aed4ec 102 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 103 * NON-API FUNCTIONS
<> 150:02e0a0aed4ec 104 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 105
<> 150:02e0a0aed4ec 106 /* Initialise the given serial config by setting the pin functions
<> 150:02e0a0aed4ec 107 * and then resetting the relevant HW */
<> 150:02e0a0aed4ec 108 static void init_config(serial_t *obj)
<> 150:02e0a0aed4ec 109 {
<> 150:02e0a0aed4ec 110 uint32_t x;
<> 150:02e0a0aed4ec 111
<> 150:02e0a0aed4ec 112 switch (obj->config) {
<> 150:02e0a0aed4ec 113 case SERIAL_CONFIG_UARTLP_RX_UART0_TX:
<> 150:02e0a0aed4ec 114 {
<> 150:02e0a0aed4ec 115 pin_function(obj->rx_pin, PIN_FUNCTION_LP_UART);
<> 150:02e0a0aed4ec 116 pin_function(obj->tx_pin, PIN_FUNCTION_UART0_TXD);
<> 150:02e0a0aed4ec 117 CLKEN_REG_BITSET = UARTLP_CTRL | UART0_CTRL;
<> 150:02e0a0aed4ec 118 obj->reg_base = &UART0_REG;
<> 150:02e0a0aed4ec 119 obj->index = IRQ_UART_ID_0_AND_LP;
<> 150:02e0a0aed4ec 120 /* Reset the LPUART and UART0 HW */
<> 150:02e0a0aed4ec 121 /* NOTE: RESET_REG_BITTOG doesn't have the desired
<> 150:02e0a0aed4ec 122 * effect, need to use BITSET and then BITCLR */
<> 150:02e0a0aed4ec 123 RESET_REG_BITSET |= 1ul << 6;
<> 150:02e0a0aed4ec 124 RESET_REG_BITCLR |= 1ul << 6;
<> 150:02e0a0aed4ec 125 RESET_REG_BITSET |= 1ul << 3;
<> 150:02e0a0aed4ec 126 RESET_REG_BITCLR |= 1ul << 3;
<> 150:02e0a0aed4ec 127 }
<> 150:02e0a0aed4ec 128 break;
<> 150:02e0a0aed4ec 129 case SERIAL_CONFIG_UART0_RX_UART0_TX:
<> 150:02e0a0aed4ec 130 {
<> 150:02e0a0aed4ec 131 pin_function(obj->rx_pin, PIN_FUNCTION_UART0_RXD);
<> 150:02e0a0aed4ec 132 pin_function(obj->tx_pin, PIN_FUNCTION_UART0_TXD);
<> 150:02e0a0aed4ec 133 CLKEN_REG_BITSET = UART0_CTRL;
<> 150:02e0a0aed4ec 134 obj->reg_base = &UART0_REG;
<> 150:02e0a0aed4ec 135 obj->index = IRQ_UART_ID_0_AND_LP;
<> 150:02e0a0aed4ec 136 /* Reset the UART0 HW */
<> 150:02e0a0aed4ec 137 RESET_REG_BITSET |= 1ul << 3;
<> 150:02e0a0aed4ec 138 RESET_REG_BITCLR |= 1ul << 3;
<> 150:02e0a0aed4ec 139 }
<> 150:02e0a0aed4ec 140 break;
<> 150:02e0a0aed4ec 141 case SERIAL_CONFIG_UART1_RX_UART1_TX:
<> 150:02e0a0aed4ec 142 {
<> 150:02e0a0aed4ec 143 pin_function(obj->rx_pin, PIN_FUNCTION_UART1_RXD);
<> 150:02e0a0aed4ec 144 pin_function(obj->tx_pin, PIN_FUNCTION_UART1_TXD);
<> 150:02e0a0aed4ec 145 CLKEN_REG_BITSET = UART1_CTRL;
<> 150:02e0a0aed4ec 146 obj->reg_base = &UART1_REG;
<> 150:02e0a0aed4ec 147 obj->index = IRQ_UART_ID_1;
<> 150:02e0a0aed4ec 148 /* Reset the UART1 HW */
<> 150:02e0a0aed4ec 149 RESET_REG_BITSET |= 1ul << 4;
<> 150:02e0a0aed4ec 150 RESET_REG_BITCLR |= 1ul << 4;
<> 150:02e0a0aed4ec 151 }
<> 150:02e0a0aed4ec 152 break;
<> 150:02e0a0aed4ec 153 default:
<> 150:02e0a0aed4ec 154 {
<> 150:02e0a0aed4ec 155 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 156 }
<> 150:02e0a0aed4ec 157 break;
<> 150:02e0a0aed4ec 158 }
<> 150:02e0a0aed4ec 159
<> 150:02e0a0aed4ec 160 /* Tickle the UART control register to make sure it is updated */
<> 150:02e0a0aed4ec 161 x = obj->reg_base->UARTLCR_H;
<> 150:02e0a0aed4ec 162 obj->reg_base->UARTLCR_H = x;
<> 150:02e0a0aed4ec 163
<> 150:02e0a0aed4ec 164 /* Set the FIFO. The meaning of the three FIFO interrupt-level
<> 150:02e0a0aed4ec 165 * bits are as follows:
<> 150:02e0a0aed4ec 166 *
<> 150:02e0a0aed4ec 167 * 0 = 1/8 full
<> 150:02e0a0aed4ec 168 * 1 = 1/4 full
<> 150:02e0a0aed4ec 169 * 2 = 1/2 full
<> 150:02e0a0aed4ec 170 * 3 = 3/4 full
<> 150:02e0a0aed4ec 171 * 4 = 7/8 full
<> 150:02e0a0aed4ec 172 *
<> 150:02e0a0aed4ec 173 * Set up the Rx FIFO to be used fully (but we will also set
<> 150:02e0a0aed4ec 174 * a timeout to get immediate notice) and also the Tx FIFO
<> 150:02e0a0aed4ec 175 * to be fully used. */
<> 150:02e0a0aed4ec 176 obj->reg_base->UARTIFLS = (obj->reg_base->UARTIFLS & ~(0x07 << 0)) | (4 << 0);
<> 150:02e0a0aed4ec 177 obj->reg_base->UARTIFLS = (obj->reg_base->UARTIFLS & ~(0x07 << 3)) | (4 << 3);
<> 150:02e0a0aed4ec 178 obj->reg_base->UARTLCR_H |= 1 << 4;
<> 150:02e0a0aed4ec 179
<> 150:02e0a0aed4ec 180 /* Enable for Tx and Rx (TODO: add CTS when we add flow control) */
<> 150:02e0a0aed4ec 181 obj->reg_base->UARTCR |= (1 << 8) | (1 << 9);
<> 150:02e0a0aed4ec 182
<> 150:02e0a0aed4ec 183 /* Now enable it */
<> 150:02e0a0aed4ec 184 obj->reg_base->UARTCR |= 1 << 0;
<> 150:02e0a0aed4ec 185
<> 150:02e0a0aed4ec 186 obj->format_set = false;
<> 150:02e0a0aed4ec 187 obj->baud_rate = 0;
<> 150:02e0a0aed4ec 188 obj->irq_rx_setting = IRQ_NOT_SET;
<> 150:02e0a0aed4ec 189 obj->irq_tx_setting = IRQ_NOT_SET;
<> 150:02e0a0aed4ec 190 }
<> 150:02e0a0aed4ec 191
<> 150:02e0a0aed4ec 192 /* Release a serial port */
<> 150:02e0a0aed4ec 193 static void deinit_config(serial_t *obj)
<> 150:02e0a0aed4ec 194 {
<> 150:02e0a0aed4ec 195 pin_function(obj->rx_pin, PIN_FUNCTION_UNCLAIMED);
<> 150:02e0a0aed4ec 196 pin_function(obj->tx_pin, PIN_FUNCTION_UNCLAIMED);
<> 150:02e0a0aed4ec 197
<> 150:02e0a0aed4ec 198 /* Disable UART */
<> 150:02e0a0aed4ec 199 obj->reg_base->UARTCR &= ~(1 << 0);
<> 150:02e0a0aed4ec 200
<> 150:02e0a0aed4ec 201 /* Flush transmit FIFO */
<> 150:02e0a0aed4ec 202 obj->reg_base->UARTLCR_H = 0;
<> 150:02e0a0aed4ec 203
<> 150:02e0a0aed4ec 204 /* Disable everything */
<> 150:02e0a0aed4ec 205 obj->reg_base->UARTCR = 0;
<> 150:02e0a0aed4ec 206
<> 150:02e0a0aed4ec 207 switch (obj->config) {
<> 150:02e0a0aed4ec 208 case SERIAL_CONFIG_UARTLP_RX_UART0_TX:
<> 150:02e0a0aed4ec 209 {
<> 150:02e0a0aed4ec 210 CLKEN_REG_BITCLR = UARTLP_CTRL | UART0_CTRL;
<> 150:02e0a0aed4ec 211 LP_UART_CTRL &= ~(0xF << 20); /* Disable all LP interrupts */
<> 150:02e0a0aed4ec 212 }
<> 150:02e0a0aed4ec 213 break;
<> 150:02e0a0aed4ec 214 case SERIAL_CONFIG_UART0_RX_UART0_TX:
<> 150:02e0a0aed4ec 215 {
<> 150:02e0a0aed4ec 216 CLKEN_REG_BITCLR = UART0_CTRL;
<> 150:02e0a0aed4ec 217 }
<> 150:02e0a0aed4ec 218 break;
<> 150:02e0a0aed4ec 219 case SERIAL_CONFIG_UART1_RX_UART1_TX:
<> 150:02e0a0aed4ec 220 {
<> 150:02e0a0aed4ec 221 CLKEN_REG_BITCLR = UART1_CTRL;
<> 150:02e0a0aed4ec 222 }
<> 150:02e0a0aed4ec 223 break;
<> 150:02e0a0aed4ec 224 default:
<> 150:02e0a0aed4ec 225 {
<> 150:02e0a0aed4ec 226 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 227 }
<> 150:02e0a0aed4ec 228 break;
<> 150:02e0a0aed4ec 229 }
<> 150:02e0a0aed4ec 230
<> 150:02e0a0aed4ec 231 obj->config = MAX_NUM_SERIAL_CONFIGS;
<> 150:02e0a0aed4ec 232 obj->reg_base = NULL;
<> 150:02e0a0aed4ec 233 }
<> 150:02e0a0aed4ec 234
<> 150:02e0a0aed4ec 235 /* Set the baud rate for either of the two (non-LP) UARTS */
<> 150:02e0a0aed4ec 236 static void set_baud(serial_t *obj, uint32_t baud_rate)
<> 150:02e0a0aed4ec 237 {
<> 150:02e0a0aed4ec 238 uint32_t baud_rate_divider_i;
<> 150:02e0a0aed4ec 239 uint32_t baud_rate_divider_f;
<> 150:02e0a0aed4ec 240 uint32_t remainder;
<> 150:02e0a0aed4ec 241 uint32_t core_clock;
<> 150:02e0a0aed4ec 242 uint32_t x;
<> 150:02e0a0aed4ec 243
<> 150:02e0a0aed4ec 244 /* Baud rate divider calculation:
<> 150:02e0a0aed4ec 245 *
<> 150:02e0a0aed4ec 246 * The integer part is: clock / (16 * baud)
<> 150:02e0a0aed4ec 247 *
<> 150:02e0a0aed4ec 248 * The fractional part is: round (decimal_part * 64),
<> 150:02e0a0aed4ec 249 * ...where decimal part is, for example, 0.085
<> 150:02e0a0aed4ec 250 *
<> 150:02e0a0aed4ec 251 * decimal_part is: remainder / (16 * baud),
<> 150:02e0a0aed4ec 252 * ...where: remainder = core_clock % (baud * 16),
<> 150:02e0a0aed4ec 253 *
<> 150:02e0a0aed4ec 254 * So the fractional part becomes:
<> 150:02e0a0aed4ec 255 * round (decimal_part * 64) = round (remainder * 64 / (16 * baud)) = round (remainder * 4 / baud)
<> 150:02e0a0aed4ec 256 */
<> 150:02e0a0aed4ec 257
<> 150:02e0a0aed4ec 258 /* Get the mean clock frequency */
<> 150:02e0a0aed4ec 259 core_clock = (CLK_FREQ_HIGHTARGET >> 1) + (CLK_FREQ_LOWTARGET >> 1);
<> 150:02e0a0aed4ec 260 /* Work out the actual clock frequency */
<> 150:02e0a0aed4ec 261 core_clock = (core_clock * CLOCKS_REFERENCE_CLOCK_FREQ) / (((CLK_FREQ_NREFCLKS + 1) & 0xFFFF) * (CLK_GATE_SYS & 0xFF));
<> 150:02e0a0aed4ec 262 baud_rate_divider_i = core_clock / (baud_rate << 4);
<> 150:02e0a0aed4ec 263 remainder = core_clock % (baud_rate << 4);
<> 150:02e0a0aed4ec 264 baud_rate_divider_f = ((remainder << 3) / baud_rate) >> 1;
<> 150:02e0a0aed4ec 265 /* Round it */
<> 150:02e0a0aed4ec 266 baud_rate_divider_f += ((remainder << 3) / baud_rate) & 1;
<> 150:02e0a0aed4ec 267
<> 150:02e0a0aed4ec 268 /* Disable UART while writing to control registers */
<> 150:02e0a0aed4ec 269 obj->reg_base->UARTCR &= ~(1 << 0);
<> 150:02e0a0aed4ec 270
<> 150:02e0a0aed4ec 271 obj->reg_base->UARTIBRD = baud_rate_divider_i;
<> 150:02e0a0aed4ec 272 obj->reg_base->UARTFBRD = baud_rate_divider_f;
<> 150:02e0a0aed4ec 273
<> 150:02e0a0aed4ec 274 /* Make IBRD and FBRD update */
<> 150:02e0a0aed4ec 275 x = obj->reg_base->UARTLCR_H;
<> 150:02e0a0aed4ec 276 obj->reg_base->UARTLCR_H = x;
<> 150:02e0a0aed4ec 277
<> 150:02e0a0aed4ec 278 /* Now enable the UART again */
<> 150:02e0a0aed4ec 279 obj->reg_base->UARTCR |= 1 << 0;
<> 150:02e0a0aed4ec 280 }
<> 150:02e0a0aed4ec 281
<> 150:02e0a0aed4ec 282 /* Set the NVIC bits */
<> 150:02e0a0aed4ec 283 static void irq_enable(serial_t *obj)
<> 150:02e0a0aed4ec 284 {
<> 150:02e0a0aed4ec 285 switch (obj->config) {
<> 150:02e0a0aed4ec 286 case SERIAL_CONFIG_UARTLP_RX_UART0_TX:
<> 150:02e0a0aed4ec 287 {
<> 150:02e0a0aed4ec 288 NVIC_EnableIRQ(UART0_IRQn);
<> 150:02e0a0aed4ec 289 NVIC_EnableIRQ(LPUART_IRQn);
<> 150:02e0a0aed4ec 290 }
<> 150:02e0a0aed4ec 291 break;
<> 150:02e0a0aed4ec 292 case SERIAL_CONFIG_UART0_RX_UART0_TX:
<> 150:02e0a0aed4ec 293 {
<> 150:02e0a0aed4ec 294 NVIC_EnableIRQ(UART0_IRQn);
<> 150:02e0a0aed4ec 295 }
<> 150:02e0a0aed4ec 296 break;
<> 150:02e0a0aed4ec 297 case SERIAL_CONFIG_UART1_RX_UART1_TX:
<> 150:02e0a0aed4ec 298 {
<> 150:02e0a0aed4ec 299 NVIC_EnableIRQ(UART1_IRQn);
<> 150:02e0a0aed4ec 300 }
<> 150:02e0a0aed4ec 301 break;
<> 150:02e0a0aed4ec 302 default:
<> 150:02e0a0aed4ec 303 {
<> 150:02e0a0aed4ec 304 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 305 }
<> 150:02e0a0aed4ec 306 break;
<> 150:02e0a0aed4ec 307 }
<> 150:02e0a0aed4ec 308 }
<> 150:02e0a0aed4ec 309
<> 150:02e0a0aed4ec 310 /* Unset the NVIC bits */
<> 150:02e0a0aed4ec 311 static void irq_disable(serial_t *obj)
<> 150:02e0a0aed4ec 312 {
<> 150:02e0a0aed4ec 313 switch (obj->config) {
<> 150:02e0a0aed4ec 314 case SERIAL_CONFIG_UARTLP_RX_UART0_TX:
<> 150:02e0a0aed4ec 315 {
<> 150:02e0a0aed4ec 316 NVIC_DisableIRQ(UART0_IRQn);
<> 150:02e0a0aed4ec 317 NVIC_DisableIRQ(LPUART_IRQn);
<> 150:02e0a0aed4ec 318 }
<> 150:02e0a0aed4ec 319 break;
<> 150:02e0a0aed4ec 320 case SERIAL_CONFIG_UART0_RX_UART0_TX:
<> 150:02e0a0aed4ec 321 {
<> 150:02e0a0aed4ec 322 NVIC_DisableIRQ(UART0_IRQn);
<> 150:02e0a0aed4ec 323 }
<> 150:02e0a0aed4ec 324 break;
<> 150:02e0a0aed4ec 325 case SERIAL_CONFIG_UART1_RX_UART1_TX:
<> 150:02e0a0aed4ec 326 {
<> 150:02e0a0aed4ec 327 NVIC_DisableIRQ(UART1_IRQn);
<> 150:02e0a0aed4ec 328 }
<> 150:02e0a0aed4ec 329 break;
<> 150:02e0a0aed4ec 330 default:
<> 150:02e0a0aed4ec 331 {
<> 150:02e0a0aed4ec 332 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 333 }
<> 150:02e0a0aed4ec 334 break;
<> 150:02e0a0aed4ec 335 }
<> 150:02e0a0aed4ec 336 }
<> 150:02e0a0aed4ec 337
<> 150:02e0a0aed4ec 338 /* UART0 IRQ */
<> 150:02e0a0aed4ec 339 void IRQ7_UART0_Handler()
<> 150:02e0a0aed4ec 340 {
<> 150:02e0a0aed4ec 341 uint32_t id = serial_irq_ids[IRQ_UART_ID_0_AND_LP];
<> 150:02e0a0aed4ec 342
<> 150:02e0a0aed4ec 343 /* Check Rx and Rx Timeout bit */
<> 150:02e0a0aed4ec 344 if (UART0_REG.UARTMIS & ((1 << 4) | (1 << 6))) {
<> 150:02e0a0aed4ec 345 if (id != 0) {
<> 150:02e0a0aed4ec 346 irq_handler(id, RxIrq);
<> 150:02e0a0aed4ec 347 /* Reading the character clears the interrupt,
<> 150:02e0a0aed4ec 348 * no way to protect against another arriving
<> 150:02e0a0aed4ec 349 * while processing one */
<> 150:02e0a0aed4ec 350 }
<> 150:02e0a0aed4ec 351 }
<> 150:02e0a0aed4ec 352 /* Check Tx bit */
<> 150:02e0a0aed4ec 353 if (UART0_REG.UARTMIS & (1 << 5)) {
<> 150:02e0a0aed4ec 354 if (id != 0) {
<> 150:02e0a0aed4ec 355 irq_handler(id, TxIrq);
<> 150:02e0a0aed4ec 356 }
<> 150:02e0a0aed4ec 357 /* Not sure what clears the interrupt so clear it explicitly */
<> 150:02e0a0aed4ec 358 NVIC_ClearPendingIRQ(UART1_IRQn);
<> 150:02e0a0aed4ec 359 }
<> 150:02e0a0aed4ec 360 }
<> 150:02e0a0aed4ec 361
<> 150:02e0a0aed4ec 362 /* UART1 IRQ */
<> 150:02e0a0aed4ec 363 void IRQ8_UART1_Handler()
<> 150:02e0a0aed4ec 364 {
<> 150:02e0a0aed4ec 365 uint32_t id = serial_irq_ids[IRQ_UART_ID_1];
<> 150:02e0a0aed4ec 366
<> 150:02e0a0aed4ec 367 /* Check Rx and Rx Timeout bit */
<> 150:02e0a0aed4ec 368 if (UART1_REG.UARTMIS & ((1 << 4) | (1 << 6))) {
<> 150:02e0a0aed4ec 369 if (id != 0) {
<> 150:02e0a0aed4ec 370 irq_handler(id, RxIrq);
<> 150:02e0a0aed4ec 371 }
<> 150:02e0a0aed4ec 372 /* Reading the character clears the interrupt,
<> 150:02e0a0aed4ec 373 * no way to protect against another arriving
<> 150:02e0a0aed4ec 374 * while processing one */
<> 150:02e0a0aed4ec 375 }
<> 150:02e0a0aed4ec 376 /* Check Tx bit */
<> 150:02e0a0aed4ec 377 if (UART1_REG.UARTMIS & (1 << 5)) {
<> 150:02e0a0aed4ec 378 if (id != 0) {
<> 150:02e0a0aed4ec 379 irq_handler(id, TxIrq);
<> 150:02e0a0aed4ec 380 }
<> 150:02e0a0aed4ec 381 /* Not sure what clears the interrupt so clear it explicitly */
<> 150:02e0a0aed4ec 382 NVIC_ClearPendingIRQ(UART1_IRQn);
<> 150:02e0a0aed4ec 383 }
<> 150:02e0a0aed4ec 384 }
<> 150:02e0a0aed4ec 385
<> 150:02e0a0aed4ec 386 /* LP UART IRQ, receive only */
<> 150:02e0a0aed4ec 387 void IRQ16_LPUART_Handler()
<> 150:02e0a0aed4ec 388 {
<> 150:02e0a0aed4ec 389 uint32_t id = serial_irq_ids[IRQ_UART_ID_0_AND_LP];
<> 150:02e0a0aed4ec 390
<> 150:02e0a0aed4ec 391 if (id != 0) {
<> 150:02e0a0aed4ec 392 irq_handler(id, RxIrq);
<> 150:02e0a0aed4ec 393
<> 150:02e0a0aed4ec 394 /* Another character might have arrived while
<> 150:02e0a0aed4ec 395 * we are processing the last, so
<> 150:02e0a0aed4ec 396 * check status bits 8 to 10 again and pend
<> 150:02e0a0aed4ec 397 * interrupt if there's something there */
<> 150:02e0a0aed4ec 398 if (((LP_UART_STATUS >> 8) & 0x07) != 0) {
<> 150:02e0a0aed4ec 399 NVIC_SetPendingIRQ(LPUART_IRQn);
<> 150:02e0a0aed4ec 400 } else {
<> 150:02e0a0aed4ec 401 LP_UART_CTRL |= 1 << 27; /* Clear the interrupt */
<> 150:02e0a0aed4ec 402 }
<> 150:02e0a0aed4ec 403 }
<> 150:02e0a0aed4ec 404 }
<> 150:02e0a0aed4ec 405
<> 150:02e0a0aed4ec 406 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 407 * MBED API CALLS: SETUP FUNCTIONS
<> 150:02e0a0aed4ec 408 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 409
<> 150:02e0a0aed4ec 410 void serial_init(serial_t *obj, PinName tx, PinName rx)
<> 150:02e0a0aed4ec 411 {
<> 150:02e0a0aed4ec 412 uint32_t clock = CLK_FREQ_DIG_CLKS;
<> 150:02e0a0aed4ec 413
<> 150:02e0a0aed4ec 414 /* There are two and a half UARTs on the chip. The normal
<> 150:02e0a0aed4ec 415 * configuration is to use the LP_UART for Rx and UART0 for
<> 150:02e0a0aed4ec 416 * Tx. This gives maximal power saving in that the chip can
<> 150:02e0a0aed4ec 417 * wake up on receipt of data. However, this only works if the
<> 150:02e0a0aed4ec 418 * data rate is 9600 because that's the only data rate that
<> 150:02e0a0aed4ec 419 * the 32 kHz (i.e. RTC) clock driving the LP UART can support.
<> 150:02e0a0aed4ec 420 *
<> 150:02e0a0aed4ec 421 * So, if the data rate is 9600, use the LP_UART/UART0
<> 150:02e0a0aed4ec 422 * combination, otherwise use UART0 for both Rx and Tx. However,
<> 150:02e0a0aed4ec 423 * we don't know the data rate at this point so assume LP_UART
<> 150:02e0a0aed4ec 424 * (as this works at the default baud rate) and we can change
<> 150:02e0a0aed4ec 425 * our minds later.
<> 150:02e0a0aed4ec 426 *
<> 150:02e0a0aed4ec 427 * There is another serial port, UART1, which is normally used
<> 150:02e0a0aed4ec 428 * by the modem processor to send out debug. We only initialise
<> 150:02e0a0aed4ec 429 * that here if the Tx pin is UART1_TX. */
<> 150:02e0a0aed4ec 430
<> 150:02e0a0aed4ec 431 /* Wait for the clock to be stable */
<> 150:02e0a0aed4ec 432 while ((clock < CLK_FREQ_LOWTARGET) || (clock > CLK_FREQ_HIGHTARGET)) {
<> 150:02e0a0aed4ec 433 clock = CLK_FREQ_DIG_CLKS;
<> 150:02e0a0aed4ec 434 }
<> 150:02e0a0aed4ec 435
<> 150:02e0a0aed4ec 436 if (tx == UART1_TX) {
<> 150:02e0a0aed4ec 437 /* Use UART1 for Rx and Tx */
<> 150:02e0a0aed4ec 438 obj->config = SERIAL_CONFIG_UART1_RX_UART1_TX;
<> 150:02e0a0aed4ec 439 } else {
<> 150:02e0a0aed4ec 440 /* Use LP_UART for Rx, UART0 for Tx */
<> 150:02e0a0aed4ec 441 obj->config = SERIAL_CONFIG_UARTLP_RX_UART0_TX;
<> 150:02e0a0aed4ec 442 }
<> 150:02e0a0aed4ec 443
<> 150:02e0a0aed4ec 444 obj->rx_pin = rx;
<> 150:02e0a0aed4ec 445 obj->tx_pin = tx;
<> 150:02e0a0aed4ec 446 init_config(obj);
<> 150:02e0a0aed4ec 447
<> 150:02e0a0aed4ec 448 /* TODO: set rx pin Pull mode ? */
<> 150:02e0a0aed4ec 449
<> 150:02e0a0aed4ec 450 /* set default baud rate and format */
<> 150:02e0a0aed4ec 451 serial_baud(obj, 9600);
<> 150:02e0a0aed4ec 452 serial_format(obj, 8, ParityNone, 1);
<> 150:02e0a0aed4ec 453
<> 150:02e0a0aed4ec 454 if (tx == UART0_TX) {
<> 150:02e0a0aed4ec 455 /* The UART0 pins are the stdio pins */
<> 150:02e0a0aed4ec 456 stdio_uart_inited = 1;
<> 150:02e0a0aed4ec 457 stdio_uart = *obj;
<> 150:02e0a0aed4ec 458 }
<> 150:02e0a0aed4ec 459 }
<> 150:02e0a0aed4ec 460
<> 150:02e0a0aed4ec 461 void serial_free(serial_t *obj)
<> 150:02e0a0aed4ec 462 {
<> 150:02e0a0aed4ec 463 if (obj->tx_pin == UART0_TX) {
<> 150:02e0a0aed4ec 464 stdio_uart_inited = 0;
<> 150:02e0a0aed4ec 465 }
<> 150:02e0a0aed4ec 466
<> 150:02e0a0aed4ec 467 serial_irq_ids[obj->index] = 0;
<> 150:02e0a0aed4ec 468
<> 150:02e0a0aed4ec 469 /* Release the port HW */
<> 150:02e0a0aed4ec 470 deinit_config(obj);
<> 150:02e0a0aed4ec 471 }
<> 150:02e0a0aed4ec 472
<> 150:02e0a0aed4ec 473 void serial_baud(serial_t *obj, int baudrate)
<> 150:02e0a0aed4ec 474 {
<> 150:02e0a0aed4ec 475 bool switch_port_config = false;
<> 150:02e0a0aed4ec 476 bool format_set = obj->format_set;
<> 150:02e0a0aed4ec 477 uint8_t stop_bits = obj->format.stop_bits;
<> 150:02e0a0aed4ec 478 uint8_t data_bits = obj->format.data_bits;
<> 150:02e0a0aed4ec 479 SerialParity parity = (SerialParity) obj->format.parity;
<> 150:02e0a0aed4ec 480 irq_setting_t irq_rx_setting = obj->irq_rx_setting;
<> 150:02e0a0aed4ec 481 irq_setting_t irq_tx_setting = obj->irq_tx_setting;
<> 150:02e0a0aed4ec 482
<> 150:02e0a0aed4ec 483 if ((obj->config == SERIAL_CONFIG_UARTLP_RX_UART0_TX) && (baudrate != 9600)) {
<> 150:02e0a0aed4ec 484 /* If we were on LP UART but the baud rate is not 9600 then
<> 150:02e0a0aed4ec 485 * switch to the standard UART (as the LP UART can't go any higher
<> 150:02e0a0aed4ec 486 * because it's clocked from 32 kHz) */
<> 150:02e0a0aed4ec 487 deinit_config(obj);
<> 150:02e0a0aed4ec 488 obj->config = SERIAL_CONFIG_UART0_RX_UART0_TX;
<> 150:02e0a0aed4ec 489 init_config(obj);
<> 150:02e0a0aed4ec 490 switch_port_config = true;
<> 150:02e0a0aed4ec 491 } else if ((obj->config == SERIAL_CONFIG_UART0_RX_UART0_TX) && (baudrate == 9600)) {
<> 150:02e0a0aed4ec 492 /* If we were on UART0 but the baud rate is 9600 then switch to the
<> 150:02e0a0aed4ec 493 * LP UART for receive */
<> 150:02e0a0aed4ec 494 deinit_config(obj);
<> 150:02e0a0aed4ec 495 obj->config = SERIAL_CONFIG_UARTLP_RX_UART0_TX;
<> 150:02e0a0aed4ec 496 init_config(obj);
<> 150:02e0a0aed4ec 497 switch_port_config = true;
<> 150:02e0a0aed4ec 498 }
<> 150:02e0a0aed4ec 499
<> 150:02e0a0aed4ec 500 /* Disable UART while writing to control registers */
<> 150:02e0a0aed4ec 501 obj->reg_base->UARTCR &= ~(1 << 0);
<> 150:02e0a0aed4ec 502
<> 150:02e0a0aed4ec 503 if (switch_port_config) {
<> 150:02e0a0aed4ec 504 /* If the port was switched, switch the port configuration also */
<> 150:02e0a0aed4ec 505 if (format_set) {
<> 150:02e0a0aed4ec 506 /* This serial port has been previously set up so switch the
<> 150:02e0a0aed4ec 507 * settings across to this new configuration */
<> 150:02e0a0aed4ec 508 serial_format(obj, data_bits, parity, stop_bits);
<> 150:02e0a0aed4ec 509 }
<> 150:02e0a0aed4ec 510 if (irq_rx_setting != IRQ_NOT_SET) {
<> 150:02e0a0aed4ec 511 /* Do the same for Rx interrupts, if they were set */
<> 150:02e0a0aed4ec 512 serial_irq_set(obj, RxIrq, (irq_rx_setting == IRQ_ON));
<> 150:02e0a0aed4ec 513 }
<> 150:02e0a0aed4ec 514 if (irq_tx_setting != IRQ_NOT_SET) {
<> 150:02e0a0aed4ec 515 /* Do the same for Tx interrupts, if they were set */
<> 150:02e0a0aed4ec 516 serial_irq_set(obj, TxIrq, (irq_tx_setting == IRQ_ON));
<> 150:02e0a0aed4ec 517 }
<> 150:02e0a0aed4ec 518 }
<> 150:02e0a0aed4ec 519
<> 150:02e0a0aed4ec 520 switch (obj->config) {
<> 150:02e0a0aed4ec 521 case SERIAL_CONFIG_UARTLP_RX_UART0_TX:
<> 150:02e0a0aed4ec 522 {
<> 150:02e0a0aed4ec 523 /* Set LP UART to 9600 (numerator 75 (0x4B), denominator 256 (00 == 256)) */
<> 150:02e0a0aed4ec 524 LP_UART_CTRL = (LP_UART_CTRL & ~0xFFFF) | 0x004B;
<> 150:02e0a0aed4ec 525 set_baud(obj, baudrate);
<> 150:02e0a0aed4ec 526 }
<> 150:02e0a0aed4ec 527 break;
<> 150:02e0a0aed4ec 528 case SERIAL_CONFIG_UART0_RX_UART0_TX:
<> 150:02e0a0aed4ec 529 case SERIAL_CONFIG_UART1_RX_UART1_TX:
<> 150:02e0a0aed4ec 530 {
<> 150:02e0a0aed4ec 531 set_baud(obj, baudrate);
<> 150:02e0a0aed4ec 532 }
<> 150:02e0a0aed4ec 533 break;
<> 150:02e0a0aed4ec 534 default:
<> 150:02e0a0aed4ec 535 {
<> 150:02e0a0aed4ec 536 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 537 }
<> 150:02e0a0aed4ec 538 break;
<> 150:02e0a0aed4ec 539 }
<> 150:02e0a0aed4ec 540
<> 150:02e0a0aed4ec 541 /* Enable the UART again */
<> 150:02e0a0aed4ec 542 obj->reg_base->UARTCR |= 1 << 0;
<> 150:02e0a0aed4ec 543
<> 150:02e0a0aed4ec 544 obj->baud_rate = baudrate;
<> 150:02e0a0aed4ec 545 }
<> 150:02e0a0aed4ec 546
<> 150:02e0a0aed4ec 547 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
<> 150:02e0a0aed4ec 548 {
<> 150:02e0a0aed4ec 549 bool lp_also = false;
<> 150:02e0a0aed4ec 550
<> 150:02e0a0aed4ec 551 MBED_ASSERT(data_bits >= MIN_NUM_UART_DATA_BITS);
<> 150:02e0a0aed4ec 552 MBED_ASSERT(data_bits <= MAX_NUM_UART_DATA_BITS);
<> 150:02e0a0aed4ec 553 MBED_ASSERT(stop_bits >= NUM_UART_STOP_BITS_1);
<> 150:02e0a0aed4ec 554 MBED_ASSERT(stop_bits <= NUM_UART_STOP_BITS_2);
<> 150:02e0a0aed4ec 555
<> 150:02e0a0aed4ec 556 /* The LP UART is different to UARTs 0 and 1 so deal with it
<> 150:02e0a0aed4ec 557 * explicitly when required */
<> 150:02e0a0aed4ec 558 if (obj->config == SERIAL_CONFIG_UARTLP_RX_UART0_TX) {
<> 150:02e0a0aed4ec 559 lp_also = true;
<> 150:02e0a0aed4ec 560 }
<> 150:02e0a0aed4ec 561
<> 150:02e0a0aed4ec 562 /* Disable UART while writing to control registers */
<> 150:02e0a0aed4ec 563 obj->reg_base->UARTCR &= ~(1 << 0);
<> 150:02e0a0aed4ec 564
<> 150:02e0a0aed4ec 565 /* Set data bits (bits 5 and 6 of the UART0/1 register, bits 18 and 19 of the LP UART register) */
<> 150:02e0a0aed4ec 566 obj->reg_base->UARTLCR_H = (obj->reg_base->UARTLCR_H & ~(0x03 << 5)) | (REGISTER_DATA_BITS(data_bits) << 5);
<> 150:02e0a0aed4ec 567 if (lp_also) {
<> 150:02e0a0aed4ec 568 LP_UART_CTRL = (LP_UART_CTRL & ~(0x03 << 18)) | (REGISTER_DATA_BITS(data_bits) << 18);
<> 150:02e0a0aed4ec 569 }
<> 150:02e0a0aed4ec 570 obj->format.data_bits = (uint8_t) data_bits;
<> 150:02e0a0aed4ec 571
<> 150:02e0a0aed4ec 572 /* Set stop bits (bit 7 of the UART0/1 register) (there is no such setting for the LP UART) */
<> 150:02e0a0aed4ec 573 if (stop_bits == NUM_UART_STOP_BITS_1) {
<> 150:02e0a0aed4ec 574 /* Clear 2-stop-bits bit */
<> 150:02e0a0aed4ec 575 obj->reg_base->UARTLCR_H &= ~(1 << 7);
<> 150:02e0a0aed4ec 576 } else {
<> 150:02e0a0aed4ec 577 /* Set 2-stop-bits bit */
<> 150:02e0a0aed4ec 578 obj->reg_base->UARTLCR_H |= 1 << 7;
<> 150:02e0a0aed4ec 579 }
<> 150:02e0a0aed4ec 580 obj->format.stop_bits = (uint8_t) stop_bits;
<> 150:02e0a0aed4ec 581
<> 150:02e0a0aed4ec 582 /* Set parity */
<> 150:02e0a0aed4ec 583 switch (parity) {
<> 150:02e0a0aed4ec 584 case ParityNone:
<> 150:02e0a0aed4ec 585 {
<> 150:02e0a0aed4ec 586 /* Disable parity */
<> 150:02e0a0aed4ec 587 obj->reg_base->UARTLCR_H &= ~0x02;
<> 150:02e0a0aed4ec 588 if (lp_also)
<> 150:02e0a0aed4ec 589 {
<> 150:02e0a0aed4ec 590 LP_UART_CTRL &= ~(1 << 24);
<> 150:02e0a0aed4ec 591 }
<> 150:02e0a0aed4ec 592 }
<> 150:02e0a0aed4ec 593 break;
<> 150:02e0a0aed4ec 594 case ParityOdd:
<> 150:02e0a0aed4ec 595 {
<> 150:02e0a0aed4ec 596 /* Set even bit and enable parity */
<> 150:02e0a0aed4ec 597 obj->reg_base->UARTLCR_H = (obj->reg_base->UARTLCR_H | (1 << 3)) | (1 << 2);
<> 150:02e0a0aed4ec 598 if (lp_also)
<> 150:02e0a0aed4ec 599 {
<> 150:02e0a0aed4ec 600 LP_UART_CTRL |= (1 << 24) | (1 << 25);
<> 150:02e0a0aed4ec 601 }
<> 150:02e0a0aed4ec 602 }
<> 150:02e0a0aed4ec 603 break;
<> 150:02e0a0aed4ec 604 case ParityEven:
<> 150:02e0a0aed4ec 605 {
<> 150:02e0a0aed4ec 606 /* Clear even bit and enable parity */
<> 150:02e0a0aed4ec 607 obj->reg_base->UARTLCR_H = (obj->reg_base->UARTLCR_H & ~(1 << 3)) | (1 << 2);
<> 150:02e0a0aed4ec 608 if (lp_also)
<> 150:02e0a0aed4ec 609 {
<> 150:02e0a0aed4ec 610 LP_UART_CTRL &= ~(1 << 25);
<> 150:02e0a0aed4ec 611 LP_UART_CTRL |= 1 << 24;
<> 150:02e0a0aed4ec 612 }
<> 150:02e0a0aed4ec 613 }
<> 150:02e0a0aed4ec 614 break;
<> 150:02e0a0aed4ec 615 default:
<> 150:02e0a0aed4ec 616 {
<> 150:02e0a0aed4ec 617 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 618 }
<> 150:02e0a0aed4ec 619 break;
<> 150:02e0a0aed4ec 620 }
<> 150:02e0a0aed4ec 621
<> 150:02e0a0aed4ec 622 /* Enable the UART again */
<> 150:02e0a0aed4ec 623 obj->reg_base->UARTCR |= 1 << 0;
<> 150:02e0a0aed4ec 624
<> 150:02e0a0aed4ec 625 obj->format.parity = (uint8_t) parity;
<> 150:02e0a0aed4ec 626 obj->format_set = true;
<> 150:02e0a0aed4ec 627 }
<> 150:02e0a0aed4ec 628
<> 150:02e0a0aed4ec 629 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 630 * MBED API CALLS: INTERRUPT FUNCTIONS
<> 150:02e0a0aed4ec 631 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 632
<> 150:02e0a0aed4ec 633 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
<> 150:02e0a0aed4ec 634 {
<> 150:02e0a0aed4ec 635 irq_handler = handler;
<> 150:02e0a0aed4ec 636 serial_irq_ids[obj->index] = id;
<> 150:02e0a0aed4ec 637 }
<> 150:02e0a0aed4ec 638
<> 150:02e0a0aed4ec 639 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
<> 150:02e0a0aed4ec 640 {
<> 150:02e0a0aed4ec 641 bool lp_also = false;
<> 150:02e0a0aed4ec 642
<> 150:02e0a0aed4ec 643 if (obj->config == SERIAL_CONFIG_UARTLP_RX_UART0_TX) {
<> 150:02e0a0aed4ec 644 lp_also = true;
<> 150:02e0a0aed4ec 645 }
<> 150:02e0a0aed4ec 646
<> 150:02e0a0aed4ec 647 /* Disable UART while writing to control registers */
<> 150:02e0a0aed4ec 648 obj->reg_base->UARTCR &= ~(1 << 0);
<> 150:02e0a0aed4ec 649
<> 150:02e0a0aed4ec 650 if (enable) {
<> 150:02e0a0aed4ec 651 switch (irq) {
<> 150:02e0a0aed4ec 652 case RxIrq:
<> 150:02e0a0aed4ec 653 {
<> 150:02e0a0aed4ec 654 /* Bit 4 for Rx and bit 6 for Rx Timeout */
<> 150:02e0a0aed4ec 655 obj->reg_base->UARTIMSC |= (1 << 4) | (1 << 6);
<> 150:02e0a0aed4ec 656 if (lp_also)
<> 150:02e0a0aed4ec 657 {
<> 150:02e0a0aed4ec 658 /* "Word Received" IRQ */
<> 150:02e0a0aed4ec 659 LP_UART_CTRL |= 1 << 23;
<> 150:02e0a0aed4ec 660 }
<> 150:02e0a0aed4ec 661 obj->irq_rx_setting = IRQ_ON;
<> 150:02e0a0aed4ec 662 irq_enable(obj);
<> 150:02e0a0aed4ec 663 }
<> 150:02e0a0aed4ec 664 break;
<> 150:02e0a0aed4ec 665 case TxIrq:
<> 150:02e0a0aed4ec 666 {
<> 150:02e0a0aed4ec 667 /* Bit 5 */
<> 150:02e0a0aed4ec 668 obj->reg_base->UARTIMSC |= 1 << 5;
<> 150:02e0a0aed4ec 669 obj->irq_tx_setting = IRQ_ON;
<> 150:02e0a0aed4ec 670 irq_enable(obj);
<> 150:02e0a0aed4ec 671 }
<> 150:02e0a0aed4ec 672 break;
<> 150:02e0a0aed4ec 673 default:
<> 150:02e0a0aed4ec 674 {
<> 150:02e0a0aed4ec 675 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 676 }
<> 150:02e0a0aed4ec 677 break;
<> 150:02e0a0aed4ec 678 }
<> 150:02e0a0aed4ec 679 } else {
<> 150:02e0a0aed4ec 680 switch (irq) {
<> 150:02e0a0aed4ec 681 case RxIrq:
<> 150:02e0a0aed4ec 682 {
<> 150:02e0a0aed4ec 683 /* Bit 4 for Rx and bit 6 for Rx Timeout */
<> 150:02e0a0aed4ec 684 obj->reg_base->UARTIMSC &= ~((1 << 4) | (1 << 6));
<> 150:02e0a0aed4ec 685 if (lp_also)
<> 150:02e0a0aed4ec 686 {
<> 150:02e0a0aed4ec 687 /* "Word Received" IRQ */
<> 150:02e0a0aed4ec 688 LP_UART_CTRL &= ~(1 << 23);
<> 150:02e0a0aed4ec 689 }
<> 150:02e0a0aed4ec 690 obj->irq_rx_setting = IRQ_OFF;
<> 150:02e0a0aed4ec 691 }
<> 150:02e0a0aed4ec 692 break;
<> 150:02e0a0aed4ec 693 case TxIrq:
<> 150:02e0a0aed4ec 694 {
<> 150:02e0a0aed4ec 695 /* Bit 5 */
<> 150:02e0a0aed4ec 696 obj->reg_base->UARTIMSC &= ~(1 << 5);
<> 150:02e0a0aed4ec 697 obj->irq_tx_setting = IRQ_OFF;
<> 150:02e0a0aed4ec 698 }
<> 150:02e0a0aed4ec 699 break;
<> 150:02e0a0aed4ec 700 default:
<> 150:02e0a0aed4ec 701 {
<> 150:02e0a0aed4ec 702 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 703 }
<> 150:02e0a0aed4ec 704 break;
<> 150:02e0a0aed4ec 705 }
<> 150:02e0a0aed4ec 706
<> 150:02e0a0aed4ec 707 if ((obj->irq_rx_setting == IRQ_OFF) && (obj->irq_tx_setting == IRQ_OFF)) {
<> 150:02e0a0aed4ec 708 irq_disable(obj);
<> 150:02e0a0aed4ec 709 }
<> 150:02e0a0aed4ec 710 }
<> 150:02e0a0aed4ec 711
<> 150:02e0a0aed4ec 712 /* Enable the UART again */
<> 150:02e0a0aed4ec 713 obj->reg_base->UARTCR |= 1 << 0;
<> 150:02e0a0aed4ec 714 }
<> 150:02e0a0aed4ec 715
<> 150:02e0a0aed4ec 716 /* ----------------------------------------------------------------
<> 150:02e0a0aed4ec 717 * MBED API CALLS: TRANSMIT AND RECEIVE FUNCTIONS
<> 150:02e0a0aed4ec 718 * ----------------------------------------------------------------*/
<> 150:02e0a0aed4ec 719
<> 150:02e0a0aed4ec 720 int serial_getc(serial_t *obj)
<> 150:02e0a0aed4ec 721 {
<> 150:02e0a0aed4ec 722 uint8_t data = 0;
<> 150:02e0a0aed4ec 723
<> 150:02e0a0aed4ec 724 /* Block until there is data to read */
<> 150:02e0a0aed4ec 725 while (!serial_readable(obj)) {}
<> 150:02e0a0aed4ec 726
<> 150:02e0a0aed4ec 727 /* Read the data */
<> 150:02e0a0aed4ec 728 switch (obj->config) {
<> 150:02e0a0aed4ec 729 case SERIAL_CONFIG_UARTLP_RX_UART0_TX:
<> 150:02e0a0aed4ec 730 {
<> 150:02e0a0aed4ec 731 data = (uint8_t) LP_UART_DATA;
<> 150:02e0a0aed4ec 732 }
<> 150:02e0a0aed4ec 733 break;
<> 150:02e0a0aed4ec 734 case SERIAL_CONFIG_UART0_RX_UART0_TX:
<> 150:02e0a0aed4ec 735 case SERIAL_CONFIG_UART1_RX_UART1_TX:
<> 150:02e0a0aed4ec 736 {
<> 150:02e0a0aed4ec 737 data = (uint8_t) obj->reg_base->UARTDR;
<> 150:02e0a0aed4ec 738 }
<> 150:02e0a0aed4ec 739 break;
<> 150:02e0a0aed4ec 740 default:
<> 150:02e0a0aed4ec 741 {
<> 150:02e0a0aed4ec 742 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 743 }
<> 150:02e0a0aed4ec 744 break;
<> 150:02e0a0aed4ec 745 }
<> 150:02e0a0aed4ec 746
<> 150:02e0a0aed4ec 747 return (int) data;
<> 150:02e0a0aed4ec 748 }
<> 150:02e0a0aed4ec 749
<> 150:02e0a0aed4ec 750 void serial_putc(serial_t *obj, int c)
<> 150:02e0a0aed4ec 751 {
<> 150:02e0a0aed4ec 752 /* Block until there is room to write */
<> 150:02e0a0aed4ec 753 while (!serial_writable(obj)) {}
<> 150:02e0a0aed4ec 754
<> 150:02e0a0aed4ec 755 /* Write the data */
<> 150:02e0a0aed4ec 756 obj->reg_base->UARTDR = (uint8_t) c;
<> 150:02e0a0aed4ec 757 }
<> 150:02e0a0aed4ec 758
<> 150:02e0a0aed4ec 759 int serial_readable(serial_t *obj)
<> 150:02e0a0aed4ec 760 {
<> 150:02e0a0aed4ec 761 bool readable = false;
<> 150:02e0a0aed4ec 762
<> 150:02e0a0aed4ec 763 switch (obj->config) {
<> 150:02e0a0aed4ec 764 case SERIAL_CONFIG_UARTLP_RX_UART0_TX:
<> 150:02e0a0aed4ec 765 {
<> 150:02e0a0aed4ec 766 /* Check the status register, bits 8 to 10 indicate
<> 150:02e0a0aed4ec 767 * the number of Rx bytes (make sure it's the status
<> 150:02e0a0aed4ec 768 * register not the data register as a read from that
<> 150:02e0a0aed4ec 769 * register would clear the Rx interrupt) */
<> 150:02e0a0aed4ec 770 readable = (((LP_UART_STATUS >> 8) & 0x07) != 0);
<> 150:02e0a0aed4ec 771 }
<> 150:02e0a0aed4ec 772 break;
<> 150:02e0a0aed4ec 773 case SERIAL_CONFIG_UART0_RX_UART0_TX:
<> 150:02e0a0aed4ec 774 case SERIAL_CONFIG_UART1_RX_UART1_TX:
<> 150:02e0a0aed4ec 775 {
<> 150:02e0a0aed4ec 776 /* Check the Rx FIFO Empty bit */
<> 150:02e0a0aed4ec 777 readable = ((obj->reg_base->UARTFR & (1 << 4)) != (1 << 4));
<> 150:02e0a0aed4ec 778 }
<> 150:02e0a0aed4ec 779 break;
<> 150:02e0a0aed4ec 780 default:
<> 150:02e0a0aed4ec 781 {
<> 150:02e0a0aed4ec 782 MBED_ASSERT(false);
<> 150:02e0a0aed4ec 783 }
<> 150:02e0a0aed4ec 784 break;
<> 150:02e0a0aed4ec 785 }
<> 150:02e0a0aed4ec 786
<> 150:02e0a0aed4ec 787 return (int) readable;
<> 150:02e0a0aed4ec 788 }
<> 150:02e0a0aed4ec 789
<> 150:02e0a0aed4ec 790 int serial_writable(serial_t *obj)
<> 150:02e0a0aed4ec 791 {
<> 150:02e0a0aed4ec 792 /* Check the "UART TX FIFO full" bit:
<> 150:02e0a0aed4ec 793 * only if this is 0 can we transmit */
<> 150:02e0a0aed4ec 794 return (obj->reg_base->UARTFR & (1 << 5)) != (1 << 5);
<> 150:02e0a0aed4ec 795 }
<> 150:02e0a0aed4ec 796
<> 150:02e0a0aed4ec 797 void serial_break_set(serial_t *obj)
<> 150:02e0a0aed4ec 798 {
<> 150:02e0a0aed4ec 799 /* Disable UART while writing to control registers */
<> 150:02e0a0aed4ec 800 obj->reg_base->UARTCR &= ~(1 << 0);
<> 150:02e0a0aed4ec 801
<> 150:02e0a0aed4ec 802 /* Set bit 1 of the line control register */
<> 150:02e0a0aed4ec 803 obj->reg_base->UARTLCR_H |= 1 << 0;
<> 150:02e0a0aed4ec 804
<> 150:02e0a0aed4ec 805 /* Enable the UART again */
<> 150:02e0a0aed4ec 806 obj->reg_base->UARTCR |= 1 << 0;
<> 150:02e0a0aed4ec 807 }
<> 150:02e0a0aed4ec 808
<> 150:02e0a0aed4ec 809 void serial_break_clear(serial_t *obj)
<> 150:02e0a0aed4ec 810 {
<> 150:02e0a0aed4ec 811 /* Disable UART while writing to control registers */
<> 150:02e0a0aed4ec 812 obj->reg_base->UARTCR &= ~(1 << 0);
<> 150:02e0a0aed4ec 813
<> 150:02e0a0aed4ec 814 /* Clear bit 1 of the line control register */
<> 150:02e0a0aed4ec 815 obj->reg_base->UARTLCR_H &= ~(1 << 0);
<> 150:02e0a0aed4ec 816
<> 150:02e0a0aed4ec 817 /* Enable the UART again */
<> 150:02e0a0aed4ec 818 obj->reg_base->UARTCR |= 1 << 0;
<> 150:02e0a0aed4ec 819 }