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 * Copyright (c) 2016-2017 NXP
Pawel Zarembski 0:01f31e923fe2 8 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 9 *
Pawel Zarembski 0:01f31e923fe2 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 11 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 12 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 13 *
Pawel Zarembski 0:01f31e923fe2 14 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 15 *
Pawel Zarembski 0:01f31e923fe2 16 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 19 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 20 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 21 */
Pawel Zarembski 0:01f31e923fe2 22
Pawel Zarembski 0:01f31e923fe2 23 #include "string.h"
Pawel Zarembski 0:01f31e923fe2 24 #include "fsl_device_registers.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 #define UART_INSTANCE (UART0)
Pawel Zarembski 0:01f31e923fe2 32 #define UART_IRQ (UART0_RX_TX_IRQn)
Pawel Zarembski 0:01f31e923fe2 33
Pawel Zarembski 0:01f31e923fe2 34 extern uint32_t SystemCoreClock;
Pawel Zarembski 0:01f31e923fe2 35
Pawel Zarembski 0:01f31e923fe2 36 static void clear_buffers(void);
Pawel Zarembski 0:01f31e923fe2 37
Pawel Zarembski 0:01f31e923fe2 38 #define RX_OVRF_MSG "<DAPLink:Overflow>\n"
Pawel Zarembski 0:01f31e923fe2 39 #define RX_OVRF_MSG_SIZE (sizeof(RX_OVRF_MSG) - 1)
Pawel Zarembski 0:01f31e923fe2 40 #define BUFFER_SIZE (512)
Pawel Zarembski 0:01f31e923fe2 41
Pawel Zarembski 0:01f31e923fe2 42
Pawel Zarembski 0:01f31e923fe2 43 circ_buf_t write_buffer;
Pawel Zarembski 0:01f31e923fe2 44 uint8_t write_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 45 circ_buf_t read_buffer;
Pawel Zarembski 0:01f31e923fe2 46 uint8_t read_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 47
Pawel Zarembski 0:01f31e923fe2 48 void clear_buffers(void)
Pawel Zarembski 0:01f31e923fe2 49 {
Pawel Zarembski 0:01f31e923fe2 50 util_assert(!(UART_INSTANCE->C2 & UART_C2_TIE_MASK));
Pawel Zarembski 0:01f31e923fe2 51 circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data));
Pawel Zarembski 0:01f31e923fe2 52 circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data));
Pawel Zarembski 0:01f31e923fe2 53 }
Pawel Zarembski 0:01f31e923fe2 54
Pawel Zarembski 0:01f31e923fe2 55 int32_t uart_initialize(void)
Pawel Zarembski 0:01f31e923fe2 56 {
Pawel Zarembski 0:01f31e923fe2 57 NVIC_DisableIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 58 // enable clk PORTC
Pawel Zarembski 0:01f31e923fe2 59 SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
Pawel Zarembski 0:01f31e923fe2 60 // enable clk uart
Pawel Zarembski 0:01f31e923fe2 61 SIM->SCGC4 |= SIM_SCGC4_UART0_MASK;
Pawel Zarembski 0:01f31e923fe2 62
Pawel Zarembski 0:01f31e923fe2 63 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 64 NVIC_DisableIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 65 // transmitter and receiver disabled
Pawel Zarembski 0:01f31e923fe2 66 UART_INSTANCE->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
Pawel Zarembski 0:01f31e923fe2 67 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 68 UART_INSTANCE->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 69
Pawel Zarembski 0:01f31e923fe2 70 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 71
Pawel Zarembski 0:01f31e923fe2 72 // Enable receiver and transmitter
Pawel Zarembski 0:01f31e923fe2 73 UART_INSTANCE->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
Pawel Zarembski 0:01f31e923fe2 74
Pawel Zarembski 0:01f31e923fe2 75 // alternate 3: UART0
Pawel Zarembski 0:01f31e923fe2 76 PORTB->PCR[16] = PORT_PCR_MUX(3);
Pawel Zarembski 0:01f31e923fe2 77 PORTB->PCR[17] = PORT_PCR_MUX(3);
Pawel Zarembski 0:01f31e923fe2 78
Pawel Zarembski 0:01f31e923fe2 79 // Enable receive interrupt
Pawel Zarembski 0:01f31e923fe2 80 UART_INSTANCE->C2 |= UART_C2_RIE_MASK;
Pawel Zarembski 0:01f31e923fe2 81 NVIC_ClearPendingIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 82 NVIC_EnableIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 83
Pawel Zarembski 0:01f31e923fe2 84 return 1;
Pawel Zarembski 0:01f31e923fe2 85 }
Pawel Zarembski 0:01f31e923fe2 86
Pawel Zarembski 0:01f31e923fe2 87 int32_t uart_uninitialize(void)
Pawel Zarembski 0:01f31e923fe2 88 {
Pawel Zarembski 0:01f31e923fe2 89 // transmitter and receiver disabled
Pawel Zarembski 0:01f31e923fe2 90 UART_INSTANCE->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
Pawel Zarembski 0:01f31e923fe2 91 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 92 UART_INSTANCE->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 93 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 94 return 1;
Pawel Zarembski 0:01f31e923fe2 95 }
Pawel Zarembski 0:01f31e923fe2 96
Pawel Zarembski 0:01f31e923fe2 97 int32_t uart_reset(void)
Pawel Zarembski 0:01f31e923fe2 98 {
Pawel Zarembski 0:01f31e923fe2 99 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 100 NVIC_DisableIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 101 // disable TIE interrupt
Pawel Zarembski 0:01f31e923fe2 102 UART_INSTANCE->C2 &= ~(UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 103 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 104 // enable interrupt
Pawel Zarembski 0:01f31e923fe2 105 NVIC_EnableIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 106 return 1;
Pawel Zarembski 0:01f31e923fe2 107 }
Pawel Zarembski 0:01f31e923fe2 108
Pawel Zarembski 0:01f31e923fe2 109 int32_t uart_set_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 110 {
Pawel Zarembski 0:01f31e923fe2 111 uint8_t data_bits = 8;
Pawel Zarembski 0:01f31e923fe2 112 uint8_t parity_enable = 0;
Pawel Zarembski 0:01f31e923fe2 113 uint8_t parity_type = 0;
Pawel Zarembski 0:01f31e923fe2 114 uint32_t dll;
Pawel Zarembski 0:01f31e923fe2 115 // disable interrupt
Pawel Zarembski 0:01f31e923fe2 116 NVIC_DisableIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 117 UART_INSTANCE->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 118 // Disable receiver and transmitter while updating
Pawel Zarembski 0:01f31e923fe2 119 UART_INSTANCE->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
Pawel Zarembski 0:01f31e923fe2 120 clear_buffers();
Pawel Zarembski 0:01f31e923fe2 121
Pawel Zarembski 0:01f31e923fe2 122 // set data bits, stop bits, parity
Pawel Zarembski 0:01f31e923fe2 123 if ((config->DataBits < 8) || (config->DataBits > 9)) {
Pawel Zarembski 0:01f31e923fe2 124 data_bits = 8;
Pawel Zarembski 0:01f31e923fe2 125 }
Pawel Zarembski 0:01f31e923fe2 126
Pawel Zarembski 0:01f31e923fe2 127 data_bits -= 8;
Pawel Zarembski 0:01f31e923fe2 128
Pawel Zarembski 0:01f31e923fe2 129 if (config->Parity == 1) {
Pawel Zarembski 0:01f31e923fe2 130 parity_enable = 1;
Pawel Zarembski 0:01f31e923fe2 131 parity_type = 1;
Pawel Zarembski 0:01f31e923fe2 132 data_bits++;
Pawel Zarembski 0:01f31e923fe2 133 } else if (config->Parity == 2) {
Pawel Zarembski 0:01f31e923fe2 134 parity_enable = 1;
Pawel Zarembski 0:01f31e923fe2 135 parity_type = 0;
Pawel Zarembski 0:01f31e923fe2 136 data_bits++;
Pawel Zarembski 0:01f31e923fe2 137 }
Pawel Zarembski 0:01f31e923fe2 138
Pawel Zarembski 0:01f31e923fe2 139 // does not support 10 bit data comm
Pawel Zarembski 0:01f31e923fe2 140 if (data_bits == 2) {
Pawel Zarembski 0:01f31e923fe2 141 data_bits = 0;
Pawel Zarembski 0:01f31e923fe2 142 parity_enable = 0;
Pawel Zarembski 0:01f31e923fe2 143 parity_type = 0;
Pawel Zarembski 0:01f31e923fe2 144 }
Pawel Zarembski 0:01f31e923fe2 145
Pawel Zarembski 0:01f31e923fe2 146 // data bits, parity and parity mode
Pawel Zarembski 0:01f31e923fe2 147 UART_INSTANCE->C1 = data_bits << UART_C1_M_SHIFT
Pawel Zarembski 0:01f31e923fe2 148 | parity_enable << UART_C1_PE_SHIFT
Pawel Zarembski 0:01f31e923fe2 149 | parity_type << UART_C1_PT_SHIFT;
Pawel Zarembski 0:01f31e923fe2 150 dll = SystemCoreClock / (16 * config->Baudrate);
Pawel Zarembski 0:01f31e923fe2 151 // set baudrate
Pawel Zarembski 0:01f31e923fe2 152 UART_INSTANCE->BDH = (UART_INSTANCE->BDH & ~(UART_BDH_SBR_MASK)) | ((dll >> 8) & UART_BDH_SBR_MASK);
Pawel Zarembski 0:01f31e923fe2 153 UART_INSTANCE->BDL = (UART_INSTANCE->BDL & ~(UART_BDL_SBR_MASK)) | (dll & UART_BDL_SBR_MASK);
Pawel Zarembski 0:01f31e923fe2 154 // Enable transmitter and receiver
Pawel Zarembski 0:01f31e923fe2 155 UART_INSTANCE->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
Pawel Zarembski 0:01f31e923fe2 156 // Enable UART interrupt
Pawel Zarembski 0:01f31e923fe2 157 NVIC_ClearPendingIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 158 NVIC_EnableIRQ(UART_IRQ);
Pawel Zarembski 0:01f31e923fe2 159 UART_INSTANCE->C2 |= UART_C2_RIE_MASK;
Pawel Zarembski 0:01f31e923fe2 160 return 1;
Pawel Zarembski 0:01f31e923fe2 161 }
Pawel Zarembski 0:01f31e923fe2 162
Pawel Zarembski 0:01f31e923fe2 163 int32_t uart_get_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 164 {
Pawel Zarembski 0:01f31e923fe2 165 return 1;
Pawel Zarembski 0:01f31e923fe2 166 }
Pawel Zarembski 0:01f31e923fe2 167
Pawel Zarembski 0:01f31e923fe2 168 int32_t uart_write_free(void)
Pawel Zarembski 0:01f31e923fe2 169 {
Pawel Zarembski 0:01f31e923fe2 170 return circ_buf_count_free(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 171 }
Pawel Zarembski 0:01f31e923fe2 172
Pawel Zarembski 0:01f31e923fe2 173 int32_t uart_write_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 174 {
Pawel Zarembski 0:01f31e923fe2 175 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 176 uint32_t cnt;
Pawel Zarembski 0:01f31e923fe2 177
Pawel Zarembski 0:01f31e923fe2 178 cnt = circ_buf_write(&write_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 179
Pawel Zarembski 0:01f31e923fe2 180 // Atomically enable TX
Pawel Zarembski 0:01f31e923fe2 181 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 182 if (circ_buf_count_used(&write_buffer)) {
Pawel Zarembski 0:01f31e923fe2 183 UART_INSTANCE->C2 |= UART_C2_TIE_MASK;
Pawel Zarembski 0:01f31e923fe2 184 }
Pawel Zarembski 0:01f31e923fe2 185 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 186
Pawel Zarembski 0:01f31e923fe2 187 return cnt;
Pawel Zarembski 0:01f31e923fe2 188 }
Pawel Zarembski 0:01f31e923fe2 189
Pawel Zarembski 0:01f31e923fe2 190 int32_t uart_read_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 191 {
Pawel Zarembski 0:01f31e923fe2 192 return circ_buf_read(&read_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 193 }
Pawel Zarembski 0:01f31e923fe2 194
Pawel Zarembski 0:01f31e923fe2 195 void UART0_RX_TX_IRQHandler(void)
Pawel Zarembski 0:01f31e923fe2 196 {
Pawel Zarembski 0:01f31e923fe2 197 uint32_t s1;
Pawel Zarembski 0:01f31e923fe2 198 volatile uint8_t errorData;
Pawel Zarembski 0:01f31e923fe2 199 // read interrupt status
Pawel Zarembski 0:01f31e923fe2 200 s1 = UART_INSTANCE->S1;
Pawel Zarembski 0:01f31e923fe2 201 // mask off interrupts that are not enabled
Pawel Zarembski 0:01f31e923fe2 202 if (!(UART_INSTANCE->C2 & UART_C2_RIE_MASK)) {
Pawel Zarembski 0:01f31e923fe2 203 s1 &= ~UART_S1_RDRF_MASK;
Pawel Zarembski 0:01f31e923fe2 204 }
Pawel Zarembski 0:01f31e923fe2 205 if (!(UART_INSTANCE->C2 & UART_C2_TIE_MASK)) {
Pawel Zarembski 0:01f31e923fe2 206 s1 &= ~UART_S1_TDRE_MASK;
Pawel Zarembski 0:01f31e923fe2 207 }
Pawel Zarembski 0:01f31e923fe2 208
Pawel Zarembski 0:01f31e923fe2 209 // handle character to transmit
Pawel Zarembski 0:01f31e923fe2 210 if (s1 & UART_S1_TDRE_MASK) {
Pawel Zarembski 0:01f31e923fe2 211 // Assert that there is data in the buffer
Pawel Zarembski 0:01f31e923fe2 212 util_assert(circ_buf_count_used(&write_buffer) > 0);
Pawel Zarembski 0:01f31e923fe2 213
Pawel Zarembski 0:01f31e923fe2 214 // Send out data
Pawel Zarembski 0:01f31e923fe2 215 UART_INSTANCE->D = circ_buf_pop(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 216 // Turn off the transmitter if that was the last byte
Pawel Zarembski 0:01f31e923fe2 217 if (circ_buf_count_used(&write_buffer) == 0) {
Pawel Zarembski 0:01f31e923fe2 218 // disable TIE interrupt
Pawel Zarembski 0:01f31e923fe2 219 UART_INSTANCE->C2 &= ~(UART_C2_TIE_MASK);
Pawel Zarembski 0:01f31e923fe2 220 }
Pawel Zarembski 0:01f31e923fe2 221 }
Pawel Zarembski 0:01f31e923fe2 222
Pawel Zarembski 0:01f31e923fe2 223 // handle received character
Pawel Zarembski 0:01f31e923fe2 224 if (s1 & UART_S1_RDRF_MASK) {
Pawel Zarembski 0:01f31e923fe2 225 if ((s1 & UART_S1_NF_MASK) || (s1 & UART_S1_FE_MASK)) {
Pawel Zarembski 0:01f31e923fe2 226 errorData = UART_INSTANCE->D;
Pawel Zarembski 0:01f31e923fe2 227 } else {
Pawel Zarembski 0:01f31e923fe2 228 uint32_t free;
Pawel Zarembski 0:01f31e923fe2 229 uint8_t data;
Pawel Zarembski 0:01f31e923fe2 230
Pawel Zarembski 0:01f31e923fe2 231 data = UART_INSTANCE->D;
Pawel Zarembski 0:01f31e923fe2 232 free = circ_buf_count_free(&read_buffer);
Pawel Zarembski 0:01f31e923fe2 233 if (free > RX_OVRF_MSG_SIZE) {
Pawel Zarembski 0:01f31e923fe2 234 circ_buf_push(&read_buffer, data);
Pawel Zarembski 0:01f31e923fe2 235 } else if ((RX_OVRF_MSG_SIZE == free) && config_get_overflow_detect()) {
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 character
Pawel Zarembski 0:01f31e923fe2 239 }
Pawel Zarembski 0:01f31e923fe2 240 }
Pawel Zarembski 0:01f31e923fe2 241 }
Pawel Zarembski 0:01f31e923fe2 242 }