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 /* CMSIS-DAP Interface Firmware 00002 * Copyright (c) 2009-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <string.h> 00018 #include "max32620.h" 00019 #include "clkman_regs.h" 00020 #include "ioman_regs.h" 00021 #include "gpio_regs.h" 00022 #include "uart_regs.h" 00023 #include "uart.h" 00024 00025 // Size must be 2^n 00026 #define BUFFER_SIZE (4096) 00027 00028 #define UART_ERRORS (MXC_F_UART_INTFL_RX_FRAMING_ERR | \ 00029 MXC_F_UART_INTFL_RX_PARITY_ERR | \ 00030 MXC_F_UART_INTFL_RX_FIFO_OVERFLOW) 00031 00032 00033 // Track bit rate to avoid calculation from bus clock, clock scaler and baud divisor values 00034 static uint32_t baudrate; 00035 00036 static mxc_uart_regs_t *CdcAcmUart = MXC_UART0; 00037 static mxc_uart_fifo_regs_t *CdcAcmUartFifo = MXC_UART0_FIFO; 00038 static const IRQn_Type CdcAcmUartIrqNumber = UART0_IRQn; 00039 00040 00041 static struct { 00042 uint8_t data[BUFFER_SIZE]; 00043 volatile uint16_t idx_in; 00044 volatile uint16_t idx_out; 00045 volatile int16_t cnt_in; 00046 volatile int16_t cnt_out; 00047 } write_buffer, read_buffer; 00048 00049 /******************************************************************************/ 00050 static void set_bitrate(uint32_t bps) 00051 { 00052 uint32_t baud_divisor; 00053 00054 baud_divisor = SystemCoreClock / (1 << (MXC_CLKMAN->sys_clk_ctrl_8_uart - 1)); 00055 baud_divisor /= (bps * 16); 00056 CdcAcmUart->baud = baud_divisor; 00057 00058 baudrate = bps; 00059 } 00060 00061 /******************************************************************************/ 00062 int32_t uart_initialize(void) 00063 { 00064 if (MXC_CLKMAN->sys_clk_ctrl_8_uart != MXC_S_CLKMAN_CLK_SCALE_DIV_4) { 00065 MXC_CLKMAN->sys_clk_ctrl_8_uart = MXC_S_CLKMAN_CLK_SCALE_DIV_4; 00066 } 00067 // Configure GPIO for UART 00068 MXC_IOMAN->uart0_req = ((0 << MXC_F_IOMAN_UART0_REQ_IO_MAP_POS) | MXC_F_IOMAN_UART0_REQ_IO_REQ); 00069 while (MXC_IOMAN->uart0_ack != ((0 << MXC_F_IOMAN_UART0_REQ_IO_MAP_POS) | MXC_F_IOMAN_UART0_REQ_IO_REQ)); 00070 00071 // Disable TX and RX fifos 00072 CdcAcmUart->ctrl &= ~(MXC_F_UART_CTRL_RX_FIFO_EN | MXC_F_UART_CTRL_TX_FIFO_EN); 00073 00074 // Disable interrupts 00075 CdcAcmUart->inten = 0; 00076 CdcAcmUart->intfl = CdcAcmUart->intfl; 00077 00078 // Set the parity, size, stop and flow configuration 00079 CdcAcmUart->ctrl |= (MXC_S_UART_CTRL_DATA_SIZE_8_BITS | MXC_S_UART_CTRL_PARITY_DISABLE); 00080 00081 // Set receive fifo threshold to 0 00082 CdcAcmUart->rx_fifo_ctrl &= ~MXC_F_UART_RX_FIFO_CTRL_FIFO_AF_LVL; 00083 CdcAcmUart->rx_fifo_ctrl |= (0 << MXC_F_UART_RX_FIFO_CTRL_FIFO_AF_LVL_POS); 00084 00085 // Enable TX and RX fifos 00086 CdcAcmUart->ctrl |= (MXC_F_UART_CTRL_RX_FIFO_EN | MXC_F_UART_CTRL_TX_FIFO_EN); 00087 00088 NVIC_EnableIRQ(CdcAcmUartIrqNumber); 00089 00090 // Set transmit almost empty level to three-quarters of the fifo size 00091 CdcAcmUart->tx_fifo_ctrl &= ~MXC_F_UART_TX_FIFO_CTRL_FIFO_AE_LVL; 00092 CdcAcmUart->tx_fifo_ctrl |= (MXC_UART_FIFO_DEPTH - (MXC_UART_FIFO_DEPTH >> 2)) << MXC_F_UART_TX_FIFO_CTRL_FIFO_AE_LVL_POS; 00093 00094 // Enable TX and RX interrupts 00095 CdcAcmUart->inten = (MXC_F_UART_INTEN_RX_FIFO_NOT_EMPTY | MXC_F_UART_INTFL_RX_FIFO_OVERFLOW | MXC_F_UART_INTEN_TX_FIFO_AE); 00096 00097 // Enable UART 00098 CdcAcmUart->ctrl |= MXC_F_UART_CTRL_UART_EN; 00099 00100 return 1; 00101 } 00102 00103 /******************************************************************************/ 00104 int32_t uart_uninitialize(void) 00105 { 00106 // Disable UART 00107 CdcAcmUart->ctrl &= ~MXC_F_UART_CTRL_UART_EN; 00108 00109 // Disable interrupts 00110 CdcAcmUart->inten = 0; 00111 NVIC_DisableIRQ(CdcAcmUartIrqNumber); 00112 00113 // Clear buffers 00114 memset(&write_buffer, 0, sizeof(write_buffer)); 00115 memset(&read_buffer, 0, sizeof(read_buffer)); 00116 00117 return 1; 00118 } 00119 00120 /******************************************************************************/ 00121 void uart_set_control_line_state(uint16_t ctrl_bmp) 00122 { 00123 } 00124 00125 /******************************************************************************/ 00126 int32_t uart_reset(void) 00127 { 00128 // Clear buffers 00129 memset(&write_buffer, 0, sizeof(write_buffer)); 00130 memset(&read_buffer, 0, sizeof(read_buffer)); 00131 00132 return 1; 00133 } 00134 00135 /******************************************************************************/ 00136 int32_t uart_set_configuration(UART_Configuration *config) 00137 { 00138 uint32_t ctrl; 00139 00140 // Get current configuration; clearing parameters that may be configured here 00141 ctrl = CdcAcmUart->ctrl & ~(MXC_F_UART_CTRL_PARITY | 00142 MXC_F_UART_CTRL_DATA_SIZE | 00143 MXC_F_UART_CTRL_EXTRA_STOP | 00144 MXC_F_UART_CTRL_CTS_EN | 00145 MXC_F_UART_CTRL_RTS_EN); 00146 00147 switch (config->Parity) { 00148 case UART_PARITY_NONE: break; 00149 case UART_PARITY_ODD: ctrl |= MXC_S_UART_CTRL_PARITY_ODD; 00150 case UART_PARITY_EVEN: ctrl |= MXC_S_UART_CTRL_PARITY_EVEN; 00151 case UART_PARITY_MARK: return 0; 00152 case UART_PARITY_SPACE: return 0; 00153 } 00154 00155 switch (config->DataBits) { 00156 case UART_DATA_BITS_5: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_5_BITS; break; 00157 case UART_DATA_BITS_6: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_6_BITS; break; 00158 case UART_DATA_BITS_7: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_7_BITS; break; 00159 case UART_DATA_BITS_8: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_8_BITS; break; 00160 case UART_DATA_BITS_16: return 0; 00161 } 00162 00163 switch (config->StopBits) { 00164 case UART_STOP_BITS_1: break; 00165 case UART_STOP_BITS_1_5: 00166 case UART_STOP_BITS_2: ctrl |= MXC_F_UART_CTRL_EXTRA_STOP; break; 00167 } 00168 00169 switch (config->FlowControl) { 00170 case UART_FLOW_CONTROL_NONE: break; 00171 case UART_FLOW_CONTROL_RTS_CTS: return 0; 00172 case UART_FLOW_CONTROL_XON_XOFF: return 0; 00173 } 00174 00175 set_bitrate(config->Baudrate); 00176 00177 // Set the new configuration 00178 CdcAcmUart->ctrl = ctrl; 00179 00180 return 1; 00181 } 00182 00183 /******************************************************************************/ 00184 int32_t uart_get_configuration(UART_Configuration *config) 00185 { 00186 uint32_t ctrl; 00187 00188 // Capture current configuration 00189 ctrl = CdcAcmUart->ctrl; 00190 00191 if (!(ctrl & MXC_S_UART_CTRL_PARITY_DISABLE)) { 00192 config->Parity = UART_PARITY_NONE; 00193 } else if (ctrl & MXC_S_UART_CTRL_PARITY_ODD) { 00194 config->Parity = UART_PARITY_ODD; 00195 } else { 00196 // Note both EVEN and MARK parity are captured here 00197 config->Parity = UART_PARITY_EVEN; 00198 } 00199 00200 switch (ctrl & MXC_F_UART_CTRL_DATA_SIZE) { 00201 case MXC_S_UART_CTRL_DATA_SIZE_5_BITS: config->DataBits = UART_DATA_BITS_5; break; 00202 case MXC_S_UART_CTRL_DATA_SIZE_6_BITS: config->DataBits = UART_DATA_BITS_6; break; 00203 case MXC_S_UART_CTRL_DATA_SIZE_7_BITS: config->DataBits = UART_DATA_BITS_7; break; 00204 case MXC_S_UART_CTRL_DATA_SIZE_8_BITS: config->DataBits = UART_DATA_BITS_8; break; 00205 } 00206 00207 if (!(ctrl & MXC_F_UART_CTRL_EXTRA_STOP)) { 00208 config->StopBits = UART_STOP_BITS_1; 00209 } else { 00210 config->StopBits = UART_STOP_BITS_2; 00211 } 00212 00213 if ((ctrl & (MXC_F_UART_CTRL_CTS_EN | MXC_F_UART_CTRL_RTS_EN)) == (MXC_F_UART_CTRL_CTS_EN | MXC_F_UART_CTRL_RTS_EN)) { 00214 config->FlowControl = UART_FLOW_CONTROL_RTS_CTS; 00215 } else { 00216 // Not true if only one of ...CST_EN and ...RTS_EN are asserted 00217 config->FlowControl = UART_FLOW_CONTROL_NONE; 00218 } 00219 00220 config->Baudrate = baudrate; 00221 00222 return 1; 00223 } 00224 00225 /******************************************************************************/ 00226 int32_t uart_write_free(void) 00227 { 00228 return BUFFER_SIZE - (write_buffer.cnt_in - write_buffer.cnt_out); 00229 } 00230 00231 /******************************************************************************/ 00232 int32_t uart_write_data(uint8_t *data, uint16_t size) 00233 { 00234 uint16_t xfer_count = size; 00235 00236 NVIC_DisableIRQ(CdcAcmUartIrqNumber); 00237 if (write_buffer.cnt_in == write_buffer.cnt_out) { 00238 while ((((CdcAcmUart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) >> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS) < MXC_UART_FIFO_DEPTH) && 00239 (xfer_count > 0)) { 00240 CdcAcmUart->intfl = MXC_F_UART_INTFL_TX_FIFO_AE; 00241 CdcAcmUartFifo->tx = *data++; 00242 xfer_count--; 00243 } 00244 } 00245 NVIC_EnableIRQ(CdcAcmUartIrqNumber); 00246 00247 while (xfer_count > 0) { 00248 if ((write_buffer.cnt_in - write_buffer.cnt_out) < BUFFER_SIZE) { 00249 write_buffer.data[write_buffer.idx_in++] = *data++; 00250 write_buffer.idx_in &= (BUFFER_SIZE - 1); 00251 write_buffer.cnt_in++; 00252 xfer_count--; 00253 } else { 00254 break; 00255 } 00256 } 00257 return size - xfer_count; 00258 } 00259 00260 /******************************************************************************/ 00261 int32_t uart_read_data(uint8_t *data, uint16_t size) 00262 { 00263 int32_t cnt; 00264 00265 for (cnt = 0; (cnt < size) && (read_buffer.cnt_in != read_buffer.cnt_out); cnt++) { 00266 *data++ = read_buffer.data[read_buffer.idx_out++]; 00267 read_buffer.idx_out &= (BUFFER_SIZE - 1); 00268 read_buffer.cnt_out++; 00269 } 00270 00271 return cnt; 00272 } 00273 00274 /******************************************************************************/ 00275 void UART0_IRQHandler(void) 00276 { 00277 /* Capture interrupt flag state at entry */ 00278 uint32_t intfl = CdcAcmUart->intfl; 00279 /* Clear interrupts that will be serviced */ 00280 CdcAcmUart->intfl = intfl; 00281 00282 if (intfl & MXC_F_UART_INTFL_RX_FIFO_OVERFLOW) { 00283 read_buffer.data[read_buffer.idx_in++] = '*'; 00284 read_buffer.idx_in &= (BUFFER_SIZE - 1); 00285 read_buffer.cnt_in++; 00286 } 00287 00288 if (intfl & (MXC_F_UART_INTFL_RX_FIFO_NOT_EMPTY | UART_ERRORS)) { 00289 while ((CdcAcmUart->rx_fifo_ctrl & MXC_F_UART_RX_FIFO_CTRL_FIFO_ENTRY) && 00290 ((read_buffer.cnt_in - read_buffer.cnt_out) < BUFFER_SIZE)) { 00291 read_buffer.data[read_buffer.idx_in++] = CdcAcmUartFifo->rx; 00292 CdcAcmUart->intfl = MXC_F_UART_INTFL_RX_FIFO_NOT_EMPTY; 00293 read_buffer.idx_in &= (BUFFER_SIZE - 1); 00294 read_buffer.cnt_in++; 00295 } 00296 if (((read_buffer.cnt_in - read_buffer.cnt_out) >= BUFFER_SIZE)) { 00297 read_buffer.data[read_buffer.idx_in++] = '%'; 00298 read_buffer.idx_in &= (BUFFER_SIZE - 1); 00299 read_buffer.cnt_in++; 00300 } 00301 } 00302 00303 if (intfl & MXC_F_UART_INTFL_TX_FIFO_AE) { 00304 /* 00305 Transfer data from write buffer to transmit fifo if 00306 a) write buffer contains data and 00307 b) transmit fifo is not full 00308 */ 00309 while ((write_buffer.cnt_out != write_buffer.cnt_in) && 00310 (((CdcAcmUart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) >> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS) < MXC_UART_FIFO_DEPTH)) { 00311 CdcAcmUartFifo->tx = write_buffer.data[write_buffer.idx_out++]; 00312 write_buffer.idx_out &= (BUFFER_SIZE - 1); 00313 write_buffer.cnt_out++; 00314 } 00315 } 00316 }
Generated on Tue Jul 12 2022 15:37:25 by
1.7.2