fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088
Fork of mbed-src by
serial_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 // math.h required for floating point operations for baud rate calculation 00017 #include <math.h> 00018 #include <string.h> 00019 00020 #include "serial_api.h" 00021 #include "cmsis.h" 00022 #include "pinmap.h" 00023 #include "error.h" 00024 00025 /****************************************************************************** 00026 * INITIALIZATION 00027 ******************************************************************************/ 00028 #define UART_NUM 3 00029 00030 static const SWM_Map SWM_UART_TX[] = { 00031 {0, 0}, 00032 {1, 8}, 00033 {2, 16}, 00034 }; 00035 00036 static const SWM_Map SWM_UART_RX[] = { 00037 {0, 8}, 00038 {1, 16}, 00039 {2, 24}, 00040 }; 00041 00042 // bit flags for used UARTs 00043 static unsigned char uart_used = 0; 00044 static int get_available_uart(void) { 00045 int i; 00046 for (i=0; i<3; i++) { 00047 if ((uart_used & (1 << i)) == 0) 00048 return i; 00049 } 00050 return -1; 00051 } 00052 00053 #define UART_EN (0x01<<0) 00054 00055 #define CTS_DELTA (0x01<<5) 00056 #define RXBRK (0x01<<10) 00057 #define DELTA_RXBRK (0x01<<11) 00058 00059 #define RXRDY (0x01<<0) 00060 #define TXRDY (0x01<<2) 00061 00062 static uint32_t UARTSysClk; 00063 00064 static uint32_t serial_irq_ids[UART_NUM] = {0}; 00065 static uart_irq_handler irq_handler; 00066 00067 int stdio_uart_inited = 0; 00068 serial_t stdio_uart; 00069 00070 void serial_init(serial_t *obj, PinName tx, PinName rx) { 00071 int is_stdio_uart = 0; 00072 00073 int uart_n = get_available_uart(); 00074 if (uart_n == -1) { 00075 error("No available UART"); 00076 } 00077 obj->index = uart_n; 00078 obj->uart = (LPC_USART_TypeDef *)(LPC_USART0_BASE + (0x4000 * uart_n)); 00079 uart_used |= (1 << uart_n); 00080 00081 const SWM_Map *swm; 00082 uint32_t regVal; 00083 00084 swm = &SWM_UART_TX[uart_n]; 00085 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00086 LPC_SWM->PINASSIGN[swm->n] = regVal | (tx << swm->offset); 00087 00088 swm = &SWM_UART_RX[uart_n]; 00089 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); 00090 LPC_SWM->PINASSIGN[swm->n] = regVal | (rx << swm->offset); 00091 00092 /* uart clock divided by 1 */ 00093 LPC_SYSCON->UARTCLKDIV = 1; 00094 00095 /* disable uart interrupts */ 00096 NVIC_DisableIRQ((IRQn_Type )(UART0_IRQn + uart_n)); 00097 00098 /* Enable UART clock */ 00099 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << (14 + uart_n)); 00100 00101 /* Peripheral reset control to UART, a "1" bring it out of reset. */ 00102 LPC_SYSCON->PRESETCTRL &= ~(0x1 << (3 + uart_n)); 00103 LPC_SYSCON->PRESETCTRL |= (0x1 << (3 + uart_n)); 00104 00105 UARTSysClk = SystemCoreClock / LPC_SYSCON->UARTCLKDIV; 00106 00107 // set default baud rate and format 00108 serial_baud (obj, 9600); 00109 serial_format(obj, 8, ParityNone, 1); 00110 00111 /* Clear all status bits. */ 00112 obj->uart->STAT = CTS_DELTA | DELTA_RXBRK; 00113 00114 /* enable uart interrupts */ 00115 NVIC_EnableIRQ((IRQn_Type )(UART0_IRQn + uart_n)); 00116 00117 /* Enable UART interrupt */ 00118 // obj->uart->INTENSET = RXRDY | TXRDY | DELTA_RXBRK; 00119 00120 /* Enable UART */ 00121 obj->uart->CFG |= UART_EN; 00122 00123 is_stdio_uart = ((tx == USBTX) && (rx == USBRX)); 00124 00125 if (is_stdio_uart) { 00126 stdio_uart_inited = 1; 00127 memcpy(&stdio_uart, obj, sizeof(serial_t)); 00128 } 00129 } 00130 00131 void serial_free(serial_t *obj) { 00132 uart_used &= ~(1 << obj->index); 00133 serial_irq_ids[obj->index] = 0; 00134 } 00135 00136 // serial_baud 00137 // set the baud rate, taking in to account the current SystemFrequency 00138 void serial_baud(serial_t *obj, int baudrate) { 00139 /* Integer divider: 00140 BRG = UARTSysClk/(Baudrate * 16) - 1 00141 00142 Frational divider: 00143 FRG = ((UARTSysClk / (Baudrate * 16 * (BRG + 1))) - 1) 00144 00145 where 00146 FRG = (LPC_SYSCON->UARTFRDADD + 1) / (LPC_SYSCON->UARTFRDSUB + 1) 00147 00148 (1) The easiest way is set SUB value to 256, -1 encoded, thus SUB 00149 register is 0xFF. 00150 (2) In ADD register value, depending on the value of UartSysClk, 00151 baudrate, BRG register value, and SUB register value, be careful 00152 about the order of multiplier and divider and make sure any 00153 multiplier doesn't exceed 32-bit boundary and any divider doesn't get 00154 down below one(integer 0). 00155 (3) ADD should be always less than SUB. 00156 */ 00157 obj->uart->BRG = UARTSysClk / 16 / baudrate - 1; 00158 00159 LPC_SYSCON->UARTFRGDIV = 0xFF; 00160 LPC_SYSCON->UARTFRGMULT = ( ((UARTSysClk / 16) * (LPC_SYSCON->UARTFRGDIV + 1)) / 00161 (baudrate * (obj->uart->BRG + 1)) 00162 ) - (LPC_SYSCON->UARTFRGDIV + 1); 00163 00164 } 00165 00166 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { 00167 // 0: 1 stop bits, 1: 2 stop bits 00168 if (stop_bits != 1 && stop_bits != 2) { 00169 error("Invalid stop bits specified"); 00170 } 00171 stop_bits -= 1; 00172 00173 // 0: 7 data bits ... 2: 9 data bits 00174 if (data_bits < 7 || data_bits > 9) { 00175 error("Invalid number of bits (%d) in serial format, should be 7..9", data_bits); 00176 } 00177 data_bits -= 7; 00178 00179 int paritysel; 00180 switch (parity) { 00181 case ParityNone: paritysel = 0; break; 00182 case ParityEven: paritysel = 2; break; 00183 case ParityOdd : paritysel = 3; break; 00184 default: 00185 error("Invalid serial parity setting"); 00186 return; 00187 } 00188 00189 obj->uart->CFG = (data_bits << 2) 00190 | (paritysel << 4) 00191 | (stop_bits << 6); 00192 } 00193 00194 /****************************************************************************** 00195 * INTERRUPTS HANDLING 00196 ******************************************************************************/ 00197 static inline void uart_irq(uint32_t iir, uint32_t index) { 00198 // [Chapter 14] LPC17xx UART0/2/3: UARTn Interrupt Handling 00199 SerialIrq irq_type; 00200 switch (iir) { 00201 case 1: irq_type = TxIrq; break; 00202 case 2: irq_type = RxIrq; break; 00203 default: return; 00204 } 00205 00206 if (serial_irq_ids[index] != 0) 00207 irq_handler(serial_irq_ids[index], irq_type); 00208 } 00209 00210 void uart0_irq() {uart_irq((LPC_USART0->STAT & (1 << 2)) ? 2 : 1, 0);} 00211 void uart1_irq() {uart_irq((LPC_USART1->STAT & (1 << 2)) ? 2 : 1, 1);} 00212 void uart2_irq() {uart_irq((LPC_USART2->STAT & (1 << 2)) ? 2 : 1, 2);} 00213 00214 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { 00215 irq_handler = handler; 00216 serial_irq_ids[obj->index] = id; 00217 } 00218 00219 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { 00220 IRQn_Type irq_n = (IRQn_Type )0; 00221 uint32_t vector = 0; 00222 switch ((int)obj->uart) { 00223 case LPC_USART0_BASE: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break; 00224 case LPC_USART1_BASE: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break; 00225 case LPC_USART2_BASE: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break; 00226 } 00227 00228 if (enable) { 00229 obj->uart->INTENSET = (1 << ((irq == RxIrq) ? 0 : 2)); 00230 NVIC_SetVector(irq_n, vector); 00231 NVIC_EnableIRQ(irq_n); 00232 } else { // disable 00233 int all_disabled = 0; 00234 SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq); 00235 obj->uart->INTENSET &= ~(1 << ((irq == RxIrq) ? 0 : 2)); 00236 all_disabled = (obj->uart->INTENSET & (1 << ((other_irq == RxIrq) ? 0 : 2))) == 0; 00237 if (all_disabled) 00238 NVIC_DisableIRQ(irq_n); 00239 } 00240 } 00241 00242 /****************************************************************************** 00243 * READ/WRITE 00244 ******************************************************************************/ 00245 int serial_getc(serial_t *obj) { 00246 while (!serial_readable(obj)); 00247 return obj->uart->RXDATA; 00248 } 00249 00250 void serial_putc(serial_t *obj, int c) { 00251 while (!serial_writable(obj)); 00252 obj->uart->TXDATA = c; 00253 } 00254 00255 int serial_readable(serial_t *obj) { 00256 return obj->uart->STAT & RXRDY; 00257 } 00258 00259 int serial_writable(serial_t *obj) { 00260 return obj->uart->STAT & TXRDY; 00261 } 00262 00263 void serial_clear(serial_t *obj) { 00264 // [TODO] 00265 } 00266 00267 void serial_pinout_tx(PinName tx) { 00268 00269 }
Generated on Tue Jul 12 2022 13:47:02 by 1.7.2