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 "string.h"
Pawel Zarembski 0:01f31e923fe2 23
Pawel Zarembski 0:01f31e923fe2 24 #include "uart.h"
Pawel Zarembski 0:01f31e923fe2 25 #include "util.h"
Pawel Zarembski 0:01f31e923fe2 26 #include "cortex_m.h"
Pawel Zarembski 0:01f31e923fe2 27 #include "IO_Config.h"
Pawel Zarembski 0:01f31e923fe2 28 #include "circ_buf.h"
Pawel Zarembski 0:01f31e923fe2 29 #include "settings.h" // for config_get_overflow_detect
Pawel Zarembski 0:01f31e923fe2 30
Pawel Zarembski 0:01f31e923fe2 31 #define RX_OVRF_MSG "<DAPLink:Overflow>\n"
Pawel Zarembski 0:01f31e923fe2 32 #define RX_OVRF_MSG_SIZE (sizeof(RX_OVRF_MSG) - 1)
Pawel Zarembski 0:01f31e923fe2 33 #define BUFFER_SIZE (512)
Pawel Zarembski 0:01f31e923fe2 34
Pawel Zarembski 0:01f31e923fe2 35 circ_buf_t write_buffer;
Pawel Zarembski 0:01f31e923fe2 36 uint8_t write_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 37 circ_buf_t read_buffer;
Pawel Zarembski 0:01f31e923fe2 38 uint8_t read_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 39
Pawel Zarembski 0:01f31e923fe2 40 void clear_buffers(void)
Pawel Zarembski 0:01f31e923fe2 41 {
Pawel Zarembski 0:01f31e923fe2 42 util_assert(!(UART->C2 & UART_C2_TIE_MASK));
Pawel Zarembski 0:01f31e923fe2 43 circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data));
Pawel Zarembski 0:01f31e923fe2 44 circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data));
Pawel Zarembski 0:01f31e923fe2 45 }
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_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 50
Pawel Zarembski 0:01f31e923fe2 51 // enable clk port
Pawel Zarembski 0:01f31e923fe2 52 if (UART_PORT == PORTA) {
Pawel Zarembski 0:01f31e923fe2 53 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
Pawel Zarembski 0:01f31e923fe2 54 }
Pawel Zarembski 0:01f31e923fe2 55
Pawel Zarembski 0:01f31e923fe2 56 if (UART_PORT == PORTC) {
Pawel Zarembski 0:01f31e923fe2 57 SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
Pawel Zarembski 0:01f31e923fe2 58 }
Pawel Zarembski 0:01f31e923fe2 59
Pawel Zarembski 0:01f31e923fe2 60 if (UART_PORT == PORTD) {
Pawel Zarembski 0:01f31e923fe2 61 SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
Pawel Zarembski 0:01f31e923fe2 62 }
Pawel Zarembski 0:01f31e923fe2 63
Pawel Zarembski 0:01f31e923fe2 64 if (UART_PORT == PORTE) {
Pawel Zarembski 0:01f31e923fe2 65 SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK;
Pawel Zarembski 0:01f31e923fe2 66 }
Pawel Zarembski 0:01f31e923fe2 67
Pawel Zarembski 0:01f31e923fe2 68 // enable clk uart
Pawel Zarembski 0:01f31e923fe2 69 if (1 == UART_NUM) {
Pawel Zarembski 0:01f31e923fe2 70 SIM->SCGC4 |= SIM_SCGC4_UART1_MASK;
Pawel Zarembski 0:01f31e923fe2 71 }
Pawel Zarembski 0:01f31e923fe2 72
Pawel Zarembski 0:01f31e923fe2 73 if (2 == UART_NUM) {
Pawel Zarembski 0:01f31e923fe2 74 SIM->SCGC4 |= SIM_SCGC4_UART2_MASK;
Pawel Zarembski 0:01f31e923fe2 75 }
Pawel Zarembski 0:01f31e923fe2 76
Pawel Zarembski 0:01f31e923fe2 77 // transmitter and receiver disabled
Pawel Zarembski 0:01f31e923fe2 78 UART->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
Pawel Zarembski 0:01f31e923fe2 79 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 80 UART->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 81
Pawel Zarembski 0:01f31e923fe2 82 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 83
Pawel Zarembski 0:01f31e923fe2 84 // alternate setting
Pawel Zarembski 0:01f31e923fe2 85 UART_PORT->PCR[PIN_UART_RX_BIT] = PORT_PCR_MUX(PIN_UART_RX_MUX_ALT) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
Pawel Zarembski 0:01f31e923fe2 86 UART_PORT->PCR[PIN_UART_TX_BIT] = PORT_PCR_MUX(PIN_UART_TX_MUX_ALT);
Pawel Zarembski 0:01f31e923fe2 87 // transmitter and receiver enabled
Pawel Zarembski 0:01f31e923fe2 88 UART->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
Pawel Zarembski 0:01f31e923fe2 89 // Enable receive interrupt
Pawel Zarembski 0:01f31e923fe2 90 UART->C2 |= UART_C2_RIE_MASK;
Pawel Zarembski 0:01f31e923fe2 91 NVIC_ClearPendingIRQ(UART_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 92 NVIC_EnableIRQ(UART_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 93 return 1;
Pawel Zarembski 0:01f31e923fe2 94 }
Pawel Zarembski 0:01f31e923fe2 95
Pawel Zarembski 0:01f31e923fe2 96 int32_t uart_uninitialize(void)
Pawel Zarembski 0:01f31e923fe2 97 {
Pawel Zarembski 0:01f31e923fe2 98 // transmitter and receiver disabled
Pawel Zarembski 0:01f31e923fe2 99 UART->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
Pawel Zarembski 0:01f31e923fe2 100 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 101 UART->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 102 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 103 return 1;
Pawel Zarembski 0:01f31e923fe2 104 }
Pawel Zarembski 0:01f31e923fe2 105
Pawel Zarembski 0:01f31e923fe2 106 int32_t uart_reset(void)
Pawel Zarembski 0:01f31e923fe2 107 {
Pawel Zarembski 0:01f31e923fe2 108 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 109 NVIC_DisableIRQ(UART_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 110 // disable TIE interrupt
Pawel Zarembski 0:01f31e923fe2 111 UART->C2 &= ~(UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 112 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 113 // enable interrupt
Pawel Zarembski 0:01f31e923fe2 114 NVIC_EnableIRQ(UART_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 115 return 1;
Pawel Zarembski 0:01f31e923fe2 116 }
Pawel Zarembski 0:01f31e923fe2 117
Pawel Zarembski 0:01f31e923fe2 118 int32_t uart_set_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 119 {
Pawel Zarembski 0:01f31e923fe2 120 uint8_t data_bits = 8;
Pawel Zarembski 0:01f31e923fe2 121 uint8_t parity_enable = 0;
Pawel Zarembski 0:01f31e923fe2 122 uint8_t parity_type = 0;
Pawel Zarembski 0:01f31e923fe2 123 uint32_t dll;
Pawel Zarembski 0:01f31e923fe2 124 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 125 NVIC_DisableIRQ(UART_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 126 UART->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 127 // Disable receiver and transmitter while updating
Pawel Zarembski 0:01f31e923fe2 128 UART->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
Pawel Zarembski 0:01f31e923fe2 129 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 130
Pawel Zarembski 0:01f31e923fe2 131 // set data bits, stop bits, parity
Pawel Zarembski 0:01f31e923fe2 132 if ((config->DataBits < 8) || (config->DataBits > 9)) {
Pawel Zarembski 0:01f31e923fe2 133 data_bits = 8;
Pawel Zarembski 0:01f31e923fe2 134 }
Pawel Zarembski 0:01f31e923fe2 135
Pawel Zarembski 0:01f31e923fe2 136 data_bits -= 8;
Pawel Zarembski 0:01f31e923fe2 137
Pawel Zarembski 0:01f31e923fe2 138 if (config->Parity == 1) {
Pawel Zarembski 0:01f31e923fe2 139 parity_enable = 1;
Pawel Zarembski 0:01f31e923fe2 140 parity_type = 1;
Pawel Zarembski 0:01f31e923fe2 141 data_bits++;
Pawel Zarembski 0:01f31e923fe2 142 } else if (config->Parity == 2) {
Pawel Zarembski 0:01f31e923fe2 143 parity_enable = 1;
Pawel Zarembski 0:01f31e923fe2 144 parity_type = 0;
Pawel Zarembski 0:01f31e923fe2 145 data_bits++;
Pawel Zarembski 0:01f31e923fe2 146 }
Pawel Zarembski 0:01f31e923fe2 147
Pawel Zarembski 0:01f31e923fe2 148 // does not support 10 bit data comm
Pawel Zarembski 0:01f31e923fe2 149 if (data_bits == 2) {
Pawel Zarembski 0:01f31e923fe2 150 data_bits = 0;
Pawel Zarembski 0:01f31e923fe2 151 parity_enable = 0;
Pawel Zarembski 0:01f31e923fe2 152 parity_type = 0;
Pawel Zarembski 0:01f31e923fe2 153 }
Pawel Zarembski 0:01f31e923fe2 154
Pawel Zarembski 0:01f31e923fe2 155 // data bits, parity and parity mode
Pawel Zarembski 0:01f31e923fe2 156 UART->C1 = data_bits << UART_C1_M_SHIFT |
Pawel Zarembski 0:01f31e923fe2 157 parity_enable << UART_C1_PE_SHIFT |
Pawel Zarembski 0:01f31e923fe2 158 parity_type << UART_C1_PT_SHIFT;
Pawel Zarembski 0:01f31e923fe2 159 dll = SystemCoreClock / (16 * config->Baudrate);
Pawel Zarembski 0:01f31e923fe2 160
Pawel Zarembski 0:01f31e923fe2 161 if (1 == UART_NUM || 2 == UART_NUM) {
Pawel Zarembski 0:01f31e923fe2 162 dll /= 2; //TODO <<= 1
Pawel Zarembski 0:01f31e923fe2 163 }
Pawel Zarembski 0:01f31e923fe2 164
Pawel Zarembski 0:01f31e923fe2 165 // set baudrate
Pawel Zarembski 0:01f31e923fe2 166 UART->BDH = (UART->BDH & ~(UART_BDH_SBR_MASK)) | ((dll >> 8) & UART_BDH_SBR_MASK);
Pawel Zarembski 0:01f31e923fe2 167 UART->BDL = (UART->BDL & ~(UART_BDL_SBR_MASK)) | (dll & UART_BDL_SBR_MASK);
Pawel Zarembski 0:01f31e923fe2 168 // Enable transmitter and receiver
Pawel Zarembski 0:01f31e923fe2 169 UART->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
Pawel Zarembski 0:01f31e923fe2 170 // Enable UART interrupt
Pawel Zarembski 0:01f31e923fe2 171 NVIC_ClearPendingIRQ(UART_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 172 NVIC_EnableIRQ(UART_RX_TX_IRQn);
Pawel Zarembski 0:01f31e923fe2 173 UART->C2 |= UART_C2_RIE_MASK;
Pawel Zarembski 0:01f31e923fe2 174 return 1;
Pawel Zarembski 0:01f31e923fe2 175 }
Pawel Zarembski 0:01f31e923fe2 176
Pawel Zarembski 0:01f31e923fe2 177 int32_t uart_get_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 178 {
Pawel Zarembski 0:01f31e923fe2 179 return 1;
Pawel Zarembski 0:01f31e923fe2 180 }
Pawel Zarembski 0:01f31e923fe2 181
Pawel Zarembski 0:01f31e923fe2 182 int32_t uart_write_free(void)
Pawel Zarembski 0:01f31e923fe2 183 {
Pawel Zarembski 0:01f31e923fe2 184 return circ_buf_count_free(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 185 }
Pawel Zarembski 0:01f31e923fe2 186
Pawel Zarembski 0:01f31e923fe2 187 int32_t uart_write_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 188 {
Pawel Zarembski 0:01f31e923fe2 189 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 190 uint32_t cnt;
Pawel Zarembski 0:01f31e923fe2 191
Pawel Zarembski 0:01f31e923fe2 192 cnt = circ_buf_write(&write_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 193
Pawel Zarembski 0:01f31e923fe2 194 // Atomically enable TX
Pawel Zarembski 0:01f31e923fe2 195 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 196 if (circ_buf_count_used(&write_buffer)) {
Pawel Zarembski 0:01f31e923fe2 197 UART->C2 |= UART_C2_TIE_MASK;
Pawel Zarembski 0:01f31e923fe2 198 }
Pawel Zarembski 0:01f31e923fe2 199 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 200
Pawel Zarembski 0:01f31e923fe2 201 return cnt;
Pawel Zarembski 0:01f31e923fe2 202 }
Pawel Zarembski 0:01f31e923fe2 203
Pawel Zarembski 0:01f31e923fe2 204 int32_t uart_read_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 205 {
Pawel Zarembski 0:01f31e923fe2 206 return circ_buf_read(&read_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 207 }
Pawel Zarembski 0:01f31e923fe2 208
Pawel Zarembski 0:01f31e923fe2 209 void uart_enable_flow_control(bool enabled)
Pawel Zarembski 0:01f31e923fe2 210 {
Pawel Zarembski 0:01f31e923fe2 211 // Flow control not implemented for this platform
Pawel Zarembski 0:01f31e923fe2 212 }
Pawel Zarembski 0:01f31e923fe2 213
Pawel Zarembski 0:01f31e923fe2 214 void UART_RX_TX_IRQHandler(void)
Pawel Zarembski 0:01f31e923fe2 215 {
Pawel Zarembski 0:01f31e923fe2 216 uint32_t s1;
Pawel Zarembski 0:01f31e923fe2 217 volatile uint8_t errorData;
Pawel Zarembski 0:01f31e923fe2 218 // read interrupt status
Pawel Zarembski 0:01f31e923fe2 219 s1 = UART->S1;
Pawel Zarembski 0:01f31e923fe2 220 // mask off interrupts that are not enabled
Pawel Zarembski 0:01f31e923fe2 221 if (!(UART->C2 & UART_C2_RIE_MASK)) {
Pawel Zarembski 0:01f31e923fe2 222 s1 &= ~UART_S1_RDRF_MASK;
Pawel Zarembski 0:01f31e923fe2 223 }
Pawel Zarembski 0:01f31e923fe2 224 if (!(UART->C2 & UART_C2_TIE_MASK)) {
Pawel Zarembski 0:01f31e923fe2 225 s1 &= ~UART_S1_TDRE_MASK;
Pawel Zarembski 0:01f31e923fe2 226 }
Pawel Zarembski 0:01f31e923fe2 227
Pawel Zarembski 0:01f31e923fe2 228 // handle character to transmit
Pawel Zarembski 0:01f31e923fe2 229 if (s1 & UART_S1_TDRE_MASK) {
Pawel Zarembski 0:01f31e923fe2 230 // Assert that there is data in the buffer
Pawel Zarembski 0:01f31e923fe2 231 util_assert(circ_buf_count_used(&write_buffer) > 0);
Pawel Zarembski 0:01f31e923fe2 232 // Send out data
Pawel Zarembski 0:01f31e923fe2 233 UART1->D = circ_buf_pop(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 234 // Turn off the transmitter if that was the last byte
Pawel Zarembski 0:01f31e923fe2 235 if (circ_buf_count_used(&write_buffer) == 0) {
Pawel Zarembski 0:01f31e923fe2 236 // disable TIE interrupt
Pawel Zarembski 0:01f31e923fe2 237 UART->C2 &= ~(UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 238 }
Pawel Zarembski 0:01f31e923fe2 239 }
Pawel Zarembski 0:01f31e923fe2 240
Pawel Zarembski 0:01f31e923fe2 241 // handle received character
Pawel Zarembski 0:01f31e923fe2 242 if (s1 & UART_S1_RDRF_MASK) {
Pawel Zarembski 0:01f31e923fe2 243 if ((s1 & UART_S1_NF_MASK) || (s1 & UART_S1_FE_MASK)) {
Pawel Zarembski 0:01f31e923fe2 244 errorData = UART->D;
Pawel Zarembski 0:01f31e923fe2 245 } else {
Pawel Zarembski 0:01f31e923fe2 246 uint32_t free;
Pawel Zarembski 0:01f31e923fe2 247 uint8_t data;
Pawel Zarembski 0:01f31e923fe2 248
Pawel Zarembski 0:01f31e923fe2 249 data = UART1->D;
Pawel Zarembski 0:01f31e923fe2 250 free = circ_buf_count_free(&read_buffer);
Pawel Zarembski 0:01f31e923fe2 251 if (free > RX_OVRF_MSG_SIZE) {
Pawel Zarembski 0:01f31e923fe2 252 circ_buf_push(&read_buffer, data);
Pawel Zarembski 0:01f31e923fe2 253 } else if (config_get_overflow_detect()) {
Pawel Zarembski 0:01f31e923fe2 254 if (RX_OVRF_MSG_SIZE == free) {
Pawel Zarembski 0:01f31e923fe2 255 circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE);
Pawel Zarembski 0:01f31e923fe2 256 } else {
Pawel Zarembski 0:01f31e923fe2 257 // Drop newest
Pawel Zarembski 0:01f31e923fe2 258 }
Pawel Zarembski 0:01f31e923fe2 259 } else {
Pawel Zarembski 0:01f31e923fe2 260 // Drop oldest
Pawel Zarembski 0:01f31e923fe2 261 circ_buf_pop(&read_buffer);
Pawel Zarembski 0:01f31e923fe2 262 circ_buf_push(&read_buffer, data);
Pawel Zarembski 0:01f31e923fe2 263 }
Pawel Zarembski 0:01f31e923fe2 264 }
Pawel Zarembski 0:01f31e923fe2 265 }
Pawel Zarembski 0:01f31e923fe2 266 }