Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 /**
Pawel Zarembski 0:01f31e923fe2 2 * @file uart.c
Pawel Zarembski 0:01f31e923fe2 3 * @brief
Pawel Zarembski 0:01f31e923fe2 4 *
Pawel Zarembski 0:01f31e923fe2 5 * DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 6 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 7 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 8 *
Pawel Zarembski 0:01f31e923fe2 9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 10 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 11 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 12 *
Pawel Zarembski 0:01f31e923fe2 13 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 14 *
Pawel Zarembski 0:01f31e923fe2 15 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 18 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 19 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 20 */
Pawel Zarembski 0:01f31e923fe2 21
Pawel Zarembski 0:01f31e923fe2 22 #include "LPC11Uxx.h"
Pawel Zarembski 0:01f31e923fe2 23 #include "uart.h"
Pawel Zarembski 0:01f31e923fe2 24 #include "util.h"
Pawel Zarembski 0:01f31e923fe2 25 #include "circ_buf.h"
Pawel Zarembski 0:01f31e923fe2 26 #include "settings.h" // for config_get_overflow_detect
Pawel Zarembski 0:01f31e923fe2 27
Pawel Zarembski 0:01f31e923fe2 28 static uint32_t baudrate;
Pawel Zarembski 0:01f31e923fe2 29 static uint32_t dll;
Pawel Zarembski 0:01f31e923fe2 30 static uint32_t tx_in_progress;
Pawel Zarembski 0:01f31e923fe2 31
Pawel Zarembski 0:01f31e923fe2 32 extern uint32_t SystemCoreClock;
Pawel Zarembski 0:01f31e923fe2 33
Pawel Zarembski 0:01f31e923fe2 34 #define RX_OVRF_MSG "<DAPLink:Overflow>\n"
Pawel Zarembski 0:01f31e923fe2 35 #define RX_OVRF_MSG_SIZE (sizeof(RX_OVRF_MSG) - 1)
Pawel Zarembski 0:01f31e923fe2 36 #define BUFFER_SIZE (64)
Pawel Zarembski 0:01f31e923fe2 37
Pawel Zarembski 0:01f31e923fe2 38 circ_buf_t write_buffer;
Pawel Zarembski 0:01f31e923fe2 39 uint8_t write_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 40 circ_buf_t read_buffer;
Pawel Zarembski 0:01f31e923fe2 41 uint8_t read_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 42
Pawel Zarembski 0:01f31e923fe2 43 static uint8_t flow_control_enabled = 0;
Pawel Zarembski 0:01f31e923fe2 44
Pawel Zarembski 0:01f31e923fe2 45 static int32_t reset(void);
Pawel Zarembski 0:01f31e923fe2 46
Pawel Zarembski 0:01f31e923fe2 47 int32_t uart_initialize(void)
Pawel Zarembski 0:01f31e923fe2 48 {
Pawel Zarembski 0:01f31e923fe2 49 NVIC_DisableIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 50 LPC_SYSCON->SYSAHBCLKCTRL |= ((1UL << 6) | // enable clock for GPIO
Pawel Zarembski 0:01f31e923fe2 51 (1UL << 16)); // enable clock for IOCON
Pawel Zarembski 0:01f31e923fe2 52 // enable clk for usart
Pawel Zarembski 0:01f31e923fe2 53 LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 12);
Pawel Zarembski 0:01f31e923fe2 54 // usart clk divider = 1
Pawel Zarembski 0:01f31e923fe2 55 LPC_SYSCON->UARTCLKDIV = (1UL << 0);
Pawel Zarembski 0:01f31e923fe2 56 // alternate function USART and PullNone
Pawel Zarembski 0:01f31e923fe2 57 LPC_IOCON->PIO0_18 |= 0x01;
Pawel Zarembski 0:01f31e923fe2 58 LPC_IOCON->PIO0_19 |= 0x01;
Pawel Zarembski 0:01f31e923fe2 59 // enable FIFOs (trigger level 1) and clear them
Pawel Zarembski 0:01f31e923fe2 60 LPC_USART->FCR = 0x87;
Pawel Zarembski 0:01f31e923fe2 61 // Transmit Enable
Pawel Zarembski 0:01f31e923fe2 62 LPC_USART->TER = 0x80;
Pawel Zarembski 0:01f31e923fe2 63 // reset uart
Pawel Zarembski 0:01f31e923fe2 64 reset();
Pawel Zarembski 0:01f31e923fe2 65 // enable rx and tx interrupt
Pawel Zarembski 0:01f31e923fe2 66 LPC_USART->IER |= (1 << 0) | (1 << 1);
Pawel Zarembski 0:01f31e923fe2 67 NVIC_EnableIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 68 return 1;
Pawel Zarembski 0:01f31e923fe2 69 }
Pawel Zarembski 0:01f31e923fe2 70
Pawel Zarembski 0:01f31e923fe2 71 int32_t uart_uninitialize(void)
Pawel Zarembski 0:01f31e923fe2 72 {
Pawel Zarembski 0:01f31e923fe2 73 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 74 LPC_USART->IER &= ~(0x7);
Pawel Zarembski 0:01f31e923fe2 75 NVIC_DisableIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 76 // reset uart
Pawel Zarembski 0:01f31e923fe2 77 reset();
Pawel Zarembski 0:01f31e923fe2 78 return 1;
Pawel Zarembski 0:01f31e923fe2 79 }
Pawel Zarembski 0:01f31e923fe2 80
Pawel Zarembski 0:01f31e923fe2 81 int32_t uart_reset(void)
Pawel Zarembski 0:01f31e923fe2 82 {
Pawel Zarembski 0:01f31e923fe2 83 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 84 NVIC_DisableIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 85 // reset uart
Pawel Zarembski 0:01f31e923fe2 86 reset();
Pawel Zarembski 0:01f31e923fe2 87 // enable interrupt
Pawel Zarembski 0:01f31e923fe2 88 NVIC_EnableIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 89 return 1;
Pawel Zarembski 0:01f31e923fe2 90 }
Pawel Zarembski 0:01f31e923fe2 91
Pawel Zarembski 0:01f31e923fe2 92 int32_t uart_set_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 93 {
Pawel Zarembski 0:01f31e923fe2 94 uint8_t DivAddVal = 0;
Pawel Zarembski 0:01f31e923fe2 95 uint8_t MulVal = 1;
Pawel Zarembski 0:01f31e923fe2 96 uint8_t mv, data_bits = 8, parity, stop_bits = 0;
Pawel Zarembski 0:01f31e923fe2 97 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 98 NVIC_DisableIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 99 // reset uart
Pawel Zarembski 0:01f31e923fe2 100 reset();
Pawel Zarembski 0:01f31e923fe2 101 baudrate = config->Baudrate;
Pawel Zarembski 0:01f31e923fe2 102 // Compute baud rate dividers
Pawel Zarembski 0:01f31e923fe2 103 mv = 15;
Pawel Zarembski 0:01f31e923fe2 104 dll = util_div_round_down(SystemCoreClock, 16 * config->Baudrate);
Pawel Zarembski 0:01f31e923fe2 105 DivAddVal = util_div_round(SystemCoreClock * mv, dll * config->Baudrate * 16) - mv;
Pawel Zarembski 0:01f31e923fe2 106 // set LCR[DLAB] to enable writing to divider registers
Pawel Zarembski 0:01f31e923fe2 107 LPC_USART->LCR |= (1 << 7);
Pawel Zarembski 0:01f31e923fe2 108 // set divider values
Pawel Zarembski 0:01f31e923fe2 109 LPC_USART->DLM = (dll >> 8) & 0xFF;
Pawel Zarembski 0:01f31e923fe2 110 LPC_USART->DLL = (dll >> 0) & 0xFF;
Pawel Zarembski 0:01f31e923fe2 111 LPC_USART->FDR = (uint32_t) DivAddVal << 0
Pawel Zarembski 0:01f31e923fe2 112 | (uint32_t) MulVal << 4;
Pawel Zarembski 0:01f31e923fe2 113 // clear LCR[DLAB]
Pawel Zarembski 0:01f31e923fe2 114 LPC_USART->LCR &= ~(1 << 7);
Pawel Zarembski 0:01f31e923fe2 115
Pawel Zarembski 0:01f31e923fe2 116 // set data bits, stop bits, parity
Pawel Zarembski 0:01f31e923fe2 117 if ((config->DataBits < 5) || (config->DataBits > 8)) {
Pawel Zarembski 0:01f31e923fe2 118 data_bits = 8;
Pawel Zarembski 0:01f31e923fe2 119 }
Pawel Zarembski 0:01f31e923fe2 120
Pawel Zarembski 0:01f31e923fe2 121 data_bits -= 5;
Pawel Zarembski 0:01f31e923fe2 122
Pawel Zarembski 0:01f31e923fe2 123 if (config->StopBits != 1 && config->StopBits != 2) {
Pawel Zarembski 0:01f31e923fe2 124 stop_bits = 1;
Pawel Zarembski 0:01f31e923fe2 125 }
Pawel Zarembski 0:01f31e923fe2 126
Pawel Zarembski 0:01f31e923fe2 127 stop_bits -= 1;
Pawel Zarembski 0:01f31e923fe2 128
Pawel Zarembski 0:01f31e923fe2 129 switch (config->Parity) {
Pawel Zarembski 0:01f31e923fe2 130 case UART_PARITY_ODD:
Pawel Zarembski 0:01f31e923fe2 131 parity = 0x01;
Pawel Zarembski 0:01f31e923fe2 132 break; // Parity Odd
Pawel Zarembski 0:01f31e923fe2 133
Pawel Zarembski 0:01f31e923fe2 134 case UART_PARITY_EVEN:
Pawel Zarembski 0:01f31e923fe2 135 parity = 0x03;
Pawel Zarembski 0:01f31e923fe2 136 break; // Parity Even
Pawel Zarembski 0:01f31e923fe2 137
Pawel Zarembski 0:01f31e923fe2 138 case UART_PARITY_MARK:
Pawel Zarembski 0:01f31e923fe2 139 parity = 0x05;
Pawel Zarembski 0:01f31e923fe2 140 break; // Parity Mark
Pawel Zarembski 0:01f31e923fe2 141
Pawel Zarembski 0:01f31e923fe2 142 case UART_PARITY_SPACE:
Pawel Zarembski 0:01f31e923fe2 143 parity = 0x07;
Pawel Zarembski 0:01f31e923fe2 144 break; // Parity Space
Pawel Zarembski 0:01f31e923fe2 145
Pawel Zarembski 0:01f31e923fe2 146 case UART_PARITY_NONE: // Parity None
Pawel Zarembski 0:01f31e923fe2 147 default:
Pawel Zarembski 0:01f31e923fe2 148 parity = 0x00;
Pawel Zarembski 0:01f31e923fe2 149 break;
Pawel Zarembski 0:01f31e923fe2 150 }
Pawel Zarembski 0:01f31e923fe2 151
Pawel Zarembski 0:01f31e923fe2 152 if (flow_control_enabled) {
Pawel Zarembski 0:01f31e923fe2 153 LPC_IOCON->PIO0_17 |= 0x01; // RTS
Pawel Zarembski 0:01f31e923fe2 154 LPC_IOCON->PIO0_7 |= 0x01; // CTS
Pawel Zarembski 0:01f31e923fe2 155 // enable auto RTS and CTS
Pawel Zarembski 0:01f31e923fe2 156 LPC_USART->MCR = (1 << 6) | (1 << 7);
Pawel Zarembski 0:01f31e923fe2 157 } else {
Pawel Zarembski 0:01f31e923fe2 158 LPC_IOCON->PIO0_17 &= ~0x01; // RTS
Pawel Zarembski 0:01f31e923fe2 159 LPC_IOCON->PIO0_7 &= ~0x01; // CTS
Pawel Zarembski 0:01f31e923fe2 160 // disable auto RTS and CTS
Pawel Zarembski 0:01f31e923fe2 161 LPC_USART->MCR = (0 << 6) | (0 << 7);
Pawel Zarembski 0:01f31e923fe2 162 }
Pawel Zarembski 0:01f31e923fe2 163
Pawel Zarembski 0:01f31e923fe2 164 LPC_USART->LCR = (data_bits << 0)
Pawel Zarembski 0:01f31e923fe2 165 | (stop_bits << 2)
Pawel Zarembski 0:01f31e923fe2 166 | (parity << 3);
Pawel Zarembski 0:01f31e923fe2 167 // Enable UART interrupt
Pawel Zarembski 0:01f31e923fe2 168 NVIC_EnableIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 169 return 1;
Pawel Zarembski 0:01f31e923fe2 170 }
Pawel Zarembski 0:01f31e923fe2 171
Pawel Zarembski 0:01f31e923fe2 172 int32_t uart_get_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 173 {
Pawel Zarembski 0:01f31e923fe2 174 float br;
Pawel Zarembski 0:01f31e923fe2 175 uint32_t lcr;
Pawel Zarembski 0:01f31e923fe2 176 // line control parameter
Pawel Zarembski 0:01f31e923fe2 177 lcr = LPC_USART->LCR;
Pawel Zarembski 0:01f31e923fe2 178 // baudrate
Pawel Zarembski 0:01f31e923fe2 179 br = SystemCoreClock / (dll * 16);
Pawel Zarembski 0:01f31e923fe2 180
Pawel Zarembski 0:01f31e923fe2 181 // If inside +/- 2% tolerance
Pawel Zarembski 0:01f31e923fe2 182 if (((br * 100) <= (baudrate * 102)) && ((br * 100) >= (baudrate * 98))) {
Pawel Zarembski 0:01f31e923fe2 183 config->Baudrate = baudrate;
Pawel Zarembski 0:01f31e923fe2 184 } else {
Pawel Zarembski 0:01f31e923fe2 185 config->Baudrate = br;
Pawel Zarembski 0:01f31e923fe2 186 }
Pawel Zarembski 0:01f31e923fe2 187
Pawel Zarembski 0:01f31e923fe2 188 // get data bits
Pawel Zarembski 0:01f31e923fe2 189 switch ((lcr >> 0) & 3) {
Pawel Zarembski 0:01f31e923fe2 190 case 0:
Pawel Zarembski 0:01f31e923fe2 191 config->DataBits = UART_DATA_BITS_5;
Pawel Zarembski 0:01f31e923fe2 192 break;
Pawel Zarembski 0:01f31e923fe2 193
Pawel Zarembski 0:01f31e923fe2 194 case 1:
Pawel Zarembski 0:01f31e923fe2 195 config->DataBits = UART_DATA_BITS_6;
Pawel Zarembski 0:01f31e923fe2 196 break;
Pawel Zarembski 0:01f31e923fe2 197
Pawel Zarembski 0:01f31e923fe2 198 case 2:
Pawel Zarembski 0:01f31e923fe2 199 config->DataBits = UART_DATA_BITS_7;
Pawel Zarembski 0:01f31e923fe2 200 break;
Pawel Zarembski 0:01f31e923fe2 201
Pawel Zarembski 0:01f31e923fe2 202 case 3:
Pawel Zarembski 0:01f31e923fe2 203 config->DataBits = UART_DATA_BITS_8;
Pawel Zarembski 0:01f31e923fe2 204 break;
Pawel Zarembski 0:01f31e923fe2 205
Pawel Zarembski 0:01f31e923fe2 206 default:
Pawel Zarembski 0:01f31e923fe2 207 return 0;
Pawel Zarembski 0:01f31e923fe2 208 }
Pawel Zarembski 0:01f31e923fe2 209
Pawel Zarembski 0:01f31e923fe2 210 // get parity
Pawel Zarembski 0:01f31e923fe2 211 switch ((lcr >> 3) & 7) {
Pawel Zarembski 0:01f31e923fe2 212 case 0:
Pawel Zarembski 0:01f31e923fe2 213 case 2:
Pawel Zarembski 0:01f31e923fe2 214 case 4:
Pawel Zarembski 0:01f31e923fe2 215 case 6:
Pawel Zarembski 0:01f31e923fe2 216 config->Parity = UART_PARITY_NONE;
Pawel Zarembski 0:01f31e923fe2 217 break;
Pawel Zarembski 0:01f31e923fe2 218
Pawel Zarembski 0:01f31e923fe2 219 case 1:
Pawel Zarembski 0:01f31e923fe2 220 config->Parity = UART_PARITY_ODD;
Pawel Zarembski 0:01f31e923fe2 221 break;
Pawel Zarembski 0:01f31e923fe2 222
Pawel Zarembski 0:01f31e923fe2 223 case 3:
Pawel Zarembski 0:01f31e923fe2 224 config->Parity = UART_PARITY_MARK;
Pawel Zarembski 0:01f31e923fe2 225 break;
Pawel Zarembski 0:01f31e923fe2 226
Pawel Zarembski 0:01f31e923fe2 227 case 5:
Pawel Zarembski 0:01f31e923fe2 228 config->Parity = UART_PARITY_EVEN;
Pawel Zarembski 0:01f31e923fe2 229 break;
Pawel Zarembski 0:01f31e923fe2 230
Pawel Zarembski 0:01f31e923fe2 231 case 7:
Pawel Zarembski 0:01f31e923fe2 232 config->Parity = UART_PARITY_SPACE;
Pawel Zarembski 0:01f31e923fe2 233 break;
Pawel Zarembski 0:01f31e923fe2 234
Pawel Zarembski 0:01f31e923fe2 235 default:
Pawel Zarembski 0:01f31e923fe2 236 return 0;
Pawel Zarembski 0:01f31e923fe2 237 }
Pawel Zarembski 0:01f31e923fe2 238
Pawel Zarembski 0:01f31e923fe2 239 // get stop bits
Pawel Zarembski 0:01f31e923fe2 240 switch ((lcr >> 2) & 1) {
Pawel Zarembski 0:01f31e923fe2 241 case 0:
Pawel Zarembski 0:01f31e923fe2 242 config->StopBits = UART_STOP_BITS_1;
Pawel Zarembski 0:01f31e923fe2 243 break;
Pawel Zarembski 0:01f31e923fe2 244
Pawel Zarembski 0:01f31e923fe2 245 case 1:
Pawel Zarembski 0:01f31e923fe2 246 config->StopBits = UART_STOP_BITS_2;
Pawel Zarembski 0:01f31e923fe2 247 break;
Pawel Zarembski 0:01f31e923fe2 248
Pawel Zarembski 0:01f31e923fe2 249 default:
Pawel Zarembski 0:01f31e923fe2 250 return 0;
Pawel Zarembski 0:01f31e923fe2 251 }
Pawel Zarembski 0:01f31e923fe2 252
Pawel Zarembski 0:01f31e923fe2 253 // get flow control
Pawel Zarembski 0:01f31e923fe2 254 if (flow_control_enabled) {
Pawel Zarembski 0:01f31e923fe2 255 config->FlowControl = UART_FLOW_CONTROL_RTS_CTS;
Pawel Zarembski 0:01f31e923fe2 256 }
Pawel Zarembski 0:01f31e923fe2 257 else {
Pawel Zarembski 0:01f31e923fe2 258 config->FlowControl = UART_FLOW_CONTROL_NONE;
Pawel Zarembski 0:01f31e923fe2 259 }
Pawel Zarembski 0:01f31e923fe2 260 return 1;
Pawel Zarembski 0:01f31e923fe2 261 }
Pawel Zarembski 0:01f31e923fe2 262
Pawel Zarembski 0:01f31e923fe2 263 int32_t uart_write_free(void)
Pawel Zarembski 0:01f31e923fe2 264 {
Pawel Zarembski 0:01f31e923fe2 265 return circ_buf_count_free(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 266 }
Pawel Zarembski 0:01f31e923fe2 267
Pawel Zarembski 0:01f31e923fe2 268 int32_t uart_write_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 269 {
Pawel Zarembski 0:01f31e923fe2 270 uint32_t cnt;
Pawel Zarembski 0:01f31e923fe2 271
Pawel Zarembski 0:01f31e923fe2 272 cnt = circ_buf_write(&write_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 273
Pawel Zarembski 0:01f31e923fe2 274 // enable THRE interrupt
Pawel Zarembski 0:01f31e923fe2 275 LPC_USART->IER |= (1 << 1);
Pawel Zarembski 0:01f31e923fe2 276
Pawel Zarembski 0:01f31e923fe2 277 if (!tx_in_progress) {
Pawel Zarembski 0:01f31e923fe2 278 // force THRE interrupt to start
Pawel Zarembski 0:01f31e923fe2 279 NVIC_SetPendingIRQ(UART_IRQn);
Pawel Zarembski 0:01f31e923fe2 280 }
Pawel Zarembski 0:01f31e923fe2 281
Pawel Zarembski 0:01f31e923fe2 282 return cnt;
Pawel Zarembski 0:01f31e923fe2 283 }
Pawel Zarembski 0:01f31e923fe2 284
Pawel Zarembski 0:01f31e923fe2 285
Pawel Zarembski 0:01f31e923fe2 286 int32_t uart_read_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 287 {
Pawel Zarembski 0:01f31e923fe2 288 return circ_buf_read(&read_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 289 }
Pawel Zarembski 0:01f31e923fe2 290
Pawel Zarembski 0:01f31e923fe2 291 void uart_enable_flow_control(bool enabled)
Pawel Zarembski 0:01f31e923fe2 292 {
Pawel Zarembski 0:01f31e923fe2 293 flow_control_enabled = (uint8_t)enabled;
Pawel Zarembski 0:01f31e923fe2 294 }
Pawel Zarembski 0:01f31e923fe2 295
Pawel Zarembski 0:01f31e923fe2 296 void UART_IRQHandler(void)
Pawel Zarembski 0:01f31e923fe2 297 {
Pawel Zarembski 0:01f31e923fe2 298 uint32_t iir;
Pawel Zarembski 0:01f31e923fe2 299 // read interrupt status
Pawel Zarembski 0:01f31e923fe2 300 iir = LPC_USART->IIR;
Pawel Zarembski 0:01f31e923fe2 301
Pawel Zarembski 0:01f31e923fe2 302 // handle character to transmit
Pawel Zarembski 0:01f31e923fe2 303 if (circ_buf_count_used(&write_buffer) > 0) {
Pawel Zarembski 0:01f31e923fe2 304 // if THR is empty
Pawel Zarembski 0:01f31e923fe2 305 if (LPC_USART->LSR & (1 << 5)) {
Pawel Zarembski 0:01f31e923fe2 306 LPC_USART->THR = circ_buf_pop(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 307 tx_in_progress = 1;
Pawel Zarembski 0:01f31e923fe2 308 }
Pawel Zarembski 0:01f31e923fe2 309
Pawel Zarembski 0:01f31e923fe2 310 } else if (tx_in_progress) {
Pawel Zarembski 0:01f31e923fe2 311 tx_in_progress = 0;
Pawel Zarembski 0:01f31e923fe2 312 // disable THRE interrupt
Pawel Zarembski 0:01f31e923fe2 313 LPC_USART->IER &= ~(1 << 1);
Pawel Zarembski 0:01f31e923fe2 314 }
Pawel Zarembski 0:01f31e923fe2 315
Pawel Zarembski 0:01f31e923fe2 316 // handle received character
Pawel Zarembski 0:01f31e923fe2 317 if (((iir & 0x0E) == 0x04) || // Rx interrupt (RDA)
Pawel Zarembski 0:01f31e923fe2 318 ((iir & 0x0E) == 0x0C)) { // Rx interrupt (CTI)
Pawel Zarembski 0:01f31e923fe2 319 while (LPC_USART->LSR & 0x01) {
Pawel Zarembski 0:01f31e923fe2 320 uint32_t free;
Pawel Zarembski 0:01f31e923fe2 321 uint8_t data;
Pawel Zarembski 0:01f31e923fe2 322
Pawel Zarembski 0:01f31e923fe2 323 data = LPC_USART->RBR;
Pawel Zarembski 0:01f31e923fe2 324 free = circ_buf_count_free(&read_buffer);
Pawel Zarembski 0:01f31e923fe2 325 if (free > RX_OVRF_MSG_SIZE) {
Pawel Zarembski 0:01f31e923fe2 326 circ_buf_push(&read_buffer, data);
Pawel Zarembski 0:01f31e923fe2 327 } else if (config_get_overflow_detect()) {
Pawel Zarembski 0:01f31e923fe2 328 if (RX_OVRF_MSG_SIZE == free) {
Pawel Zarembski 0:01f31e923fe2 329 circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE);
Pawel Zarembski 0:01f31e923fe2 330 } else {
Pawel Zarembski 0:01f31e923fe2 331 // Drop newest
Pawel Zarembski 0:01f31e923fe2 332 }
Pawel Zarembski 0:01f31e923fe2 333 } else {
Pawel Zarembski 0:01f31e923fe2 334 // Drop oldest
Pawel Zarembski 0:01f31e923fe2 335 circ_buf_pop(&read_buffer);
Pawel Zarembski 0:01f31e923fe2 336 circ_buf_push(&read_buffer, data);
Pawel Zarembski 0:01f31e923fe2 337 }
Pawel Zarembski 0:01f31e923fe2 338 }
Pawel Zarembski 0:01f31e923fe2 339 }
Pawel Zarembski 0:01f31e923fe2 340
Pawel Zarembski 0:01f31e923fe2 341 LPC_USART->LSR;
Pawel Zarembski 0:01f31e923fe2 342 }
Pawel Zarembski 0:01f31e923fe2 343
Pawel Zarembski 0:01f31e923fe2 344 static int32_t reset(void)
Pawel Zarembski 0:01f31e923fe2 345 {
Pawel Zarembski 0:01f31e923fe2 346 uint32_t mcr;
Pawel Zarembski 0:01f31e923fe2 347 // Reset FIFOs
Pawel Zarembski 0:01f31e923fe2 348 LPC_USART->FCR = 0x06;
Pawel Zarembski 0:01f31e923fe2 349 baudrate = 0;
Pawel Zarembski 0:01f31e923fe2 350 dll = 0;
Pawel Zarembski 0:01f31e923fe2 351 tx_in_progress = 0;
Pawel Zarembski 0:01f31e923fe2 352
Pawel Zarembski 0:01f31e923fe2 353 circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data));
Pawel Zarembski 0:01f31e923fe2 354 circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data));
Pawel Zarembski 0:01f31e923fe2 355
Pawel Zarembski 0:01f31e923fe2 356 // Enable loopback mode to drain remaining bytes (even if flow control is on)
Pawel Zarembski 0:01f31e923fe2 357 mcr = LPC_USART->MCR;
Pawel Zarembski 0:01f31e923fe2 358 LPC_USART->MCR = mcr | (1 << 4);
Pawel Zarembski 0:01f31e923fe2 359
Pawel Zarembski 0:01f31e923fe2 360 // Ensure a clean start, no data in either TX or RX FIFO
Pawel Zarembski 0:01f31e923fe2 361 while ((LPC_USART->LSR & ((1 << 5) | (1 << 6))) != ((1 << 5) | (1 << 6))) {
Pawel Zarembski 0:01f31e923fe2 362 LPC_USART->FCR = (1 << 1) | (1 << 2);
Pawel Zarembski 0:01f31e923fe2 363 }
Pawel Zarembski 0:01f31e923fe2 364
Pawel Zarembski 0:01f31e923fe2 365 // Restore previous mode (loopback off)
Pawel Zarembski 0:01f31e923fe2 366 LPC_USART->MCR = mcr;
Pawel Zarembski 0:01f31e923fe2 367
Pawel Zarembski 0:01f31e923fe2 368 while (LPC_USART->LSR & 0x01) {
Pawel Zarembski 0:01f31e923fe2 369 LPC_USART->RBR; // Dump data from RX FIFO
Pawel Zarembski 0:01f31e923fe2 370 }
Pawel Zarembski 0:01f31e923fe2 371
Pawel Zarembski 0:01f31e923fe2 372 return 1;
Pawel Zarembski 0:01f31e923fe2 373 }