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