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 "sam3u.h"
Pawel Zarembski 0:01f31e923fe2 25 #include "uart.h"
Pawel Zarembski 0:01f31e923fe2 26 #include "circ_buf.h"
Pawel Zarembski 0:01f31e923fe2 27 #include "cortex_m.h"
Pawel Zarembski 0:01f31e923fe2 28 #include "util.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 BUFFER_SIZE 512
Pawel Zarembski 0:01f31e923fe2 32 #define _CPU_CLK_HZ 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
Pawel Zarembski 0:01f31e923fe2 37
Pawel Zarembski 0:01f31e923fe2 38 #define I8 int8_t
Pawel Zarembski 0:01f31e923fe2 39 #define I16 int16_t
Pawel Zarembski 0:01f31e923fe2 40 #define I32 int32_t
Pawel Zarembski 0:01f31e923fe2 41 #define U8 uint8_t
Pawel Zarembski 0:01f31e923fe2 42 #define U16 uint16_t
Pawel Zarembski 0:01f31e923fe2 43 #define U32 uint32_t
Pawel Zarembski 0:01f31e923fe2 44
Pawel Zarembski 0:01f31e923fe2 45 #define BIT_CDC_USB2UART_CTS (9)
Pawel Zarembski 0:01f31e923fe2 46 #define BIT_CDC_USB2UART_RTS (10)
Pawel Zarembski 0:01f31e923fe2 47
Pawel Zarembski 0:01f31e923fe2 48 #define UART_PID (8)
Pawel Zarembski 0:01f31e923fe2 49 #define UART_RX_PIN (11)
Pawel Zarembski 0:01f31e923fe2 50 #define UART_TX_PIN (12)
Pawel Zarembski 0:01f31e923fe2 51 #define UART_RXRDY_FLAG (1uL << 0) // Rx status flag
Pawel Zarembski 0:01f31e923fe2 52 #define UART_TXRDY_FLAG (1uL << 1) // Tx RDY Status flag
Pawel Zarembski 0:01f31e923fe2 53 #define UART_TXEMPTY_FLAG (1uL << 9) // Tx EMPTY Status flag
Pawel Zarembski 0:01f31e923fe2 54 #define UART_ENDTX_FLAG (1uL << 4) // Tx end flag
Pawel Zarembski 0:01f31e923fe2 55 #define UART_RX_ERR_FLAGS (0xE0) // Parity, framing, overrun error
Pawel Zarembski 0:01f31e923fe2 56 #define UART_TX_INT_FLAG UART_TXEMPTY_FLAG
Pawel Zarembski 0:01f31e923fe2 57 #define PIO_UART_PIN_MASK ((1uL << UART_RX_PIN) | (1uL << UART_TX_PIN))
Pawel Zarembski 0:01f31e923fe2 58
Pawel Zarembski 0:01f31e923fe2 59 #define PMC_BASE_ADDR (0x400E0400)
Pawel Zarembski 0:01f31e923fe2 60 #define PMC_PCER *(volatile U32*)(PMC_BASE_ADDR + 0x10) // Peripheral clock enable register
Pawel Zarembski 0:01f31e923fe2 61
Pawel Zarembski 0:01f31e923fe2 62 #define UART_BASE_ADDR (0x400E0600)
Pawel Zarembski 0:01f31e923fe2 63 #define OFF_UART_CR (0x00)
Pawel Zarembski 0:01f31e923fe2 64 #define OFF_UART_MR (0x04)
Pawel Zarembski 0:01f31e923fe2 65 #define OFF_UART_IER (0x08)
Pawel Zarembski 0:01f31e923fe2 66 #define OFF_UART_IDR (0x0C)
Pawel Zarembski 0:01f31e923fe2 67 #define OFF_UART_IMR (0x10)
Pawel Zarembski 0:01f31e923fe2 68 #define OFF_UART_SR (0x14)
Pawel Zarembski 0:01f31e923fe2 69 #define OFF_UART_RHR (0x18)
Pawel Zarembski 0:01f31e923fe2 70 #define OFF_UART_THR (0x1C)
Pawel Zarembski 0:01f31e923fe2 71 #define OFF_UART_BRGR (0x20)
Pawel Zarembski 0:01f31e923fe2 72 #define UART_CR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_CR)
Pawel Zarembski 0:01f31e923fe2 73 #define UART_MR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_MR)
Pawel Zarembski 0:01f31e923fe2 74 #define UART_IER *(volatile U32*)(UART_BASE_ADDR + OFF_UART_IER)
Pawel Zarembski 0:01f31e923fe2 75 #define UART_IDR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_IDR)
Pawel Zarembski 0:01f31e923fe2 76 #define UART_IMR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_IMR)
Pawel Zarembski 0:01f31e923fe2 77 #define UART_SR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_SR)
Pawel Zarembski 0:01f31e923fe2 78 #define UART_RHR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_RHR)
Pawel Zarembski 0:01f31e923fe2 79 #define UART_THR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_THR)
Pawel Zarembski 0:01f31e923fe2 80 #define UART_BRGR *(volatile U32*)(UART_BASE_ADDR + OFF_UART_BRGR)
Pawel Zarembski 0:01f31e923fe2 81 #define OFF_PDC_RPR (0x100)
Pawel Zarembski 0:01f31e923fe2 82 #define OFF_PDC_RCR (0x104)
Pawel Zarembski 0:01f31e923fe2 83 #define OFF_PDC_TPR (0x108)
Pawel Zarembski 0:01f31e923fe2 84 #define OFF_PDC_TCR (0x10C)
Pawel Zarembski 0:01f31e923fe2 85 #define OFF_PDC_RNPR (0x110)
Pawel Zarembski 0:01f31e923fe2 86 #define OFF_PDC_RNCR (0x114)
Pawel Zarembski 0:01f31e923fe2 87 #define OFF_PDC_TNPR (0x118)
Pawel Zarembski 0:01f31e923fe2 88 #define OFF_PDC_TNCR (0x11C)
Pawel Zarembski 0:01f31e923fe2 89 #define OFF_PDC_PTCR (0x120)
Pawel Zarembski 0:01f31e923fe2 90 #define OFF_PDC_PTSR (0x124)
Pawel Zarembski 0:01f31e923fe2 91 #define UART_PDC_RPR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_RPR)
Pawel Zarembski 0:01f31e923fe2 92 #define UART_PDC_RCR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_RCR)
Pawel Zarembski 0:01f31e923fe2 93 #define UART_PDC_TPR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_TPR)
Pawel Zarembski 0:01f31e923fe2 94 #define UART_PDC_TCR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_TCR)
Pawel Zarembski 0:01f31e923fe2 95 #define UART_PDC_RNPR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_RNPR)
Pawel Zarembski 0:01f31e923fe2 96 #define UART_PDC_RNCR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_RNCR)
Pawel Zarembski 0:01f31e923fe2 97 #define UART_PDC_TNPR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_TNPR)
Pawel Zarembski 0:01f31e923fe2 98 #define UART_PDC_TNCR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_TNCR)
Pawel Zarembski 0:01f31e923fe2 99 #define UART_PDC_PTCR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_PTCR)
Pawel Zarembski 0:01f31e923fe2 100 #define UART_PDC_PTSR *(volatile U32*)(UART_BASE_ADDR + OFF_PDC_PTSR)
Pawel Zarembski 0:01f31e923fe2 101
Pawel Zarembski 0:01f31e923fe2 102 #define PIOA_BASE_ADDR (0x400E0C00)
Pawel Zarembski 0:01f31e923fe2 103 #define PIOA_PDR (*(volatile U32*) (PIOA_BASE_ADDR + 0x04)) // PIO Disable Register
Pawel Zarembski 0:01f31e923fe2 104 #define PIOA_IFER (*(volatile U32*) (PIOA_BASE_ADDR + 0x20)) // Input Filter Enable Register
Pawel Zarembski 0:01f31e923fe2 105 #define PIOA_SODR (*(volatile U32*) (PIOA_BASE_ADDR + 0x30)) // Set output data
Pawel Zarembski 0:01f31e923fe2 106 #define PIOA_CODR (*(volatile U32*) (PIOA_BASE_ADDR + 0x34)) // Clear output data register
Pawel Zarembski 0:01f31e923fe2 107 #define PIOA_PDSR (*(volatile U32*) (PIOA_BASE_ADDR + 0x3c)) // pin data status register
Pawel Zarembski 0:01f31e923fe2 108 #define PIOA_IER (*(volatile U32*) (PIOA_BASE_ADDR + 0x40)) // Interrupt Enable Register
Pawel Zarembski 0:01f31e923fe2 109 #define PIOA_ISR (*(volatile U32*) (PIOA_BASE_ADDR + 0x4c)) // Interrupt Status Register
Pawel Zarembski 0:01f31e923fe2 110 #define PIOA_ABSR (*(volatile U32*) (PIOA_BASE_ADDR + 0x70)) // Peripheral AB Select Register
Pawel Zarembski 0:01f31e923fe2 111 #define PIOA_SCIFSR (*(volatile U32*) (PIOA_BASE_ADDR + 0x80)) // System Clock Glitch Input Filtering Select Register
Pawel Zarembski 0:01f31e923fe2 112 #define PIOA_AIMER (*(volatile U32*) (PIOA_BASE_ADDR + 0xB0)) // Additional Interrupt Modes Enable Register
Pawel Zarembski 0:01f31e923fe2 113 #define PIOA_ESR (*(volatile U32*) (PIOA_BASE_ADDR + 0xC0)) // Edge Select Register
Pawel Zarembski 0:01f31e923fe2 114 #define PIOA_FELLSR (*(volatile U32*) (PIOA_BASE_ADDR + 0xD0)) // Falling Edge/Low Level Select Register
Pawel Zarembski 0:01f31e923fe2 115 #define PIOA_REHLSR (*(volatile U32*) (PIOA_BASE_ADDR + 0xD4)) // Rising Edge/High Level Select Register
Pawel Zarembski 0:01f31e923fe2 116
Pawel Zarembski 0:01f31e923fe2 117 circ_buf_t write_buffer;
Pawel Zarembski 0:01f31e923fe2 118 uint8_t write_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 119 circ_buf_t read_buffer;
Pawel Zarembski 0:01f31e923fe2 120 uint8_t read_buffer_data[BUFFER_SIZE];
Pawel Zarembski 0:01f31e923fe2 121
Pawel Zarembski 0:01f31e923fe2 122 static U32 _Baudrate;
Pawel Zarembski 0:01f31e923fe2 123 static U8 _FlowControl;
Pawel Zarembski 0:01f31e923fe2 124 static U8 _UARTChar0; // Use static here since PDC starts transferring the byte when we already left this function
Pawel Zarembski 0:01f31e923fe2 125 static U32 _TxInProgress;
Pawel Zarembski 0:01f31e923fe2 126 static U8 _FlowControlEnabled = 1;
Pawel Zarembski 0:01f31e923fe2 127
Pawel Zarembski 0:01f31e923fe2 128 static U32 _DetermineDivider(U32 Baudrate)
Pawel Zarembski 0:01f31e923fe2 129 {
Pawel Zarembski 0:01f31e923fe2 130 U32 Div;
Pawel Zarembski 0:01f31e923fe2 131 //
Pawel Zarembski 0:01f31e923fe2 132 // Calculate divider for baudrate and round it correctly.
Pawel Zarembski 0:01f31e923fe2 133 // This is necessary to get a tolerance as small as possible.
Pawel Zarembski 0:01f31e923fe2 134 //
Pawel Zarembski 0:01f31e923fe2 135 Div = Baudrate << 4;
Pawel Zarembski 0:01f31e923fe2 136 Div = ((_CPU_CLK_HZ << 1) / Div) ;//+ 1;
Pawel Zarembski 0:01f31e923fe2 137 Div = Div >> 1;
Pawel Zarembski 0:01f31e923fe2 138 return Div;
Pawel Zarembski 0:01f31e923fe2 139 }
Pawel Zarembski 0:01f31e923fe2 140
Pawel Zarembski 0:01f31e923fe2 141 static int _SetBaudrate(U32 Baudrate)
Pawel Zarembski 0:01f31e923fe2 142 {
Pawel Zarembski 0:01f31e923fe2 143 U32 Div;
Pawel Zarembski 0:01f31e923fe2 144 Div = _DetermineDivider(Baudrate);
Pawel Zarembski 0:01f31e923fe2 145
Pawel Zarembski 0:01f31e923fe2 146 if (Div >= 1) {
Pawel Zarembski 0:01f31e923fe2 147 UART_BRGR = Div;
Pawel Zarembski 0:01f31e923fe2 148 _Baudrate = _CPU_CLK_HZ / Div / 16;
Pawel Zarembski 0:01f31e923fe2 149 return _Baudrate;
Pawel Zarembski 0:01f31e923fe2 150 }
Pawel Zarembski 0:01f31e923fe2 151
Pawel Zarembski 0:01f31e923fe2 152 return -1;
Pawel Zarembski 0:01f31e923fe2 153 }
Pawel Zarembski 0:01f31e923fe2 154
Pawel Zarembski 0:01f31e923fe2 155 static void _Send1(void)
Pawel Zarembski 0:01f31e923fe2 156 {
Pawel Zarembski 0:01f31e923fe2 157 // Assert that there is data in the buffer
Pawel Zarembski 0:01f31e923fe2 158 util_assert(circ_buf_count_used(&write_buffer) > 0);
Pawel Zarembski 0:01f31e923fe2 159
Pawel Zarembski 0:01f31e923fe2 160 //
Pawel Zarembski 0:01f31e923fe2 161 // Use PDC for transferring the byte to the UART since direct write to UART_THR does not seem to work properly.
Pawel Zarembski 0:01f31e923fe2 162 //
Pawel Zarembski 0:01f31e923fe2 163 PIOA->PIO_MDDR = (1 << UART_TX_PIN); //Disable open-drain on TX pin
Pawel Zarembski 0:01f31e923fe2 164 _UARTChar0 = circ_buf_pop(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 165
Pawel Zarembski 0:01f31e923fe2 166 _TxInProgress = 1;
Pawel Zarembski 0:01f31e923fe2 167 UART_PDC_TPR = (U32)&_UARTChar0;
Pawel Zarembski 0:01f31e923fe2 168 UART_PDC_TCR = 1;
Pawel Zarembski 0:01f31e923fe2 169 UART_PDC_PTCR = (1 << 8); // Enable transmission
Pawel Zarembski 0:01f31e923fe2 170 UART_IER = UART_TX_INT_FLAG; // enable Tx interrupt
Pawel Zarembski 0:01f31e923fe2 171 }
Pawel Zarembski 0:01f31e923fe2 172
Pawel Zarembski 0:01f31e923fe2 173 static void _ResetBuffers(void)
Pawel Zarembski 0:01f31e923fe2 174 {
Pawel Zarembski 0:01f31e923fe2 175 //TODO - assert that transmit is off
Pawel Zarembski 0:01f31e923fe2 176 circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data));
Pawel Zarembski 0:01f31e923fe2 177 circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data));
Pawel Zarembski 0:01f31e923fe2 178 _TxInProgress = 0;
Pawel Zarembski 0:01f31e923fe2 179 }
Pawel Zarembski 0:01f31e923fe2 180
Pawel Zarembski 0:01f31e923fe2 181 static int get_tx_ready()
Pawel Zarembski 0:01f31e923fe2 182 {
Pawel Zarembski 0:01f31e923fe2 183 if (!_FlowControlEnabled) {
Pawel Zarembski 0:01f31e923fe2 184 return 1;
Pawel Zarembski 0:01f31e923fe2 185 }
Pawel Zarembski 0:01f31e923fe2 186 return ((PIOA->PIO_PDSR >> BIT_CDC_USB2UART_CTS) & 1) == 0;
Pawel Zarembski 0:01f31e923fe2 187 }
Pawel Zarembski 0:01f31e923fe2 188
Pawel Zarembski 0:01f31e923fe2 189 static void set_rx_ready(int ready)
Pawel Zarembski 0:01f31e923fe2 190 {
Pawel Zarembski 0:01f31e923fe2 191 if (ready || !_FlowControlEnabled) {
Pawel Zarembski 0:01f31e923fe2 192 PIOA->PIO_CODR = 1 << BIT_CDC_USB2UART_RTS;
Pawel Zarembski 0:01f31e923fe2 193 } else {
Pawel Zarembski 0:01f31e923fe2 194 PIOA->PIO_SODR = 1 << BIT_CDC_USB2UART_RTS;
Pawel Zarembski 0:01f31e923fe2 195 }
Pawel Zarembski 0:01f31e923fe2 196 }
Pawel Zarembski 0:01f31e923fe2 197
Pawel Zarembski 0:01f31e923fe2 198 void UART_IntrEna(void)
Pawel Zarembski 0:01f31e923fe2 199 {
Pawel Zarembski 0:01f31e923fe2 200 NVIC_EnableIRQ(UART_IRQn); // Enable USB interrupt
Pawel Zarembski 0:01f31e923fe2 201 }
Pawel Zarembski 0:01f31e923fe2 202
Pawel Zarembski 0:01f31e923fe2 203 void UART_IntrDis(void)
Pawel Zarembski 0:01f31e923fe2 204 {
Pawel Zarembski 0:01f31e923fe2 205 NVIC_DisableIRQ(UART_IRQn); // Enable USB interrupt
Pawel Zarembski 0:01f31e923fe2 206 }
Pawel Zarembski 0:01f31e923fe2 207
Pawel Zarembski 0:01f31e923fe2 208 void uart_set_control_line_state(uint16_t ctrl_bmp)
Pawel Zarembski 0:01f31e923fe2 209 {
Pawel Zarembski 0:01f31e923fe2 210 }
Pawel Zarembski 0:01f31e923fe2 211
Pawel Zarembski 0:01f31e923fe2 212 void uart_software_flow_control()
Pawel Zarembski 0:01f31e923fe2 213 {
Pawel Zarembski 0:01f31e923fe2 214 int v;
Pawel Zarembski 0:01f31e923fe2 215
Pawel Zarembski 0:01f31e923fe2 216 if (((PIOA->PIO_PDSR >> BIT_CDC_USB2UART_CTS) & 1) == 0) {
Pawel Zarembski 0:01f31e923fe2 217 _TxInProgress = 0;
Pawel Zarembski 0:01f31e923fe2 218 v = circ_buf_count_used(&write_buffer); // NumBytes in write buffer
Pawel Zarembski 0:01f31e923fe2 219
Pawel Zarembski 0:01f31e923fe2 220 if (v == 0) { // No more characters to send ?: Disable further tx interrupts
Pawel Zarembski 0:01f31e923fe2 221 UART_IER = UART_TX_INT_FLAG;
Pawel Zarembski 0:01f31e923fe2 222 } else {
Pawel Zarembski 0:01f31e923fe2 223 _Send1(); //More bytes to send? Trigger sending of next byte
Pawel Zarembski 0:01f31e923fe2 224 }
Pawel Zarembski 0:01f31e923fe2 225
Pawel Zarembski 0:01f31e923fe2 226 } else {
Pawel Zarembski 0:01f31e923fe2 227 UART_IDR = UART_TX_INT_FLAG;
Pawel Zarembski 0:01f31e923fe2 228 }
Pawel Zarembski 0:01f31e923fe2 229 }
Pawel Zarembski 0:01f31e923fe2 230
Pawel Zarembski 0:01f31e923fe2 231 int32_t uart_initialize(void)
Pawel Zarembski 0:01f31e923fe2 232 {
Pawel Zarembski 0:01f31e923fe2 233 //
Pawel Zarembski 0:01f31e923fe2 234 // Initially, disable UART interrupt
Pawel Zarembski 0:01f31e923fe2 235 //
Pawel Zarembski 0:01f31e923fe2 236 UART_IntrDis();
Pawel Zarembski 0:01f31e923fe2 237 PMC->PMC_WPMR = 0x504D4300; // Disable write protect
Pawel Zarembski 0:01f31e923fe2 238 PMC->PMC_PCER0 = (1 << UART_PID) | (1 << 10); // Enable peripheral clock for UART + PIOA
Pawel Zarembski 0:01f31e923fe2 239 PMC->PMC_WPMR = 0x504D4301; // Enable write protect
Pawel Zarembski 0:01f31e923fe2 240 PIOA_PDR = PIO_UART_PIN_MASK; // Enable peripheral output signals (disable PIO Port A)
Pawel Zarembski 0:01f31e923fe2 241 PIOA_ABSR &= ~PIO_UART_PIN_MASK; // Select "A" peripherals on PIO A (UART Rx, Tx)
Pawel Zarembski 0:01f31e923fe2 242 PIOA->PIO_MDER = PIO_UART_PIN_MASK; //Enable Multi Drive Control (Open Drain) on the UART Lines so that they don't power nRF51
Pawel Zarembski 0:01f31e923fe2 243 UART_CR = (0)
Pawel Zarembski 0:01f31e923fe2 244 | (1 << 2) // RSTRX: Reset Receiver: 1 = The receiver logic is reset.
Pawel Zarembski 0:01f31e923fe2 245 | (1 << 3) // RSTTX: Reset Transmitter: 1 = The transmitter logic is reset.
Pawel Zarembski 0:01f31e923fe2 246 ;
Pawel Zarembski 0:01f31e923fe2 247 UART_CR = (0)
Pawel Zarembski 0:01f31e923fe2 248 | (0 << 2) // RSTRX: Release Receiver reset
Pawel Zarembski 0:01f31e923fe2 249 | (0 << 3) // RSTTX: Release Transmitter reset
Pawel Zarembski 0:01f31e923fe2 250 | (1 << 4) // RXEN: Receiver Enable
Pawel Zarembski 0:01f31e923fe2 251 | (0 << 5) // RXDIS: Do not disable receiver
Pawel Zarembski 0:01f31e923fe2 252 | (1 << 6) // TXEN: Transmitter Enable
Pawel Zarembski 0:01f31e923fe2 253 | (0 << 7) // TXDIS: Do not disable transmitter
Pawel Zarembski 0:01f31e923fe2 254 | (1 << 8) // RSTSTA: Reset status/error bits
Pawel Zarembski 0:01f31e923fe2 255 ;
Pawel Zarembski 0:01f31e923fe2 256 UART_MR = (0)
Pawel Zarembski 0:01f31e923fe2 257 | (4 << 9) // PAR: Parity Type: 4 => No parity
Pawel Zarembski 0:01f31e923fe2 258 | (0 << 14) // CHMODE: Channel Mode: 0 => Normal mode
Pawel Zarembski 0:01f31e923fe2 259 ;
Pawel Zarembski 0:01f31e923fe2 260 _SetBaudrate(9600);
Pawel Zarembski 0:01f31e923fe2 261 _FlowControl = UART_FLOW_CONTROL_NONE;
Pawel Zarembski 0:01f31e923fe2 262 UART_IDR = (0xFFFFFFFF); // Disable all interrupts
Pawel Zarembski 0:01f31e923fe2 263 //
Pawel Zarembski 0:01f31e923fe2 264 // Reset all status variables
Pawel Zarembski 0:01f31e923fe2 265 //
Pawel Zarembski 0:01f31e923fe2 266 _ResetBuffers();
Pawel Zarembski 0:01f31e923fe2 267 //
Pawel Zarembski 0:01f31e923fe2 268 // Enable UART Tx/Rx interrupts
Pawel Zarembski 0:01f31e923fe2 269 //
Pawel Zarembski 0:01f31e923fe2 270 UART_IER = (0)
Pawel Zarembski 0:01f31e923fe2 271 | (1 << 0) // Enable Rx Interrupt
Pawel Zarembski 0:01f31e923fe2 272 | (0 << 9) // Initially disable TxEmpty Interrupt
Pawel Zarembski 0:01f31e923fe2 273 | (0 << 4) // Initially disable ENDTx Interrupt
Pawel Zarembski 0:01f31e923fe2 274 ;
Pawel Zarembski 0:01f31e923fe2 275 //
Pawel Zarembski 0:01f31e923fe2 276 //Set "RTS" to LOW to indicate that we are ready to receive
Pawel Zarembski 0:01f31e923fe2 277 //
Pawel Zarembski 0:01f31e923fe2 278 PIOA_CODR = (1uL << BIT_CDC_USB2UART_RTS); // RTS low: Ready to receive data
Pawel Zarembski 0:01f31e923fe2 279 PIOA->PIO_OER = (1uL << BIT_CDC_USB2UART_RTS); // Pins == output
Pawel Zarembski 0:01f31e923fe2 280 PIOA->PIO_PER = (1uL << BIT_CDC_USB2UART_RTS); // Pins == GPIO control
Pawel Zarembski 0:01f31e923fe2 281 //Set CTS as input
Pawel Zarembski 0:01f31e923fe2 282 PIOA->PIO_PER = (1uL << BIT_CDC_USB2UART_CTS); // Pins == GPIO control
Pawel Zarembski 0:01f31e923fe2 283 PIOA->PIO_ODR = (1uL << BIT_CDC_USB2UART_CTS); // Pins == Input
Pawel Zarembski 0:01f31e923fe2 284 PIOA->PIO_IER = (1uL << BIT_CDC_USB2UART_CTS);
Pawel Zarembski 0:01f31e923fe2 285 //
Pawel Zarembski 0:01f31e923fe2 286 // Finally, re-enable UART interrupt
Pawel Zarembski 0:01f31e923fe2 287 //
Pawel Zarembski 0:01f31e923fe2 288 //NVIC_SetPriority(UART_IRQn, 1);
Pawel Zarembski 0:01f31e923fe2 289 UART_IntrEna();
Pawel Zarembski 0:01f31e923fe2 290 return 1; // O.K. ???
Pawel Zarembski 0:01f31e923fe2 291 }
Pawel Zarembski 0:01f31e923fe2 292
Pawel Zarembski 0:01f31e923fe2 293 int32_t uart_uninitialize(void)
Pawel Zarembski 0:01f31e923fe2 294 {
Pawel Zarembski 0:01f31e923fe2 295 UART_IntrDis();
Pawel Zarembski 0:01f31e923fe2 296 UART_IDR = (0xFFFFFFFF); // Disable all interrupts
Pawel Zarembski 0:01f31e923fe2 297 _ResetBuffers();
Pawel Zarembski 0:01f31e923fe2 298 return 1;
Pawel Zarembski 0:01f31e923fe2 299 }
Pawel Zarembski 0:01f31e923fe2 300
Pawel Zarembski 0:01f31e923fe2 301 int32_t uart_reset(void)
Pawel Zarembski 0:01f31e923fe2 302 {
Pawel Zarembski 0:01f31e923fe2 303 uart_initialize();
Pawel Zarembski 0:01f31e923fe2 304 return 1;
Pawel Zarembski 0:01f31e923fe2 305 }
Pawel Zarembski 0:01f31e923fe2 306
Pawel Zarembski 0:01f31e923fe2 307 int32_t uart_set_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 308 {
Pawel Zarembski 0:01f31e923fe2 309 //
Pawel Zarembski 0:01f31e923fe2 310 // UART always works with no parity, 1-stop bit
Pawel Zarembski 0:01f31e923fe2 311 // Parity bit is configurable but not used in current implementation
Pawel Zarembski 0:01f31e923fe2 312 //
Pawel Zarembski 0:01f31e923fe2 313 UART_IntrDis();
Pawel Zarembski 0:01f31e923fe2 314 UART_IDR = (0xFFFFFFFF); // Disable all interrupts
Pawel Zarembski 0:01f31e923fe2 315 UART_CR = (0)
Pawel Zarembski 0:01f31e923fe2 316 | (1 << 5) // RXDIS: Disable receiver
Pawel Zarembski 0:01f31e923fe2 317 | (1 << 7) // TXDIS: Disable transmitter
Pawel Zarembski 0:01f31e923fe2 318 | (1 << 8) // RSTSTA: Reset status/error bits
Pawel Zarembski 0:01f31e923fe2 319 ;
Pawel Zarembski 0:01f31e923fe2 320 _FlowControl = config->FlowControl;
Pawel Zarembski 0:01f31e923fe2 321 _SetBaudrate(config->Baudrate);
Pawel Zarembski 0:01f31e923fe2 322 UART_CR = (0)
Pawel Zarembski 0:01f31e923fe2 323 | (0 << 2) // RSTRX: Release Receiver reset
Pawel Zarembski 0:01f31e923fe2 324 | (0 << 3) // RSTTX: Release Transmitter reset
Pawel Zarembski 0:01f31e923fe2 325 | (1 << 4) // RXEN: Receiver Enable
Pawel Zarembski 0:01f31e923fe2 326 | (0 << 5) // RXDIS: Do not disable receiver
Pawel Zarembski 0:01f31e923fe2 327 | (1 << 6) // TXEN: Transmitter Enable
Pawel Zarembski 0:01f31e923fe2 328 | (0 << 7) // TXDIS: Do not disable transmitter
Pawel Zarembski 0:01f31e923fe2 329 | (1 << 8) // RSTSTA: Reset status/error bits
Pawel Zarembski 0:01f31e923fe2 330 ;
Pawel Zarembski 0:01f31e923fe2 331 UART_IER = (0)
Pawel Zarembski 0:01f31e923fe2 332 | (1 << 0) // Enable Rx Interrupt
Pawel Zarembski 0:01f31e923fe2 333 | (0 << 9) // Initially disable TxEmpty Interrupt
Pawel Zarembski 0:01f31e923fe2 334 | (0 << 4) // Initially disable ENDTx Interrupt
Pawel Zarembski 0:01f31e923fe2 335 ;
Pawel Zarembski 0:01f31e923fe2 336 _ResetBuffers();
Pawel Zarembski 0:01f31e923fe2 337 UART_IntrEna();
Pawel Zarembski 0:01f31e923fe2 338 return 1;
Pawel Zarembski 0:01f31e923fe2 339 }
Pawel Zarembski 0:01f31e923fe2 340
Pawel Zarembski 0:01f31e923fe2 341
Pawel Zarembski 0:01f31e923fe2 342 int32_t uart_get_configuration(UART_Configuration *config)
Pawel Zarembski 0:01f31e923fe2 343 {
Pawel Zarembski 0:01f31e923fe2 344 config->Baudrate = _Baudrate;
Pawel Zarembski 0:01f31e923fe2 345 config->DataBits = UART_DATA_BITS_8;
Pawel Zarembski 0:01f31e923fe2 346 config->FlowControl = (UART_FlowControl) _FlowControl;//UART_FLOW_CONTROL_NONE;
Pawel Zarembski 0:01f31e923fe2 347 config->Parity = UART_PARITY_NONE;
Pawel Zarembski 0:01f31e923fe2 348 config->StopBits = UART_STOP_BITS_1;
Pawel Zarembski 0:01f31e923fe2 349 return 1;
Pawel Zarembski 0:01f31e923fe2 350 }
Pawel Zarembski 0:01f31e923fe2 351
Pawel Zarembski 0:01f31e923fe2 352 int32_t uart_write_free(void)
Pawel Zarembski 0:01f31e923fe2 353 {
Pawel Zarembski 0:01f31e923fe2 354 return circ_buf_count_free(&write_buffer);
Pawel Zarembski 0:01f31e923fe2 355 }
Pawel Zarembski 0:01f31e923fe2 356
Pawel Zarembski 0:01f31e923fe2 357
Pawel Zarembski 0:01f31e923fe2 358 int32_t uart_write_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 359 {
Pawel Zarembski 0:01f31e923fe2 360 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 361 uint32_t cnt;
Pawel Zarembski 0:01f31e923fe2 362
Pawel Zarembski 0:01f31e923fe2 363 cnt = circ_buf_write(&write_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 364
Pawel Zarembski 0:01f31e923fe2 365 //
Pawel Zarembski 0:01f31e923fe2 366 // Atomically trigger transfer if not already in progress
Pawel Zarembski 0:01f31e923fe2 367 //
Pawel Zarembski 0:01f31e923fe2 368 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 369 if (_TxInProgress == 0 && get_tx_ready()) {
Pawel Zarembski 0:01f31e923fe2 370 _Send1();
Pawel Zarembski 0:01f31e923fe2 371 }
Pawel Zarembski 0:01f31e923fe2 372 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 373
Pawel Zarembski 0:01f31e923fe2 374 return cnt;
Pawel Zarembski 0:01f31e923fe2 375 }
Pawel Zarembski 0:01f31e923fe2 376
Pawel Zarembski 0:01f31e923fe2 377 int32_t uart_read_data(uint8_t *data, uint16_t size)
Pawel Zarembski 0:01f31e923fe2 378 {
Pawel Zarembski 0:01f31e923fe2 379 cortex_int_state_t state;
Pawel Zarembski 0:01f31e923fe2 380 uint32_t cnt;
Pawel Zarembski 0:01f31e923fe2 381
Pawel Zarembski 0:01f31e923fe2 382 cnt = circ_buf_read(&read_buffer, data, size);
Pawel Zarembski 0:01f31e923fe2 383
Pawel Zarembski 0:01f31e923fe2 384 // Atomically check if RTS had been asserted, if there is space on the buffer then deassert RTS
Pawel Zarembski 0:01f31e923fe2 385 state = cortex_int_get_and_disable();
Pawel Zarembski 0:01f31e923fe2 386 if (circ_buf_count_free(&read_buffer) > RX_OVRF_MSG_SIZE) {
Pawel Zarembski 0:01f31e923fe2 387 set_rx_ready(1);
Pawel Zarembski 0:01f31e923fe2 388 }
Pawel Zarembski 0:01f31e923fe2 389 cortex_int_restore(state);
Pawel Zarembski 0:01f31e923fe2 390
Pawel Zarembski 0:01f31e923fe2 391 return cnt;
Pawel Zarembski 0:01f31e923fe2 392 }
Pawel Zarembski 0:01f31e923fe2 393
Pawel Zarembski 0:01f31e923fe2 394 void uart_enable_flow_control(bool enabled)
Pawel Zarembski 0:01f31e923fe2 395 {
Pawel Zarembski 0:01f31e923fe2 396 _FlowControlEnabled = (U8)enabled;
Pawel Zarembski 0:01f31e923fe2 397 }
Pawel Zarembski 0:01f31e923fe2 398
Pawel Zarembski 0:01f31e923fe2 399 void UART_IRQHandler(void)
Pawel Zarembski 0:01f31e923fe2 400 {
Pawel Zarembski 0:01f31e923fe2 401 int Status;
Pawel Zarembski 0:01f31e923fe2 402 int32_t cnt;
Pawel Zarembski 0:01f31e923fe2 403 U8 data;
Pawel Zarembski 0:01f31e923fe2 404 Status = UART_SR; // Examine status register
Pawel Zarembski 0:01f31e923fe2 405
Pawel Zarembski 0:01f31e923fe2 406 if (Status & UART_RX_ERR_FLAGS) { // In case of error: Set RSTSTA to reset status bits PARE, FRAME, OVRE and RXBRK
Pawel Zarembski 0:01f31e923fe2 407 UART_CR = (1 << 8);
Pawel Zarembski 0:01f31e923fe2 408 }
Pawel Zarembski 0:01f31e923fe2 409
Pawel Zarembski 0:01f31e923fe2 410 //
Pawel Zarembski 0:01f31e923fe2 411 // Handle Rx event
Pawel Zarembski 0:01f31e923fe2 412 //
Pawel Zarembski 0:01f31e923fe2 413 if (Status & UART_RXRDY_FLAG) { // Data received?
Pawel Zarembski 0:01f31e923fe2 414 data = UART_RHR;
Pawel Zarembski 0:01f31e923fe2 415 cnt = (int32_t)circ_buf_count_free(&read_buffer) - RX_OVRF_MSG_SIZE;
Pawel Zarembski 0:01f31e923fe2 416 if (cnt > 0) {
Pawel Zarembski 0:01f31e923fe2 417 circ_buf_push(&read_buffer, data);
Pawel Zarembski 0:01f31e923fe2 418 } else if (config_get_overflow_detect()) {
Pawel Zarembski 0:01f31e923fe2 419 if (0 == cnt) {
Pawel Zarembski 0:01f31e923fe2 420 circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE);
Pawel Zarembski 0:01f31e923fe2 421 } else {
Pawel Zarembski 0:01f31e923fe2 422 // Drop newest
Pawel Zarembski 0:01f31e923fe2 423 }
Pawel Zarembski 0:01f31e923fe2 424 } else {
Pawel Zarembski 0:01f31e923fe2 425 // Drop oldest
Pawel Zarembski 0:01f31e923fe2 426 circ_buf_pop(&read_buffer);
Pawel Zarembski 0:01f31e923fe2 427 circ_buf_push(&read_buffer, data);
Pawel Zarembski 0:01f31e923fe2 428 }
Pawel Zarembski 0:01f31e923fe2 429
Pawel Zarembski 0:01f31e923fe2 430 //If this was the last available byte on the buffer then assert RTS
Pawel Zarembski 0:01f31e923fe2 431 if (cnt == 1) {
Pawel Zarembski 0:01f31e923fe2 432 set_rx_ready(0);
Pawel Zarembski 0:01f31e923fe2 433 }
Pawel Zarembski 0:01f31e923fe2 434 }
Pawel Zarembski 0:01f31e923fe2 435
Pawel Zarembski 0:01f31e923fe2 436 //
Pawel Zarembski 0:01f31e923fe2 437 // Handle Tx event
Pawel Zarembski 0:01f31e923fe2 438 //
Pawel Zarembski 0:01f31e923fe2 439 if (Status & UART_IMR & UART_TX_INT_FLAG) { // Byte has been send by UART
Pawel Zarembski 0:01f31e923fe2 440 cnt = circ_buf_count_used(&write_buffer); // NumBytes in write buffer
Pawel Zarembski 0:01f31e923fe2 441 if (cnt == 0) { // No more characters to send ?: Disable further tx interrupts
Pawel Zarembski 0:01f31e923fe2 442 UART_IDR = UART_TX_INT_FLAG;
Pawel Zarembski 0:01f31e923fe2 443 PIOA->PIO_MDER = (1 << UART_TX_PIN); //enable open-drain
Pawel Zarembski 0:01f31e923fe2 444 _TxInProgress = 0;
Pawel Zarembski 0:01f31e923fe2 445 } else if (get_tx_ready()) {
Pawel Zarembski 0:01f31e923fe2 446 _Send1(); //More bytes to send? Trigger sending of next byte
Pawel Zarembski 0:01f31e923fe2 447 } else {
Pawel Zarembski 0:01f31e923fe2 448 UART_IDR = UART_TX_INT_FLAG; // disable Tx interrupt
Pawel Zarembski 0:01f31e923fe2 449 PIOA->PIO_MDER = (1 << UART_TX_PIN); //enable open-drain
Pawel Zarembski 0:01f31e923fe2 450 }
Pawel Zarembski 0:01f31e923fe2 451 }
Pawel Zarembski 0:01f31e923fe2 452 }