Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

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