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 "max32625.h" 00019 #include "IO_Config.h" 00020 #include "clkman_regs.h" 00021 #include "ioman_regs.h" 00022 #include "gpio_regs.h" 00023 #include "uart_regs.h" 00024 #include "pwrman_regs.h" 00025 #include "uart.h" 00026 00027 // Size must be 2^n 00028 #define BUFFER_SIZE (4096) 00029 00030 #define UART_ERRORS (MXC_F_UART_INTFL_RX_FRAMING_ERR | \ 00031 MXC_F_UART_INTFL_RX_PARITY_ERR | \ 00032 MXC_F_UART_INTFL_RX_FIFO_OVERFLOW) 00033 00034 00035 // Track bit rate to avoid calculation from bus clock, clock scaler and baud divisor values 00036 static uint32_t baudrate; 00037 00038 static mxc_uart_regs_t *CdcAcmUart = NULL; 00039 static mxc_uart_fifo_regs_t *CdcAcmUartFifo = NULL; 00040 static IRQn_Type CdcAcmUartIrqNumber = MXC_IRQ_EXT_COUNT; 00041 00042 static struct { 00043 uint8_t data[BUFFER_SIZE]; 00044 volatile uint16_t idx_in; 00045 volatile uint16_t idx_out; 00046 volatile int16_t cnt_in; 00047 volatile int16_t cnt_out; 00048 } write_buffer, read_buffer; 00049 00050 /******************************************************************************/ 00051 static void set_bitrate(uint32_t bps) 00052 { 00053 uint32_t baud_divisor; 00054 00055 baud_divisor = SystemCoreClock / (1 << (MXC_CLKMAN->sys_clk_ctrl_8_uart - 1)); 00056 baud_divisor /= (bps * 16); 00057 CdcAcmUart->baud = baud_divisor; 00058 00059 baudrate = bps; 00060 } 00061 00062 /******************************************************************************/ 00063 int32_t uart_set_instance(uint32_t inst) 00064 { 00065 if (inst == 0) { 00066 CdcAcmUart = MXC_UART0; 00067 CdcAcmUartFifo = MXC_UART0_FIFO; 00068 CdcAcmUartIrqNumber = UART0_IRQn; 00069 } else if (inst == 2) { 00070 CdcAcmUart = MXC_UART2; 00071 CdcAcmUartFifo = MXC_UART2_FIFO; 00072 CdcAcmUartIrqNumber = UART2_IRQn; 00073 } else { 00074 return 0; 00075 } 00076 return 1; 00077 } 00078 00079 /******************************************************************************/ 00080 int32_t uart_initialize(void) 00081 { 00082 int idx; 00083 00084 if (CdcAcmUart == MXC_UART0) { 00085 MXC_CLKMAN->clk_gate_ctrl1 |= MXC_F_CLKMAN_CLK_GATE_CTRL1_UART0_CLK_GATER; 00086 if (MXC_CLKMAN->sys_clk_ctrl_8_uart != MXC_S_CLKMAN_CLK_SCALE_DIV_4) { 00087 MXC_CLKMAN->sys_clk_ctrl_8_uart = MXC_S_CLKMAN_CLK_SCALE_DIV_4; 00088 } 00089 00090 // Configure GPIO for UART 00091 MXC_IOMAN->uart0_req = ((MXC_V_IOMAN_MAP_A << MXC_F_IOMAN_UART0_REQ_IO_MAP_POS) | MXC_F_IOMAN_UART0_REQ_IO_REQ); 00092 while (MXC_IOMAN->uart0_ack != ((MXC_V_IOMAN_MAP_A << MXC_F_IOMAN_UART0_REQ_IO_MAP_POS) | MXC_F_IOMAN_UART0_REQ_IO_REQ)); 00093 00094 } else if (CdcAcmUart == MXC_UART2) { 00095 MXC_CLKMAN->clk_gate_ctrl1 |= MXC_F_CLKMAN_CLK_GATE_CTRL1_UART2_CLK_GATER; 00096 if (MXC_CLKMAN->sys_clk_ctrl_8_uart != MXC_S_CLKMAN_CLK_SCALE_DIV_4) { 00097 MXC_CLKMAN->sys_clk_ctrl_8_uart = MXC_S_CLKMAN_CLK_SCALE_DIV_4; 00098 } 00099 00100 // Configure GPIO for UART 00101 MXC_IOMAN->uart2_req = ((MXC_V_IOMAN_MAP_A << MXC_F_IOMAN_UART2_REQ_IO_MAP_POS) | MXC_F_IOMAN_UART2_REQ_IO_REQ); 00102 while (MXC_IOMAN->uart2_ack != ((MXC_V_IOMAN_MAP_A << MXC_F_IOMAN_UART2_REQ_IO_MAP_POS) | MXC_F_IOMAN_UART2_REQ_IO_REQ)); 00103 } else { 00104 return 0; 00105 } 00106 00107 idx = MXC_UART_GET_IDX(CdcAcmUart); 00108 MXC_PWRMAN->peripheral_reset |= (MXC_F_PWRMAN_PERIPHERAL_RESET_UART0 << idx); 00109 MXC_PWRMAN->peripheral_reset &= ~((MXC_F_PWRMAN_PERIPHERAL_RESET_UART0 << idx)); 00110 00111 // Flush RX and TX FIFOS 00112 CdcAcmUart->ctrl &= ~(MXC_F_UART_CTRL_RX_FIFO_EN | MXC_F_UART_CTRL_TX_FIFO_EN); 00113 00114 // Disable interrupts 00115 CdcAcmUart->inten = 0; 00116 CdcAcmUart->intfl = CdcAcmUart->intfl; 00117 00118 // Set the parity, size, stop and flow configuration 00119 CdcAcmUart->ctrl |= (MXC_S_UART_CTRL_DATA_SIZE_8_BITS | MXC_S_UART_CTRL_PARITY_DISABLE); 00120 00121 // Set receive fifo threshold to 0 00122 CdcAcmUart->rx_fifo_ctrl &= ~MXC_F_UART_RX_FIFO_CTRL_FIFO_AF_LVL; 00123 CdcAcmUart->rx_fifo_ctrl |= (0 << MXC_F_UART_RX_FIFO_CTRL_FIFO_AF_LVL_POS); 00124 00125 // Enable receive and transmit fifos 00126 CdcAcmUart->ctrl |= (MXC_F_UART_CTRL_RX_FIFO_EN | MXC_F_UART_CTRL_TX_FIFO_EN); 00127 00128 NVIC_EnableIRQ(CdcAcmUartIrqNumber); 00129 00130 // Set transmit almost empty level to three-quarters of the fifo size 00131 CdcAcmUart->tx_fifo_ctrl &= ~MXC_F_UART_TX_FIFO_CTRL_FIFO_AE_LVL; 00132 CdcAcmUart->tx_fifo_ctrl |= (MXC_UART_FIFO_DEPTH - (MXC_UART_FIFO_DEPTH >> 2)) << MXC_F_UART_TX_FIFO_CTRL_FIFO_AE_LVL_POS; 00133 00134 // Enable RX and TX interrupts 00135 CdcAcmUart->inten = (MXC_F_UART_INTEN_RX_FIFO_NOT_EMPTY | MXC_F_UART_INTFL_RX_FIFO_OVERFLOW | MXC_F_UART_INTEN_TX_FIFO_AE); 00136 00137 // Enable UART 00138 CdcAcmUart->ctrl |= MXC_F_UART_CTRL_UART_EN; 00139 00140 return 1; 00141 } 00142 00143 /******************************************************************************/ 00144 int32_t uart_uninitialize(void) 00145 { 00146 // Disable UART 00147 CdcAcmUart->ctrl &= ~MXC_F_UART_CTRL_UART_EN; 00148 00149 // Disable interrupts 00150 CdcAcmUart->inten = 0; 00151 NVIC_DisableIRQ(CdcAcmUartIrqNumber); 00152 00153 // Clear buffers 00154 memset(&write_buffer, 0, sizeof(write_buffer)); 00155 memset(&read_buffer, 0, sizeof(read_buffer)); 00156 00157 return 1; 00158 } 00159 00160 /******************************************************************************/ 00161 void uart_set_control_line_state(uint16_t ctrl_bmp) 00162 { 00163 } 00164 00165 /******************************************************************************/ 00166 int32_t uart_reset(void) 00167 { 00168 // Clear buffers 00169 memset(&write_buffer, 0, sizeof(write_buffer)); 00170 memset(&read_buffer, 0, sizeof(read_buffer)); 00171 00172 return 1; 00173 } 00174 00175 /******************************************************************************/ 00176 int32_t uart_set_configuration(UART_Configuration *config) 00177 { 00178 uint32_t ctrl; 00179 00180 // Get current configuration; clearing parameters that may be configured here 00181 ctrl = CdcAcmUart->ctrl & ~(MXC_F_UART_CTRL_PARITY | 00182 MXC_F_UART_CTRL_DATA_SIZE | 00183 MXC_F_UART_CTRL_EXTRA_STOP | 00184 MXC_F_UART_CTRL_CTS_EN | 00185 MXC_F_UART_CTRL_RTS_EN); 00186 00187 switch (config->Parity) { 00188 case UART_PARITY_NONE: break; 00189 case UART_PARITY_ODD: ctrl |= MXC_S_UART_CTRL_PARITY_ODD; 00190 case UART_PARITY_EVEN: ctrl |= MXC_S_UART_CTRL_PARITY_EVEN; 00191 case UART_PARITY_MARK: return 0; 00192 case UART_PARITY_SPACE: return 0; 00193 } 00194 00195 switch (config->DataBits) { 00196 case UART_DATA_BITS_5: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_5_BITS; break; 00197 case UART_DATA_BITS_6: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_6_BITS; break; 00198 case UART_DATA_BITS_7: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_7_BITS; break; 00199 case UART_DATA_BITS_8: ctrl |= MXC_S_UART_CTRL_DATA_SIZE_8_BITS; break; 00200 case UART_DATA_BITS_16: return 0; 00201 } 00202 00203 switch (config->StopBits) { 00204 case UART_STOP_BITS_1: break; 00205 case UART_STOP_BITS_1_5: 00206 case UART_STOP_BITS_2: ctrl |= MXC_F_UART_CTRL_EXTRA_STOP; break; 00207 } 00208 00209 switch (config->FlowControl) { 00210 case UART_FLOW_CONTROL_NONE: break; 00211 case UART_FLOW_CONTROL_RTS_CTS: return 0; 00212 case UART_FLOW_CONTROL_XON_XOFF: return 0; 00213 } 00214 00215 set_bitrate(config->Baudrate); 00216 00217 // Set the new configuration 00218 CdcAcmUart->ctrl = ctrl; 00219 00220 return 1; 00221 } 00222 00223 /******************************************************************************/ 00224 int32_t uart_get_configuration(UART_Configuration *config) 00225 { 00226 uint32_t ctrl; 00227 00228 // Capture current configuration 00229 ctrl = CdcAcmUart->ctrl; 00230 00231 if (!(ctrl & MXC_S_UART_CTRL_PARITY_DISABLE)) { 00232 config->Parity = UART_PARITY_NONE; 00233 } else if (ctrl & MXC_S_UART_CTRL_PARITY_ODD) { 00234 config->Parity = UART_PARITY_ODD; 00235 } else { 00236 // Note both EVEN and MARK parity are captured here 00237 config->Parity = UART_PARITY_EVEN; 00238 } 00239 00240 switch (ctrl & MXC_F_UART_CTRL_DATA_SIZE) { 00241 case MXC_S_UART_CTRL_DATA_SIZE_5_BITS: config->DataBits = UART_DATA_BITS_5; break; 00242 case MXC_S_UART_CTRL_DATA_SIZE_6_BITS: config->DataBits = UART_DATA_BITS_6; break; 00243 case MXC_S_UART_CTRL_DATA_SIZE_7_BITS: config->DataBits = UART_DATA_BITS_7; break; 00244 case MXC_S_UART_CTRL_DATA_SIZE_8_BITS: config->DataBits = UART_DATA_BITS_8; break; 00245 } 00246 00247 if (!(ctrl & MXC_F_UART_CTRL_EXTRA_STOP)) { 00248 config->StopBits = UART_STOP_BITS_1; 00249 } else { 00250 config->StopBits = UART_STOP_BITS_2; 00251 } 00252 00253 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)) { 00254 config->FlowControl = UART_FLOW_CONTROL_RTS_CTS; 00255 } else { 00256 // Not true if only one of ...CST_EN and ...RTS_EN are asserted 00257 config->FlowControl = UART_FLOW_CONTROL_NONE; 00258 } 00259 00260 config->Baudrate = baudrate; 00261 00262 return 1; 00263 } 00264 00265 /******************************************************************************/ 00266 int32_t uart_write_free(void) 00267 { 00268 return BUFFER_SIZE - (write_buffer.cnt_in - write_buffer.cnt_out); 00269 } 00270 00271 /******************************************************************************/ 00272 int32_t uart_write_data(uint8_t *data, uint16_t size) 00273 { 00274 uint16_t xfer_count = size; 00275 00276 if (write_buffer.cnt_in == write_buffer.cnt_out) { 00277 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) && 00278 (xfer_count > 0)) { 00279 00280 NVIC_DisableIRQ(CdcAcmUartIrqNumber); 00281 CdcAcmUart->intfl = MXC_F_UART_INTFL_TX_FIFO_AE; 00282 CdcAcmUartFifo->tx = *data++; 00283 xfer_count--; 00284 NVIC_EnableIRQ(CdcAcmUartIrqNumber); 00285 00286 } 00287 } 00288 00289 while (xfer_count > 0) { 00290 if ((write_buffer.cnt_in - write_buffer.cnt_out) < BUFFER_SIZE) { 00291 00292 NVIC_DisableIRQ(CdcAcmUartIrqNumber); 00293 write_buffer.data[write_buffer.idx_in++] = *data++; 00294 write_buffer.idx_in &= (BUFFER_SIZE - 1); 00295 write_buffer.cnt_in++; 00296 xfer_count--; 00297 NVIC_EnableIRQ(CdcAcmUartIrqNumber); 00298 00299 } else { 00300 break; 00301 } 00302 } 00303 return size - xfer_count; 00304 } 00305 00306 /******************************************************************************/ 00307 int32_t uart_read_data(uint8_t *data, uint16_t size) 00308 { 00309 int32_t cnt; 00310 00311 for (cnt = 0; (cnt < size) && (read_buffer.cnt_in != read_buffer.cnt_out); cnt++) { 00312 *data++ = read_buffer.data[read_buffer.idx_out++]; 00313 read_buffer.idx_out &= (BUFFER_SIZE - 1); 00314 read_buffer.cnt_out++; 00315 } 00316 00317 return cnt; 00318 } 00319 00320 /******************************************************************************/ 00321 void UART_IRQHandler(void) 00322 { 00323 // Capture interrupt flag state at entry 00324 uint32_t intfl = CdcAcmUart->intfl; 00325 // Clear interrupts that will be serviced 00326 CdcAcmUart->intfl = intfl; 00327 00328 if (intfl & MXC_F_UART_INTFL_RX_FIFO_OVERFLOW) { 00329 read_buffer.data[read_buffer.idx_in++] = '*'; 00330 read_buffer.idx_in &= (BUFFER_SIZE - 1); 00331 read_buffer.cnt_in++; 00332 } 00333 00334 if (intfl & (MXC_F_UART_INTFL_RX_FIFO_NOT_EMPTY | UART_ERRORS)) { 00335 while ((CdcAcmUart->rx_fifo_ctrl & MXC_F_UART_RX_FIFO_CTRL_FIFO_ENTRY) && 00336 ((read_buffer.cnt_in - read_buffer.cnt_out) < BUFFER_SIZE)) { 00337 read_buffer.data[read_buffer.idx_in++] = CdcAcmUartFifo->rx; 00338 CdcAcmUart->intfl = MXC_F_UART_INTFL_RX_FIFO_NOT_EMPTY; 00339 read_buffer.idx_in &= (BUFFER_SIZE - 1); 00340 read_buffer.cnt_in++; 00341 } 00342 if (((read_buffer.cnt_in - read_buffer.cnt_out) >= BUFFER_SIZE)) { 00343 read_buffer.data[read_buffer.idx_in++] = '%'; 00344 read_buffer.idx_in &= (BUFFER_SIZE - 1); 00345 read_buffer.cnt_in++; 00346 } 00347 } 00348 00349 if (intfl & MXC_F_UART_INTFL_TX_FIFO_AE) { 00350 /* 00351 Transfer data from write buffer to transmit FIFO if 00352 a) write buffer contains data and 00353 b) transmit FIFO is not full 00354 */ 00355 while ((write_buffer.cnt_out != write_buffer.cnt_in) && 00356 (((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)) { 00357 CdcAcmUartFifo->tx = write_buffer.data[write_buffer.idx_out++]; 00358 write_buffer.idx_out &= (BUFFER_SIZE - 1); 00359 write_buffer.cnt_out++; 00360 } 00361 } 00362 } 00363 00364 /******************************************************************************/ 00365 void UART0_IRQHandler(void) 00366 { 00367 UART_IRQHandler(); 00368 } 00369 00370 /******************************************************************************/ 00371 void UART1_IRQHandler(void) 00372 { 00373 UART_IRQHandler(); 00374 } 00375 00376 /******************************************************************************/ 00377 void UART2_IRQHandler(void) 00378 { 00379 UART_IRQHandler(); 00380 }
Generated on Tue Jul 12 2022 15:37:25 by
1.7.2