mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
bogdanm
Date:
Mon Aug 05 14:12:34 2013 +0300
Revision:
13:0645d8841f51
Update mbed sources to revision 64

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 13:0645d8841f51 1 /* mbed Microcontroller Library
bogdanm 13:0645d8841f51 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 13:0645d8841f51 3 *
bogdanm 13:0645d8841f51 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 13:0645d8841f51 5 * you may not use this file except in compliance with the License.
bogdanm 13:0645d8841f51 6 * You may obtain a copy of the License at
bogdanm 13:0645d8841f51 7 *
bogdanm 13:0645d8841f51 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 13:0645d8841f51 9 *
bogdanm 13:0645d8841f51 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 13:0645d8841f51 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 13:0645d8841f51 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 13:0645d8841f51 13 * See the License for the specific language governing permissions and
bogdanm 13:0645d8841f51 14 * limitations under the License.
bogdanm 13:0645d8841f51 15 */
bogdanm 13:0645d8841f51 16 // math.h required for floating point operations for baud rate calculation
bogdanm 13:0645d8841f51 17 #include <math.h>
bogdanm 13:0645d8841f51 18 #include <string.h>
bogdanm 13:0645d8841f51 19
bogdanm 13:0645d8841f51 20 #include "serial_api.h"
bogdanm 13:0645d8841f51 21 #include "cmsis.h"
bogdanm 13:0645d8841f51 22 #include "pinmap.h"
bogdanm 13:0645d8841f51 23 #include "error.h"
bogdanm 13:0645d8841f51 24
bogdanm 13:0645d8841f51 25 /******************************************************************************
bogdanm 13:0645d8841f51 26 * INITIALIZATION
bogdanm 13:0645d8841f51 27 ******************************************************************************/
bogdanm 13:0645d8841f51 28 #define UART_NUM 3
bogdanm 13:0645d8841f51 29
bogdanm 13:0645d8841f51 30 static const SWM_Map SWM_UART_TX[] = {
bogdanm 13:0645d8841f51 31 {0, 0},
bogdanm 13:0645d8841f51 32 {1, 8},
bogdanm 13:0645d8841f51 33 {2, 16},
bogdanm 13:0645d8841f51 34 };
bogdanm 13:0645d8841f51 35
bogdanm 13:0645d8841f51 36 static const SWM_Map SWM_UART_RX[] = {
bogdanm 13:0645d8841f51 37 {0, 8},
bogdanm 13:0645d8841f51 38 {1, 16},
bogdanm 13:0645d8841f51 39 {2, 24},
bogdanm 13:0645d8841f51 40 };
bogdanm 13:0645d8841f51 41
bogdanm 13:0645d8841f51 42 // bit flags for used UARTs
bogdanm 13:0645d8841f51 43 static unsigned char uart_used = 0;
bogdanm 13:0645d8841f51 44 static int get_available_uart(void) {
bogdanm 13:0645d8841f51 45 int i;
bogdanm 13:0645d8841f51 46 for (i=0; i<3; i++) {
bogdanm 13:0645d8841f51 47 if ((uart_used & (1 << i)) == 0)
bogdanm 13:0645d8841f51 48 return i;
bogdanm 13:0645d8841f51 49 }
bogdanm 13:0645d8841f51 50 return -1;
bogdanm 13:0645d8841f51 51 }
bogdanm 13:0645d8841f51 52
bogdanm 13:0645d8841f51 53 #define UART_EN (0x01<<0)
bogdanm 13:0645d8841f51 54
bogdanm 13:0645d8841f51 55 #define CTS_DELTA (0x01<<5)
bogdanm 13:0645d8841f51 56 #define RXBRK (0x01<<10)
bogdanm 13:0645d8841f51 57 #define DELTA_RXBRK (0x01<<11)
bogdanm 13:0645d8841f51 58
bogdanm 13:0645d8841f51 59 #define RXRDY (0x01<<0)
bogdanm 13:0645d8841f51 60 #define TXRDY (0x01<<2)
bogdanm 13:0645d8841f51 61
bogdanm 13:0645d8841f51 62 #define TXBRKEN (0x01<<1)
bogdanm 13:0645d8841f51 63
bogdanm 13:0645d8841f51 64 static uint32_t UARTSysClk;
bogdanm 13:0645d8841f51 65
bogdanm 13:0645d8841f51 66 static uint32_t serial_irq_ids[UART_NUM] = {0};
bogdanm 13:0645d8841f51 67 static uart_irq_handler irq_handler;
bogdanm 13:0645d8841f51 68
bogdanm 13:0645d8841f51 69 int stdio_uart_inited = 0;
bogdanm 13:0645d8841f51 70 serial_t stdio_uart;
bogdanm 13:0645d8841f51 71
bogdanm 13:0645d8841f51 72 void serial_init(serial_t *obj, PinName tx, PinName rx) {
bogdanm 13:0645d8841f51 73 int is_stdio_uart = 0;
bogdanm 13:0645d8841f51 74
bogdanm 13:0645d8841f51 75 int uart_n = get_available_uart();
bogdanm 13:0645d8841f51 76 if (uart_n == -1) {
bogdanm 13:0645d8841f51 77 error("No available UART");
bogdanm 13:0645d8841f51 78 }
bogdanm 13:0645d8841f51 79 obj->index = uart_n;
bogdanm 13:0645d8841f51 80 obj->uart = (LPC_USART_TypeDef *)(LPC_USART0_BASE + (0x4000 * uart_n));
bogdanm 13:0645d8841f51 81 uart_used |= (1 << uart_n);
bogdanm 13:0645d8841f51 82
bogdanm 13:0645d8841f51 83 const SWM_Map *swm;
bogdanm 13:0645d8841f51 84 uint32_t regVal;
bogdanm 13:0645d8841f51 85
bogdanm 13:0645d8841f51 86 swm = &SWM_UART_TX[uart_n];
bogdanm 13:0645d8841f51 87 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
bogdanm 13:0645d8841f51 88 LPC_SWM->PINASSIGN[swm->n] = regVal | (tx << swm->offset);
bogdanm 13:0645d8841f51 89
bogdanm 13:0645d8841f51 90 swm = &SWM_UART_RX[uart_n];
bogdanm 13:0645d8841f51 91 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
bogdanm 13:0645d8841f51 92 LPC_SWM->PINASSIGN[swm->n] = regVal | (rx << swm->offset);
bogdanm 13:0645d8841f51 93
bogdanm 13:0645d8841f51 94 /* uart clock divided by 1 */
bogdanm 13:0645d8841f51 95 LPC_SYSCON->UARTCLKDIV = 1;
bogdanm 13:0645d8841f51 96
bogdanm 13:0645d8841f51 97 /* disable uart interrupts */
bogdanm 13:0645d8841f51 98 NVIC_DisableIRQ((IRQn_Type)(UART0_IRQn + uart_n));
bogdanm 13:0645d8841f51 99
bogdanm 13:0645d8841f51 100 /* Enable UART clock */
bogdanm 13:0645d8841f51 101 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << (14 + uart_n));
bogdanm 13:0645d8841f51 102
bogdanm 13:0645d8841f51 103 /* Peripheral reset control to UART, a "1" bring it out of reset. */
bogdanm 13:0645d8841f51 104 LPC_SYSCON->PRESETCTRL &= ~(0x1 << (3 + uart_n));
bogdanm 13:0645d8841f51 105 LPC_SYSCON->PRESETCTRL |= (0x1 << (3 + uart_n));
bogdanm 13:0645d8841f51 106
bogdanm 13:0645d8841f51 107 UARTSysClk = SystemCoreClock / LPC_SYSCON->UARTCLKDIV;
bogdanm 13:0645d8841f51 108
bogdanm 13:0645d8841f51 109 // set default baud rate and format
bogdanm 13:0645d8841f51 110 serial_baud (obj, 9600);
bogdanm 13:0645d8841f51 111 serial_format(obj, 8, ParityNone, 1);
bogdanm 13:0645d8841f51 112
bogdanm 13:0645d8841f51 113 /* Clear all status bits. */
bogdanm 13:0645d8841f51 114 obj->uart->STAT = CTS_DELTA | DELTA_RXBRK;
bogdanm 13:0645d8841f51 115
bogdanm 13:0645d8841f51 116 /* enable uart interrupts */
bogdanm 13:0645d8841f51 117 NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + uart_n));
bogdanm 13:0645d8841f51 118
bogdanm 13:0645d8841f51 119 /* Enable UART interrupt */
bogdanm 13:0645d8841f51 120 // obj->uart->INTENSET = RXRDY | TXRDY | DELTA_RXBRK;
bogdanm 13:0645d8841f51 121
bogdanm 13:0645d8841f51 122 /* Enable UART */
bogdanm 13:0645d8841f51 123 obj->uart->CFG |= UART_EN;
bogdanm 13:0645d8841f51 124
bogdanm 13:0645d8841f51 125 is_stdio_uart = ((tx == USBTX) && (rx == USBRX));
bogdanm 13:0645d8841f51 126
bogdanm 13:0645d8841f51 127 if (is_stdio_uart) {
bogdanm 13:0645d8841f51 128 stdio_uart_inited = 1;
bogdanm 13:0645d8841f51 129 memcpy(&stdio_uart, obj, sizeof(serial_t));
bogdanm 13:0645d8841f51 130 }
bogdanm 13:0645d8841f51 131 }
bogdanm 13:0645d8841f51 132
bogdanm 13:0645d8841f51 133 void serial_free(serial_t *obj) {
bogdanm 13:0645d8841f51 134 uart_used &= ~(1 << obj->index);
bogdanm 13:0645d8841f51 135 serial_irq_ids[obj->index] = 0;
bogdanm 13:0645d8841f51 136 }
bogdanm 13:0645d8841f51 137
bogdanm 13:0645d8841f51 138 // serial_baud
bogdanm 13:0645d8841f51 139 // set the baud rate, taking in to account the current SystemFrequency
bogdanm 13:0645d8841f51 140 void serial_baud(serial_t *obj, int baudrate) {
bogdanm 13:0645d8841f51 141 /* Integer divider:
bogdanm 13:0645d8841f51 142 BRG = UARTSysClk/(Baudrate * 16) - 1
bogdanm 13:0645d8841f51 143
bogdanm 13:0645d8841f51 144 Frational divider:
bogdanm 13:0645d8841f51 145 FRG = ((UARTSysClk / (Baudrate * 16 * (BRG + 1))) - 1)
bogdanm 13:0645d8841f51 146
bogdanm 13:0645d8841f51 147 where
bogdanm 13:0645d8841f51 148 FRG = (LPC_SYSCON->UARTFRDADD + 1) / (LPC_SYSCON->UARTFRDSUB + 1)
bogdanm 13:0645d8841f51 149
bogdanm 13:0645d8841f51 150 (1) The easiest way is set SUB value to 256, -1 encoded, thus SUB
bogdanm 13:0645d8841f51 151 register is 0xFF.
bogdanm 13:0645d8841f51 152 (2) In ADD register value, depending on the value of UartSysClk,
bogdanm 13:0645d8841f51 153 baudrate, BRG register value, and SUB register value, be careful
bogdanm 13:0645d8841f51 154 about the order of multiplier and divider and make sure any
bogdanm 13:0645d8841f51 155 multiplier doesn't exceed 32-bit boundary and any divider doesn't get
bogdanm 13:0645d8841f51 156 down below one(integer 0).
bogdanm 13:0645d8841f51 157 (3) ADD should be always less than SUB.
bogdanm 13:0645d8841f51 158 */
bogdanm 13:0645d8841f51 159 obj->uart->BRG = UARTSysClk / 16 / baudrate - 1;
bogdanm 13:0645d8841f51 160
bogdanm 13:0645d8841f51 161 LPC_SYSCON->UARTFRGDIV = 0xFF;
bogdanm 13:0645d8841f51 162 LPC_SYSCON->UARTFRGMULT = ( ((UARTSysClk / 16) * (LPC_SYSCON->UARTFRGDIV + 1)) /
bogdanm 13:0645d8841f51 163 (baudrate * (obj->uart->BRG + 1))
bogdanm 13:0645d8841f51 164 ) - (LPC_SYSCON->UARTFRGDIV + 1);
bogdanm 13:0645d8841f51 165
bogdanm 13:0645d8841f51 166 }
bogdanm 13:0645d8841f51 167
bogdanm 13:0645d8841f51 168 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
bogdanm 13:0645d8841f51 169 // 0: 1 stop bits, 1: 2 stop bits
bogdanm 13:0645d8841f51 170 if (stop_bits != 1 && stop_bits != 2) {
bogdanm 13:0645d8841f51 171 error("Invalid stop bits specified");
bogdanm 13:0645d8841f51 172 }
bogdanm 13:0645d8841f51 173 stop_bits -= 1;
bogdanm 13:0645d8841f51 174
bogdanm 13:0645d8841f51 175 // 0: 7 data bits ... 2: 9 data bits
bogdanm 13:0645d8841f51 176 if (data_bits < 7 || data_bits > 9) {
bogdanm 13:0645d8841f51 177 error("Invalid number of bits (%d) in serial format, should be 7..9", data_bits);
bogdanm 13:0645d8841f51 178 }
bogdanm 13:0645d8841f51 179 data_bits -= 7;
bogdanm 13:0645d8841f51 180
bogdanm 13:0645d8841f51 181 int paritysel;
bogdanm 13:0645d8841f51 182 switch (parity) {
bogdanm 13:0645d8841f51 183 case ParityNone: paritysel = 0; break;
bogdanm 13:0645d8841f51 184 case ParityEven: paritysel = 2; break;
bogdanm 13:0645d8841f51 185 case ParityOdd : paritysel = 3; break;
bogdanm 13:0645d8841f51 186 default:
bogdanm 13:0645d8841f51 187 error("Invalid serial parity setting");
bogdanm 13:0645d8841f51 188 return;
bogdanm 13:0645d8841f51 189 }
bogdanm 13:0645d8841f51 190
bogdanm 13:0645d8841f51 191 obj->uart->CFG = (data_bits << 2)
bogdanm 13:0645d8841f51 192 | (paritysel << 4)
bogdanm 13:0645d8841f51 193 | (stop_bits << 6);
bogdanm 13:0645d8841f51 194 }
bogdanm 13:0645d8841f51 195
bogdanm 13:0645d8841f51 196 /******************************************************************************
bogdanm 13:0645d8841f51 197 * INTERRUPTS HANDLING
bogdanm 13:0645d8841f51 198 ******************************************************************************/
bogdanm 13:0645d8841f51 199 static inline void uart_irq(uint32_t iir, uint32_t index) {
bogdanm 13:0645d8841f51 200 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling
bogdanm 13:0645d8841f51 201 SerialIrq irq_type;
bogdanm 13:0645d8841f51 202 switch (iir) {
bogdanm 13:0645d8841f51 203 case 1: irq_type = TxIrq; break;
bogdanm 13:0645d8841f51 204 case 2: irq_type = RxIrq; break;
bogdanm 13:0645d8841f51 205 default: return;
bogdanm 13:0645d8841f51 206 }
bogdanm 13:0645d8841f51 207
bogdanm 13:0645d8841f51 208 if (serial_irq_ids[index] != 0)
bogdanm 13:0645d8841f51 209 irq_handler(serial_irq_ids[index], irq_type);
bogdanm 13:0645d8841f51 210 }
bogdanm 13:0645d8841f51 211
bogdanm 13:0645d8841f51 212 void uart0_irq() {uart_irq((LPC_USART0->STAT & (1 << 2)) ? 2 : 1, 0);}
bogdanm 13:0645d8841f51 213 void uart1_irq() {uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 1);}
bogdanm 13:0645d8841f51 214 void uart2_irq() {uart_irq((LPC_USART2->STAT & (1 << 2)) ? 2 : 1, 2);}
bogdanm 13:0645d8841f51 215
bogdanm 13:0645d8841f51 216 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
bogdanm 13:0645d8841f51 217 irq_handler = handler;
bogdanm 13:0645d8841f51 218 serial_irq_ids[obj->index] = id;
bogdanm 13:0645d8841f51 219 }
bogdanm 13:0645d8841f51 220
bogdanm 13:0645d8841f51 221 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
bogdanm 13:0645d8841f51 222 IRQn_Type irq_n = (IRQn_Type)0;
bogdanm 13:0645d8841f51 223 uint32_t vector = 0;
bogdanm 13:0645d8841f51 224 switch ((int)obj->uart) {
bogdanm 13:0645d8841f51 225 case LPC_USART0_BASE: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
bogdanm 13:0645d8841f51 226 case LPC_USART1_BASE: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
bogdanm 13:0645d8841f51 227 case LPC_USART2_BASE: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
bogdanm 13:0645d8841f51 228 }
bogdanm 13:0645d8841f51 229
bogdanm 13:0645d8841f51 230 if (enable) {
bogdanm 13:0645d8841f51 231 obj->uart->INTENSET = (1 << ((irq == RxIrq) ? 0 : 2));
bogdanm 13:0645d8841f51 232 NVIC_SetVector(irq_n, vector);
bogdanm 13:0645d8841f51 233 NVIC_EnableIRQ(irq_n);
bogdanm 13:0645d8841f51 234 } else { // disable
bogdanm 13:0645d8841f51 235 int all_disabled = 0;
bogdanm 13:0645d8841f51 236 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
bogdanm 13:0645d8841f51 237 obj->uart->INTENSET &= ~(1 << ((irq == RxIrq) ? 0 : 2));
bogdanm 13:0645d8841f51 238 all_disabled = (obj->uart->INTENSET & (1 << ((other_irq == RxIrq) ? 0 : 2))) == 0;
bogdanm 13:0645d8841f51 239 if (all_disabled)
bogdanm 13:0645d8841f51 240 NVIC_DisableIRQ(irq_n);
bogdanm 13:0645d8841f51 241 }
bogdanm 13:0645d8841f51 242 }
bogdanm 13:0645d8841f51 243
bogdanm 13:0645d8841f51 244 /******************************************************************************
bogdanm 13:0645d8841f51 245 * READ/WRITE
bogdanm 13:0645d8841f51 246 ******************************************************************************/
bogdanm 13:0645d8841f51 247 int serial_getc(serial_t *obj) {
bogdanm 13:0645d8841f51 248 while (!serial_readable(obj));
bogdanm 13:0645d8841f51 249 return obj->uart->RXDATA;
bogdanm 13:0645d8841f51 250 }
bogdanm 13:0645d8841f51 251
bogdanm 13:0645d8841f51 252 void serial_putc(serial_t *obj, int c) {
bogdanm 13:0645d8841f51 253 while (!serial_writable(obj));
bogdanm 13:0645d8841f51 254 obj->uart->TXDATA = c;
bogdanm 13:0645d8841f51 255 }
bogdanm 13:0645d8841f51 256
bogdanm 13:0645d8841f51 257 int serial_readable(serial_t *obj) {
bogdanm 13:0645d8841f51 258 return obj->uart->STAT & RXRDY;
bogdanm 13:0645d8841f51 259 }
bogdanm 13:0645d8841f51 260
bogdanm 13:0645d8841f51 261 int serial_writable(serial_t *obj) {
bogdanm 13:0645d8841f51 262 return obj->uart->STAT & TXRDY;
bogdanm 13:0645d8841f51 263 }
bogdanm 13:0645d8841f51 264
bogdanm 13:0645d8841f51 265 void serial_clear(serial_t *obj) {
bogdanm 13:0645d8841f51 266 // [TODO]
bogdanm 13:0645d8841f51 267 }
bogdanm 13:0645d8841f51 268
bogdanm 13:0645d8841f51 269 void serial_pinout_tx(PinName tx) {
bogdanm 13:0645d8841f51 270
bogdanm 13:0645d8841f51 271 }
bogdanm 13:0645d8841f51 272
bogdanm 13:0645d8841f51 273 void serial_break_set(serial_t *obj) {
bogdanm 13:0645d8841f51 274 obj->uart->CTRL |= TXBRKEN;
bogdanm 13:0645d8841f51 275 }
bogdanm 13:0645d8841f51 276
bogdanm 13:0645d8841f51 277 void serial_break_clear(serial_t *obj) {
bogdanm 13:0645d8841f51 278 obj->uart->CTRL &= ~TXBRKEN;
bogdanm 13:0645d8841f51 279 }
bogdanm 13:0645d8841f51 280