Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 15:37:25 by
