Gordon Craig / mbed-dev

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Wed Jun 21 17:46:44 2017 +0100
Revision:
167:e84263d55307
Parent:
154:37f96f9d4de2
This updates the lib to the mbed lib v 145

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 154:37f96f9d4de2 1 /* mbed Microcontroller Library
<> 154:37f96f9d4de2 2 * Copyright (c) 2006-2013 ARM Limited
<> 154:37f96f9d4de2 3 *
<> 154:37f96f9d4de2 4 * Licensed under the Apache License, Version 2.0 (the "License");
<> 154:37f96f9d4de2 5 * you may not use this file except in compliance with the License.
<> 154:37f96f9d4de2 6 * You may obtain a copy of the License at
<> 154:37f96f9d4de2 7 *
<> 154:37f96f9d4de2 8 * http://www.apache.org/licenses/LICENSE-2.0
<> 154:37f96f9d4de2 9 *
<> 154:37f96f9d4de2 10 * Unless required by applicable law or agreed to in writing, software
<> 154:37f96f9d4de2 11 * distributed under the License is distributed on an "AS IS" BASIS,
<> 154:37f96f9d4de2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 154:37f96f9d4de2 13 * See the License for the specific language governing permissions and
<> 154:37f96f9d4de2 14 * limitations under the License.
<> 154:37f96f9d4de2 15 */
<> 154:37f96f9d4de2 16 #include "serial_api.h"
<> 154:37f96f9d4de2 17
<> 154:37f96f9d4de2 18 #if DEVICE_SERIAL
<> 154:37f96f9d4de2 19
<> 154:37f96f9d4de2 20 // math.h required for floating point operations for baud rate calculation
<> 154:37f96f9d4de2 21 #include <math.h>
<> 154:37f96f9d4de2 22 #include "mbed_assert.h"
<> 154:37f96f9d4de2 23
<> 154:37f96f9d4de2 24 #include <string.h>
<> 154:37f96f9d4de2 25
<> 154:37f96f9d4de2 26 #include "cmsis.h"
<> 154:37f96f9d4de2 27 #include "pinmap.h"
<> 154:37f96f9d4de2 28 #include "fsl_lpuart.h"
<> 154:37f96f9d4de2 29 #include "peripheral_clock_defines.h"
<> 154:37f96f9d4de2 30 #include "PeripheralPins.h"
<> 154:37f96f9d4de2 31 #include "fsl_clock_config.h"
<> 154:37f96f9d4de2 32
<> 154:37f96f9d4de2 33 static uint32_t serial_irq_ids[FSL_FEATURE_SOC_LPUART_COUNT] = {0};
<> 154:37f96f9d4de2 34 static uart_irq_handler irq_handler;
<> 154:37f96f9d4de2 35 /* Array of UART peripheral base address. */
<> 154:37f96f9d4de2 36 static LPUART_Type *const uart_addrs[] = LPUART_BASE_PTRS;
AnnaBridge 167:e84263d55307 37 /* LPUART bus clock frequency */
AnnaBridge 167:e84263d55307 38 static uint32_t lpuart_src_freq;
<> 154:37f96f9d4de2 39
<> 154:37f96f9d4de2 40 int stdio_uart_inited = 0;
<> 154:37f96f9d4de2 41 serial_t stdio_uart;
<> 154:37f96f9d4de2 42
<> 154:37f96f9d4de2 43 void serial_init(serial_t *obj, PinName tx, PinName rx)
<> 154:37f96f9d4de2 44 {
<> 154:37f96f9d4de2 45 uint32_t uart_tx = pinmap_peripheral(tx, PinMap_UART_TX);
<> 154:37f96f9d4de2 46 uint32_t uart_rx = pinmap_peripheral(rx, PinMap_UART_RX);
<> 154:37f96f9d4de2 47 obj->index = pinmap_merge(uart_tx, uart_rx);
<> 154:37f96f9d4de2 48 MBED_ASSERT((int)obj->index != NC);
<> 154:37f96f9d4de2 49
AnnaBridge 167:e84263d55307 50 /* Set the UART clock source */
AnnaBridge 167:e84263d55307 51 serial_clock_init();
AnnaBridge 167:e84263d55307 52
AnnaBridge 167:e84263d55307 53 // since the LPuart initialization depends very much on the source clock and its
AnnaBridge 167:e84263d55307 54 // frequency, we do a check here and retrieve the frequency accordingly
AnnaBridge 167:e84263d55307 55 switch (SIM->SOPT2 & SIM_SOPT2_LPUARTSRC_MASK) {
AnnaBridge 167:e84263d55307 56 case SIM_SOPT2_LPUARTSRC(3U): {
AnnaBridge 167:e84263d55307 57 lpuart_src_freq = CLOCK_GetInternalRefClkFreq();
AnnaBridge 167:e84263d55307 58 break;
AnnaBridge 167:e84263d55307 59 }
AnnaBridge 167:e84263d55307 60 case SIM_SOPT2_LPUARTSRC(2U): {
AnnaBridge 167:e84263d55307 61 lpuart_src_freq = CLOCK_GetOsc0ErClkFreq();
AnnaBridge 167:e84263d55307 62 break;
AnnaBridge 167:e84263d55307 63 }
AnnaBridge 167:e84263d55307 64 case SIM_SOPT2_LPUARTSRC(1U): {
AnnaBridge 167:e84263d55307 65 lpuart_src_freq = CLOCK_GetPllFllSelClkFreq();
AnnaBridge 167:e84263d55307 66 break;
AnnaBridge 167:e84263d55307 67 }
AnnaBridge 167:e84263d55307 68 default: {
AnnaBridge 167:e84263d55307 69 lpuart_src_freq = CLOCK_GetOsc0ErClkFreq();
AnnaBridge 167:e84263d55307 70 break;
AnnaBridge 167:e84263d55307 71 }
AnnaBridge 167:e84263d55307 72 }
<> 154:37f96f9d4de2 73
<> 154:37f96f9d4de2 74 lpuart_config_t config;
<> 154:37f96f9d4de2 75 LPUART_GetDefaultConfig(&config);
<> 154:37f96f9d4de2 76 config.baudRate_Bps = 9600;
<> 154:37f96f9d4de2 77 config.enableTx = false;
<> 154:37f96f9d4de2 78 config.enableRx = false;
<> 154:37f96f9d4de2 79
AnnaBridge 167:e84263d55307 80 LPUART_Init(uart_addrs[obj->index], &config, lpuart_src_freq);
<> 154:37f96f9d4de2 81
<> 154:37f96f9d4de2 82 pinmap_pinout(tx, PinMap_UART_TX);
<> 154:37f96f9d4de2 83 pinmap_pinout(rx, PinMap_UART_RX);
<> 154:37f96f9d4de2 84
<> 154:37f96f9d4de2 85 if (tx != NC) {
<> 154:37f96f9d4de2 86 LPUART_EnableTx(uart_addrs[obj->index], true);
<> 154:37f96f9d4de2 87 pin_mode(tx, PullUp);
<> 154:37f96f9d4de2 88 }
<> 154:37f96f9d4de2 89 if (rx != NC) {
<> 154:37f96f9d4de2 90 LPUART_EnableRx(uart_addrs[obj->index], true);
<> 154:37f96f9d4de2 91 pin_mode(rx, PullUp);
<> 154:37f96f9d4de2 92 }
<> 154:37f96f9d4de2 93
<> 154:37f96f9d4de2 94 if (obj->index == STDIO_UART) {
<> 154:37f96f9d4de2 95 stdio_uart_inited = 1;
<> 154:37f96f9d4de2 96 memcpy(&stdio_uart, obj, sizeof(serial_t));
<> 154:37f96f9d4de2 97 }
<> 154:37f96f9d4de2 98 }
<> 154:37f96f9d4de2 99
<> 154:37f96f9d4de2 100 void serial_free(serial_t *obj)
<> 154:37f96f9d4de2 101 {
<> 154:37f96f9d4de2 102 LPUART_Deinit(uart_addrs[obj->index]);
<> 154:37f96f9d4de2 103 serial_irq_ids[obj->index] = 0;
<> 154:37f96f9d4de2 104 }
<> 154:37f96f9d4de2 105
<> 154:37f96f9d4de2 106 void serial_baud(serial_t *obj, int baudrate)
<> 154:37f96f9d4de2 107 {
AnnaBridge 167:e84263d55307 108 LPUART_SetBaudRate(uart_addrs[obj->index], (uint32_t)baudrate, lpuart_src_freq);
<> 154:37f96f9d4de2 109 }
<> 154:37f96f9d4de2 110
<> 154:37f96f9d4de2 111 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
<> 154:37f96f9d4de2 112 {
<> 154:37f96f9d4de2 113 LPUART_Type *base = uart_addrs[obj->index];
<> 154:37f96f9d4de2 114 uint8_t temp;
<> 154:37f96f9d4de2 115 /* Set bit count and parity mode. */
<> 154:37f96f9d4de2 116 temp = base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK);
<> 154:37f96f9d4de2 117 if (parity != ParityNone)
<> 154:37f96f9d4de2 118 {
<> 154:37f96f9d4de2 119 /* Enable Parity */
<> 154:37f96f9d4de2 120 temp |= (LPUART_CTRL_PE_MASK | LPUART_CTRL_M_MASK);
<> 154:37f96f9d4de2 121 if (parity == ParityOdd) {
<> 154:37f96f9d4de2 122 temp |= LPUART_CTRL_PT_MASK;
<> 154:37f96f9d4de2 123 } else if (parity == ParityEven) {
<> 154:37f96f9d4de2 124 // PT=0 so nothing more to do
<> 154:37f96f9d4de2 125 } else {
<> 154:37f96f9d4de2 126 // Hardware does not support forced parity
<> 154:37f96f9d4de2 127 MBED_ASSERT(0);
<> 154:37f96f9d4de2 128 }
<> 154:37f96f9d4de2 129 }
<> 154:37f96f9d4de2 130 base->CTRL = temp;
<> 154:37f96f9d4de2 131
<> 154:37f96f9d4de2 132 #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
<> 154:37f96f9d4de2 133 /* set stop bit per char */
<> 154:37f96f9d4de2 134 temp = base->BAUD & ~LPUART_BAUD_SBNS_MASK;
<> 154:37f96f9d4de2 135 base->BAUD = temp | LPUART_BAUD_SBNS((uint8_t)--stop_bits);
<> 154:37f96f9d4de2 136 #endif
<> 154:37f96f9d4de2 137 }
<> 154:37f96f9d4de2 138
<> 154:37f96f9d4de2 139 /******************************************************************************
<> 154:37f96f9d4de2 140 * INTERRUPTS HANDLING
<> 154:37f96f9d4de2 141 ******************************************************************************/
<> 154:37f96f9d4de2 142 static inline void uart_irq(uint32_t transmit_empty, uint32_t receive_full, uint32_t index)
<> 154:37f96f9d4de2 143 {
<> 154:37f96f9d4de2 144 LPUART_Type *base = uart_addrs[index];
<> 154:37f96f9d4de2 145
<> 154:37f96f9d4de2 146 /* If RX overrun. */
<> 154:37f96f9d4de2 147 if (LPUART_STAT_OR_MASK & base->STAT)
<> 154:37f96f9d4de2 148 {
<> 154:37f96f9d4de2 149 /* Read base->D, otherwise the RX does not work. */
<> 154:37f96f9d4de2 150 (void)base->DATA;
<> 154:37f96f9d4de2 151 LPUART_ClearStatusFlags(base, kLPUART_RxOverrunFlag);
<> 154:37f96f9d4de2 152 }
<> 154:37f96f9d4de2 153
<> 154:37f96f9d4de2 154 if (serial_irq_ids[index] != 0) {
<> 154:37f96f9d4de2 155 if (transmit_empty)
<> 154:37f96f9d4de2 156 irq_handler(serial_irq_ids[index], TxIrq);
<> 154:37f96f9d4de2 157
<> 154:37f96f9d4de2 158 if (receive_full)
<> 154:37f96f9d4de2 159 irq_handler(serial_irq_ids[index], RxIrq);
<> 154:37f96f9d4de2 160 }
<> 154:37f96f9d4de2 161 }
<> 154:37f96f9d4de2 162
<> 154:37f96f9d4de2 163 void uart0_irq()
<> 154:37f96f9d4de2 164 {
<> 154:37f96f9d4de2 165 uint32_t status_flags = LPUART0->STAT;
<> 154:37f96f9d4de2 166 uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 0);
<> 154:37f96f9d4de2 167 }
<> 154:37f96f9d4de2 168
<> 154:37f96f9d4de2 169 void uart1_irq()
<> 154:37f96f9d4de2 170 {
<> 154:37f96f9d4de2 171 uint32_t status_flags = LPUART1->STAT;
<> 154:37f96f9d4de2 172 uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 1);
<> 154:37f96f9d4de2 173 }
<> 154:37f96f9d4de2 174
<> 154:37f96f9d4de2 175 void uart2_irq()
<> 154:37f96f9d4de2 176 {
<> 154:37f96f9d4de2 177 uint32_t status_flags = LPUART2->STAT;
<> 154:37f96f9d4de2 178 uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 2);
<> 154:37f96f9d4de2 179 }
<> 154:37f96f9d4de2 180
<> 154:37f96f9d4de2 181 void uart3_irq()
<> 154:37f96f9d4de2 182 {
<> 154:37f96f9d4de2 183 uint32_t status_flags = LPUART3->STAT;
<> 154:37f96f9d4de2 184 uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 3);
<> 154:37f96f9d4de2 185 }
<> 154:37f96f9d4de2 186
<> 154:37f96f9d4de2 187 void uart4_irq()
<> 154:37f96f9d4de2 188 {
<> 154:37f96f9d4de2 189 uint32_t status_flags = LPUART4->STAT;
<> 154:37f96f9d4de2 190 uart_irq((status_flags & kLPUART_TxDataRegEmptyFlag), (status_flags & kLPUART_RxDataRegFullFlag), 4);
<> 154:37f96f9d4de2 191 }
<> 154:37f96f9d4de2 192
<> 154:37f96f9d4de2 193 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
<> 154:37f96f9d4de2 194 {
<> 154:37f96f9d4de2 195 irq_handler = handler;
<> 154:37f96f9d4de2 196 serial_irq_ids[obj->index] = id;
<> 154:37f96f9d4de2 197 }
<> 154:37f96f9d4de2 198
<> 154:37f96f9d4de2 199 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
<> 154:37f96f9d4de2 200 {
<> 154:37f96f9d4de2 201 IRQn_Type uart_irqs[] = LPUART_RX_TX_IRQS;
<> 154:37f96f9d4de2 202 uint32_t vector = 0;
<> 154:37f96f9d4de2 203
<> 154:37f96f9d4de2 204 switch (obj->index) {
<> 154:37f96f9d4de2 205 case 0:
<> 154:37f96f9d4de2 206 vector = (uint32_t)&uart0_irq;
<> 154:37f96f9d4de2 207 break;
<> 154:37f96f9d4de2 208 case 1:
<> 154:37f96f9d4de2 209 vector = (uint32_t)&uart1_irq;
<> 154:37f96f9d4de2 210 break;
<> 154:37f96f9d4de2 211 case 2:
<> 154:37f96f9d4de2 212 vector = (uint32_t)&uart2_irq;
<> 154:37f96f9d4de2 213 break;
<> 154:37f96f9d4de2 214 case 3:
<> 154:37f96f9d4de2 215 vector = (uint32_t)&uart3_irq;
<> 154:37f96f9d4de2 216 break;
<> 154:37f96f9d4de2 217 case 4:
<> 154:37f96f9d4de2 218 vector = (uint32_t)&uart4_irq;
<> 154:37f96f9d4de2 219 break;
<> 154:37f96f9d4de2 220 default:
<> 154:37f96f9d4de2 221 break;
<> 154:37f96f9d4de2 222 }
<> 154:37f96f9d4de2 223
<> 154:37f96f9d4de2 224 if (enable) {
<> 154:37f96f9d4de2 225 switch (irq) {
<> 154:37f96f9d4de2 226 case RxIrq:
<> 154:37f96f9d4de2 227 LPUART_EnableInterrupts(uart_addrs[obj->index], kLPUART_RxDataRegFullInterruptEnable);
<> 154:37f96f9d4de2 228 break;
<> 154:37f96f9d4de2 229 case TxIrq:
<> 154:37f96f9d4de2 230 LPUART_EnableInterrupts(uart_addrs[obj->index], kLPUART_TxDataRegEmptyInterruptEnable);
<> 154:37f96f9d4de2 231 break;
<> 154:37f96f9d4de2 232 default:
<> 154:37f96f9d4de2 233 break;
<> 154:37f96f9d4de2 234 }
<> 154:37f96f9d4de2 235 NVIC_SetVector(uart_irqs[obj->index], vector);
<> 154:37f96f9d4de2 236 NVIC_EnableIRQ(uart_irqs[obj->index]);
<> 154:37f96f9d4de2 237
<> 154:37f96f9d4de2 238 } else { // disable
<> 154:37f96f9d4de2 239 int all_disabled = 0;
<> 154:37f96f9d4de2 240 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
<> 154:37f96f9d4de2 241 switch (irq) {
<> 154:37f96f9d4de2 242 case RxIrq:
<> 154:37f96f9d4de2 243 LPUART_DisableInterrupts(uart_addrs[obj->index], kLPUART_RxDataRegFullInterruptEnable);
<> 154:37f96f9d4de2 244 break;
<> 154:37f96f9d4de2 245 case TxIrq:
<> 154:37f96f9d4de2 246 LPUART_DisableInterrupts(uart_addrs[obj->index], kLPUART_TxDataRegEmptyInterruptEnable);
<> 154:37f96f9d4de2 247 break;
<> 154:37f96f9d4de2 248 default:
<> 154:37f96f9d4de2 249 break;
<> 154:37f96f9d4de2 250 }
<> 154:37f96f9d4de2 251 switch (other_irq) {
<> 154:37f96f9d4de2 252 case RxIrq:
<> 154:37f96f9d4de2 253 all_disabled = ((LPUART_GetEnabledInterrupts(uart_addrs[obj->index]) & kLPUART_RxDataRegFullInterruptEnable) == 0);
<> 154:37f96f9d4de2 254 break;
<> 154:37f96f9d4de2 255 case TxIrq:
<> 154:37f96f9d4de2 256 all_disabled = ((LPUART_GetEnabledInterrupts(uart_addrs[obj->index]) & kLPUART_TxDataRegEmptyInterruptEnable) == 0);
<> 154:37f96f9d4de2 257 break;
<> 154:37f96f9d4de2 258 default:
<> 154:37f96f9d4de2 259 break;
<> 154:37f96f9d4de2 260 }
<> 154:37f96f9d4de2 261 if (all_disabled)
<> 154:37f96f9d4de2 262 NVIC_DisableIRQ(uart_irqs[obj->index]);
<> 154:37f96f9d4de2 263 }
<> 154:37f96f9d4de2 264 }
<> 154:37f96f9d4de2 265
<> 154:37f96f9d4de2 266 int serial_getc(serial_t *obj)
<> 154:37f96f9d4de2 267 {
<> 154:37f96f9d4de2 268 uint8_t data;
<> 154:37f96f9d4de2 269
<> 154:37f96f9d4de2 270 LPUART_ReadBlocking(uart_addrs[obj->index], &data, 1);
<> 154:37f96f9d4de2 271 return data;
<> 154:37f96f9d4de2 272 }
<> 154:37f96f9d4de2 273
<> 154:37f96f9d4de2 274 void serial_putc(serial_t *obj, int c)
<> 154:37f96f9d4de2 275 {
<> 154:37f96f9d4de2 276 while (!serial_writable(obj));
<> 154:37f96f9d4de2 277 LPUART_WriteByte(uart_addrs[obj->index], (uint8_t)c);
<> 154:37f96f9d4de2 278 }
<> 154:37f96f9d4de2 279
<> 154:37f96f9d4de2 280 int serial_readable(serial_t *obj)
<> 154:37f96f9d4de2 281 {
<> 154:37f96f9d4de2 282 uint32_t status_flags = LPUART_GetStatusFlags(uart_addrs[obj->index]);
<> 154:37f96f9d4de2 283 if (status_flags & kLPUART_RxOverrunFlag)
<> 154:37f96f9d4de2 284 LPUART_ClearStatusFlags(uart_addrs[obj->index], kLPUART_RxOverrunFlag);
<> 154:37f96f9d4de2 285 return (status_flags & kLPUART_RxDataRegFullFlag);
<> 154:37f96f9d4de2 286 }
<> 154:37f96f9d4de2 287
<> 154:37f96f9d4de2 288 int serial_writable(serial_t *obj)
<> 154:37f96f9d4de2 289 {
<> 154:37f96f9d4de2 290 uint32_t status_flags = LPUART_GetStatusFlags(uart_addrs[obj->index]);
<> 154:37f96f9d4de2 291 if (status_flags & kLPUART_RxOverrunFlag)
<> 154:37f96f9d4de2 292 LPUART_ClearStatusFlags(uart_addrs[obj->index], kLPUART_RxOverrunFlag);
<> 154:37f96f9d4de2 293 return (status_flags & kLPUART_TxDataRegEmptyFlag);
<> 154:37f96f9d4de2 294 }
<> 154:37f96f9d4de2 295
<> 154:37f96f9d4de2 296 void serial_clear(serial_t *obj)
<> 154:37f96f9d4de2 297 {
<> 154:37f96f9d4de2 298 }
<> 154:37f96f9d4de2 299
<> 154:37f96f9d4de2 300 void serial_pinout_tx(PinName tx)
<> 154:37f96f9d4de2 301 {
<> 154:37f96f9d4de2 302 pinmap_pinout(tx, PinMap_UART_TX);
<> 154:37f96f9d4de2 303 }
<> 154:37f96f9d4de2 304
<> 154:37f96f9d4de2 305 void serial_break_set(serial_t *obj)
<> 154:37f96f9d4de2 306 {
<> 154:37f96f9d4de2 307 uart_addrs[obj->index]->CTRL |= LPUART_CTRL_SBK_MASK;
<> 154:37f96f9d4de2 308 }
<> 154:37f96f9d4de2 309
<> 154:37f96f9d4de2 310 void serial_break_clear(serial_t *obj)
<> 154:37f96f9d4de2 311 {
<> 154:37f96f9d4de2 312 uart_addrs[obj->index]->CTRL &= ~LPUART_CTRL_SBK_MASK;
<> 154:37f96f9d4de2 313 }
<> 154:37f96f9d4de2 314
<> 154:37f96f9d4de2 315 #endif