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 "uart.h"
00025 #include "util.h"
00026 #include "cortex_m.h"
00027 #include "IO_Config.h"
00028 #include "circ_buf.h"
00029 #include "settings.h" // for config_get_overflow_detect
00030 
00031 #define RX_OVRF_MSG         "<DAPLink:Overflow>\n"
00032 #define RX_OVRF_MSG_SIZE    (sizeof(RX_OVRF_MSG) - 1)
00033 #define BUFFER_SIZE         (512)
00034 
00035 circ_buf_t write_buffer;
00036 uint8_t write_buffer_data[BUFFER_SIZE];
00037 circ_buf_t read_buffer;
00038 uint8_t read_buffer_data[BUFFER_SIZE];
00039 
00040 void clear_buffers(void)
00041 {
00042     util_assert(!(UART->C2 & UART_C2_TIE_MASK));
00043     circ_buf_init(&write_buffer, write_buffer_data, sizeof(write_buffer_data));
00044     circ_buf_init(&read_buffer, read_buffer_data, sizeof(read_buffer_data));
00045 }
00046 
00047 int32_t uart_initialize(void)
00048 {
00049     NVIC_DisableIRQ(UART_RX_TX_IRQn);
00050 
00051     // enable clk port
00052     if (UART_PORT == PORTA) {
00053         SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
00054     }
00055 
00056     if (UART_PORT == PORTC) {
00057         SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
00058     }
00059 
00060     if (UART_PORT == PORTD) {
00061         SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK;
00062     }
00063 
00064     if (UART_PORT == PORTE) {
00065         SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK;
00066     }
00067 
00068     // enable clk uart
00069     if (1 == UART_NUM) {
00070         SIM->SCGC4 |= SIM_SCGC4_UART1_MASK;
00071     }
00072 
00073     if (2 == UART_NUM) {
00074         SIM->SCGC4 |= SIM_SCGC4_UART2_MASK;
00075     }
00076 
00077     // transmitter and receiver disabled
00078     UART->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
00079     // disable interrupt
00080     UART->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
00081 
00082     clear_buffers();
00083 
00084     // alternate setting
00085     UART_PORT->PCR[PIN_UART_RX_BIT] = PORT_PCR_MUX(PIN_UART_RX_MUX_ALT) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
00086     UART_PORT->PCR[PIN_UART_TX_BIT] = PORT_PCR_MUX(PIN_UART_TX_MUX_ALT);
00087     // transmitter and receiver enabled
00088     UART->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
00089     // Enable receive interrupt
00090     UART->C2 |= UART_C2_RIE_MASK;
00091     NVIC_ClearPendingIRQ(UART_RX_TX_IRQn);
00092     NVIC_EnableIRQ(UART_RX_TX_IRQn);
00093     return 1;
00094 }
00095 
00096 int32_t uart_uninitialize(void)
00097 {
00098     // transmitter and receiver disabled
00099     UART->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
00100     // disable interrupt
00101     UART->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
00102     clear_buffers();
00103     return 1;
00104 }
00105 
00106 int32_t uart_reset(void)
00107 {
00108     // disable interrupt
00109     NVIC_DisableIRQ(UART_RX_TX_IRQn);
00110     // disable TIE interrupt
00111     UART->C2 &= ~(UART_C2_TIE_MASK);
00112     clear_buffers();
00113     // enable interrupt
00114     NVIC_EnableIRQ(UART_RX_TX_IRQn);
00115     return 1;
00116 }
00117 
00118 int32_t uart_set_configuration(UART_Configuration *config)
00119 {
00120     uint8_t data_bits = 8;
00121     uint8_t parity_enable = 0;
00122     uint8_t parity_type = 0;
00123     uint32_t dll;
00124     // disable interrupt
00125     NVIC_DisableIRQ(UART_RX_TX_IRQn);
00126     UART->C2 &= ~(UART_C2_RIE_MASK | UART_C2_TIE_MASK);
00127     // Disable receiver and transmitter while updating
00128     UART->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
00129     clear_buffers();
00130 
00131     // set data bits, stop bits, parity
00132     if ((config->DataBits < 8) || (config->DataBits > 9)) {
00133         data_bits = 8;
00134     }
00135 
00136     data_bits -= 8;
00137 
00138     if (config->Parity == 1) {
00139         parity_enable = 1;
00140         parity_type = 1;
00141         data_bits++;
00142     } else if (config->Parity == 2) {
00143         parity_enable = 1;
00144         parity_type = 0;
00145         data_bits++;
00146     }
00147 
00148     // does not support 10 bit data comm
00149     if (data_bits == 2) {
00150         data_bits = 0;
00151         parity_enable = 0;
00152         parity_type = 0;
00153     }
00154 
00155     // data bits, parity and parity mode
00156     UART->C1 = data_bits << UART_C1_M_SHIFT |
00157                parity_enable << UART_C1_PE_SHIFT |
00158                parity_type << UART_C1_PT_SHIFT;
00159     dll =  SystemCoreClock / (16 * config->Baudrate);
00160 
00161     if (1 == UART_NUM || 2 == UART_NUM) {
00162         dll /= 2; //TODO <<= 1
00163     }
00164 
00165     // set baudrate
00166     UART->BDH = (UART->BDH & ~(UART_BDH_SBR_MASK)) | ((dll >> 8) & UART_BDH_SBR_MASK);
00167     UART->BDL = (UART->BDL & ~(UART_BDL_SBR_MASK)) | (dll & UART_BDL_SBR_MASK);
00168     // Enable transmitter and receiver
00169     UART->C2 |= UART_C2_RE_MASK | UART_C2_TE_MASK;
00170     // Enable UART interrupt
00171     NVIC_ClearPendingIRQ(UART_RX_TX_IRQn);
00172     NVIC_EnableIRQ(UART_RX_TX_IRQn);
00173     UART->C2 |= UART_C2_RIE_MASK;
00174     return 1;
00175 }
00176 
00177 int32_t uart_get_configuration(UART_Configuration *config)
00178 {
00179     return 1;
00180 }
00181 
00182 int32_t uart_write_free(void)
00183 {
00184     return circ_buf_count_free(&write_buffer);
00185 }
00186 
00187 int32_t uart_write_data(uint8_t *data, uint16_t size)
00188 {
00189     cortex_int_state_t state;
00190     uint32_t cnt;
00191 
00192     cnt = circ_buf_write(&write_buffer, data, size);
00193 
00194     // Atomically enable TX
00195     state = cortex_int_get_and_disable();
00196     if (circ_buf_count_used(&write_buffer)) {
00197         UART->C2 |= UART_C2_TIE_MASK;
00198     }
00199     cortex_int_restore(state);
00200 
00201     return cnt;
00202 }
00203 
00204 int32_t uart_read_data(uint8_t *data, uint16_t size)
00205 {
00206     return circ_buf_read(&read_buffer, data, size);
00207 }
00208 
00209 void uart_enable_flow_control(bool enabled)
00210 {
00211     // Flow control not implemented for this platform
00212 }
00213 
00214 void UART_RX_TX_IRQHandler(void)
00215 {
00216     uint32_t s1;
00217     volatile uint8_t errorData;
00218     // read interrupt status
00219     s1 = UART->S1;
00220     // mask off interrupts that are not enabled
00221     if (!(UART->C2 & UART_C2_RIE_MASK)) {
00222         s1 &= ~UART_S1_RDRF_MASK;
00223     }
00224     if (!(UART->C2 & UART_C2_TIE_MASK)) {
00225         s1 &= ~UART_S1_TDRE_MASK;
00226     }
00227 
00228     // handle character to transmit
00229     if (s1 & UART_S1_TDRE_MASK) {
00230         // Assert that there is data in the buffer
00231         util_assert(circ_buf_count_used(&write_buffer) > 0);
00232         // Send out data
00233         UART1->D = circ_buf_pop(&write_buffer);
00234         // Turn off the transmitter if that was the last byte
00235         if (circ_buf_count_used(&write_buffer) == 0) {
00236             // disable TIE interrupt
00237             UART->C2 &= ~(UART_C2_TIE_MASK);
00238         }
00239     }
00240 
00241     // handle received character
00242     if (s1 & UART_S1_RDRF_MASK) {
00243         if ((s1 & UART_S1_NF_MASK) || (s1 & UART_S1_FE_MASK)) {
00244             errorData = UART->D;
00245         } else {
00246             uint32_t free;
00247             uint8_t data;
00248             
00249             data = UART1->D;
00250             free = circ_buf_count_free(&read_buffer);
00251             if (free > RX_OVRF_MSG_SIZE) {
00252                 circ_buf_push(&read_buffer, data);
00253             } else if (config_get_overflow_detect()) {
00254                 if (RX_OVRF_MSG_SIZE == free) {
00255                     circ_buf_write(&read_buffer, (uint8_t*)RX_OVRF_MSG, RX_OVRF_MSG_SIZE);
00256                 } else {
00257                     // Drop newest
00258                 }
00259             } else {
00260                 // Drop oldest
00261                 circ_buf_pop(&read_buffer);
00262                 circ_buf_push(&read_buffer, data);
00263             }
00264         }
00265     }
00266 }