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