Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uart.c Source File

uart.c

00001 /**
00002  * @file    uart.c
00003  * @brief   
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "string.h"
00023 
00024 #include "MK20D5.h"
00025 #include "uart.h"
00026 #include "util.h"
00027 #include "cortex_m.h"
00028 #include "circ_buf.h"
00029 #include "settings.h" // for config_get_overflow_detect
00030 
00031 extern uint32_t SystemCoreClock;
00032 
00033 static void clear_buffers(void);
00034 
00035 #define RX_OVRF_MSG         "<DAPLink:Overflow>\n"
00036 #define RX_OVRF_MSG_SIZE    (sizeof(RX_OVRF_MSG) - 1)
00037 #define BUFFER_SIZE         (512)
00038 
00039 
00040 circ_buf_t write_buffer;
00041 uint8_t write_buffer_data[BUFFER_SIZE];
00042 circ_buf_t read_buffer;
00043 uint8_t read_buffer_data[BUFFER_SIZE];
00044 
00045 void clear_buffers(void)
00046 {
00047     util_assert(!(UART1->C2 & UART_C2_TIE_MASK));
00048     circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data));
00049     circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data));
00050 }
00051 
00052 int32_t uart_initialize(void)
00053 {
00054     NVIC_DisableIRQ(UART1_RX_TX_IRQn);
00055     // enable clk PORTC
00056     SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
00057     // enable clk uart
00058     SIM->SCGC4 |= SIM_SCGC4_UART1_MASK;
00059 
00060     // disable interrupt
00061     NVIC_DisableIRQ(UART1_RX_TX_IRQn);
00062     // transmitter and receiver disabled
00063     UART1->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
00064     // disable interrupt
00065     UART1->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
00066     
00067     clear_buffers();
00068 
00069     // Enable receiver and transmitter
00070     UART1->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
00071     // alternate 3: UART1
00072     PORTC->PCR[3] = (3 << 8);
00073     PORTC->PCR[4] = (3 << 8);
00074     // Enable receive interrupt
00075     UART1->C2 |= UART_C2_RIE_MASK;
00076     NVIC_ClearPendingIRQ(UART1_RX_TX_IRQn);
00077     NVIC_EnableIRQ(UART1_RX_TX_IRQn);
00078     return 1;
00079 }
00080 
00081 int32_t uart_uninitialize(void)
00082 {
00083     // transmitter and receiver disabled
00084     UART1->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
00085     // disable interrupt
00086     UART1->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
00087     clear_buffers();
00088     return 1;
00089 }
00090 
00091 int32_t uart_reset(void)
00092 {
00093     // disable interrupt
00094     NVIC_DisableIRQ(UART1_RX_TX_IRQn);
00095     // disable TIE interrupt
00096     UART1->C2 &= ~(UART_C2_TIE_MASK);
00097     clear_buffers();
00098     // enable interrupt
00099     NVIC_EnableIRQ(UART1_RX_TX_IRQn);
00100     return 1;
00101 }
00102 
00103 int32_t uart_set_configuration(UART_Configuration *config)
00104 {
00105     uint8_t data_bits = 8;
00106     uint8_t parity_enable = 0;
00107     uint8_t parity_type = 0;
00108     uint32_t dll;
00109     // disable interrupt
00110     NVIC_DisableIRQ(UART1_RX_TX_IRQn);
00111     UART1->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
00112     // Disable receiver and transmitter while updating
00113     UART1->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
00114     clear_buffers();
00115 
00116     // set data bits, stop bits, parity
00117     if ((config->DataBits < 8) || (config->DataBits > 9)) {
00118         data_bits = 8;
00119     }
00120 
00121     data_bits -= 8;
00122 
00123     if (config->Parity == 1) {
00124         parity_enable = 1;
00125         parity_type = 1;
00126         data_bits++;
00127     } else if (config->Parity == 2) {
00128         parity_enable = 1;
00129         parity_type = 0;
00130         data_bits++;
00131     }
00132 
00133     // does not support 10 bit data comm
00134     if (data_bits == 2) {
00135         data_bits = 0;
00136         parity_enable = 0;
00137         parity_type = 0;
00138     }
00139 
00140     // data bits, parity and parity mode
00141     UART1->C1 = data_bits << UART_C1_M_SHIFT
00142                 | parity_enable << UART_C1_PE_SHIFT
00143                 | parity_type << UART_C1_PT_SHIFT;
00144     dll =  SystemCoreClock / (16 * config->Baudrate);
00145     // set baudrate
00146     UART1->BDH = (UART1->BDH & ~(UART_BDH_SBR_MASK)) | ((dll >> 8) & UART_BDH_SBR_MASK);
00147     UART1->BDL = (UART1->BDL & ~(UART_BDL_SBR_MASK)) | (dll & UART_BDL_SBR_MASK);
00148     // Enable transmitter and receiver
00149     UART1->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
00150     // Enable UART interrupt
00151     NVIC_ClearPendingIRQ(UART1_RX_TX_IRQn);
00152     NVIC_EnableIRQ(UART1_RX_TX_IRQn);
00153     UART1->C2 |= UART_C2_RIE_MASK;
00154     return 1;
00155 }
00156 
00157 int32_t uart_get_configuration(UART_Configuration *config)
00158 {
00159     return 1;
00160 }
00161 
00162 int32_t uart_write_free(void)
00163 {
00164     return circ_buf_count_free(&write_buffer);
00165 }
00166 
00167 int32_t uart_write_data(uint8_t *data, uint16_t size)
00168 {
00169     cortex_int_state_t state;
00170     uint32_t cnt;
00171 
00172     cnt = circ_buf_write(&write_buffer, data, size);
00173 
00174     // Atomically enable TX
00175     state = cortex_int_get_and_disable();
00176     if (circ_buf_count_used(&write_buffer)) {
00177         UART1->C2 |= UART_C2_TIE_MASK;
00178     }
00179     cortex_int_restore(state);
00180 
00181     return cnt;
00182 }
00183 
00184 int32_t uart_read_data(uint8_t *data, uint16_t size)
00185 {
00186     return circ_buf_read(&read_buffer, data, size);
00187 }
00188 
00189 void uart_enable_flow_control(bool enabled)
00190 {
00191     // Flow control not implemented for this platform
00192 }
00193 
00194 void UART1_RX_TX_IRQHandler(void)
00195 {
00196     uint32_t s1;
00197     volatile uint8_t errorData;
00198     // read interrupt status
00199     s1 = UART1->S1;
00200     // mask off interrupts that are not enabled
00201     if (!(UART1->C2 & UART_C2_RIE_MASK)) {
00202         s1 &= ~UART_S1_RDRF_MASK;
00203     }
00204     if (!(UART1->C2 & UART_C2_TIE_MASK)) {
00205         s1 &= ~UART_S1_TDRE_MASK;
00206     }
00207 
00208     // handle character to transmit
00209     if (s1 & UART_S1_TDRE_MASK) {
00210         // Assert that there is data in the buffer
00211         util_assert(circ_buf_count_used(&write_buffer) > 0);
00212 
00213         // Send out data
00214         UART1->D = circ_buf_pop(&write_buffer);
00215         // Turn off the transmitter if that was the last byte
00216         if (circ_buf_count_used(&write_buffer) == 0) {
00217             // disable TIE interrupt
00218             UART1->C2 &= ~(UART_C2_TIE_MASK);
00219         }
00220     }
00221 
00222     // handle received character
00223     if (s1 & UART_S1_RDRF_MASK) {
00224         if ((s1 & UART_S1_NF_MASK) || (s1 & UART_S1_FE_MASK)) {
00225             errorData = UART1->D;
00226         } else {
00227             uint32_t free;
00228             uint8_t data;
00229             
00230             data = UART1->D;
00231             free = circ_buf_count_free(&read_buffer);
00232             if (free > RX_OVRF_MSG_SIZE) {
00233                 circ_buf_push(&read_buffer, data);
00234             } else if (config_get_overflow_detect()) {
00235                 if (RX_OVRF_MSG_SIZE == free) {
00236                     circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE);
00237                 } else {
00238                     // Drop newest
00239                 }
00240             } else {
00241                 // Drop oldest
00242                 circ_buf_pop(&read_buffer);
00243                 circ_buf_push(&read_buffer, data);
00244             }
00245         }
00246     }
00247 }