Library to access LPC17xx peripherals. It uses static inline functions, constant propagation and dead code elimination to be as fast as possible.
Dependents: Chua-VGA Wolfram-1D-VGA WolframRnd-1D-VGA Basin-VGA ... more
uart.h
00001 /* Copyright (C) 2010, 2011, 2012 by Ivo van Poorten <ivop@euronet.nl> 00002 * This file is licensed under the terms of the GNU Lesser 00003 * General Public License, version 3. 00004 */ 00005 00006 #ifndef FASTLIB_UART_H 00007 #define FASTLIB_UART_H 00008 00009 #include "fastlib/common.h" 00010 00011 #define FL_UART_RBR 0x00 00012 #define FL_UART_THR 0x00 00013 #define FL_UART_DLL 0x00 00014 00015 #define FL_UART_DLM 0x04 00016 #define FL_UART_IER 0x04 00017 00018 #define FL_UART_IIR 0x08 00019 #define FL_UART_FCR 0x08 00020 00021 #define FL_UART_LCR 0x0C 00022 #define FL_UART_MCR 0x10 /* UART1 only */ 00023 #define FL_UART_LSR 0x14 00024 #define FL_UART_MSR 0x18 /* UART1 only */ 00025 #define FL_UART_SCR 0x1C 00026 #define FL_UART_ACR 0x20 00027 #define FL_UART_ICR 0x24 /* UART023 only */ 00028 #define FL_UART_FDR 0x28 00029 #define FL_UART_TER 0x30 00030 00031 #define FL_UART_RS485CTRL 0x4C /* UART1 only */ 00032 #define FL_UART_RS485ADRMATCH 0x50 /* UART1 only */ 00033 #define FL_UART_RS485DLY 0x54 /* UART1 only */ 00034 00035 #define FL_UART0_BASE 0x4000C000 00036 #define FL_UART1_BASE 0x40010000 00037 #define FL_UART2_BASE 0x40098000 00038 #define FL_UART3_BASE 0x4009C000 00039 00040 #define FL_UART(num, field) \ 00041 ((volatile uint32_t *)(fl_uart_num_to_base(num) + FL_UART_##field)) 00042 00043 static inline unsigned fl_uart_num_to_base(const unsigned num) { 00044 switch(num) { 00045 case 0: return FL_UART0_BASE; 00046 case 1: return FL_UART1_BASE; 00047 case 2: return FL_UART2_BASE; 00048 default: return FL_UART3_BASE; 00049 } 00050 } 00051 00052 static inline unsigned fl_uart_receive_byte(const unsigned uart) { 00053 return *FL_UART(uart, RBR); 00054 } 00055 00056 static inline void fl_uart_send_byte(const unsigned uart, const unsigned byte) { 00057 *FL_UART(uart, THR) = byte; 00058 } 00059 00060 static inline unsigned fl_uart_get_divisor_latch(const unsigned uart) { 00061 unsigned divisor; 00062 *FL_UART(uart, LCR) |= 1U<<7; // enable access to latch 00063 00064 divisor = *FL_UART(uart, DLL) | (*FL_UART(uart, DLM) << 8); 00065 00066 *FL_UART(uart, LCR) &= ~(1U<<7); // disable access to latch 00067 return divisor; 00068 } 00069 00070 /* divisor: 16-bit value */ 00071 static inline void fl_uart_set_divisor_latch(const unsigned uart, const unsigned divisor) { 00072 *FL_UART(uart, LCR) |= 1U<<7; // enable access to latch 00073 00074 *FL_UART(uart, DLL) = divisor & 0xff; 00075 *FL_UART(uart, DLM) = (divisor >> 8) & 0xff; 00076 00077 *FL_UART(uart, LCR) &= ~(1U<<7); // disable access to latch 00078 } 00079 00080 static inline void fl_uart_rx_data_available_interrupt_enable(const unsigned uart, const unsigned state) { 00081 if (state) *FL_UART(uart, IER) |= (1U<<0); 00082 else *FL_UART(uart, IER) &= ~(1U<<0); 00083 } 00084 00085 static inline void fl_uart_tx_fifo_empty_interrupt_enable(const unsigned uart, const unsigned state) { 00086 if (state) *FL_UART(uart, IER) |= (1U<<1); 00087 else *FL_UART(uart, IER) &= ~(1U<<1); 00088 } 00089 00090 static inline void fl_uart_rx_line_status_interrupt_enable(const unsigned uart, const unsigned state) { 00091 if (state) *FL_UART(uart, IER) |= (1U<<2); 00092 else *FL_UART(uart, IER) &= ~(1U<<2); 00093 } 00094 00095 static inline void fl_uart_end_of_autobaud_interrupt_enable(const unsigned uart, const unsigned state) { 00096 if (state) *FL_UART(uart, IER) |= (1U<<8); 00097 else *FL_UART(uart, IER) &= ~(1U<<8); 00098 } 00099 00100 static inline void fl_uart_timeout_autobaud_interrupt_enable(const unsigned uart, const unsigned state) { 00101 if (state) *FL_UART(uart, IER) |= (1U<<9); 00102 else *FL_UART(uart, IER) &= ~(1U<<9); 00103 } 00104 00105 static inline unsigned fl_uart_interrupt_status(const unsigned uart) { 00106 return !(*FL_UART(uart, IIR) & 1); // negate, because status is active low 00107 } 00108 00109 #define FL_UART_INTERRUPT_RLS 3 /* rx line status */ 00110 #define FL_UART_INTERRUPT_RDA 2 /* rx data available */ 00111 #define FL_UART_INTERRUPT_CTI 6 /* character time-out */ 00112 #define FL_UART_INTERRUPT_THRE 1 /* tx fifo empty */ 00113 #define FL_UART_INTERRUPT_MODEM 0 /* modem interrupt, uart1 only */ 00114 00115 static inline unsigned fl_uart_get_interrupt_identification(const unsigned uart) { 00116 return (*FL_UART(uart, IIR) >> 1) & 7; 00117 } 00118 00119 /* returns 0 or !0 */ 00120 static inline unsigned fl_uart_end_of_autobaud_interrupt(const unsigned uart) { 00121 return *FL_UART(uart, IIR) & (1U<<8); 00122 } 00123 static inline unsigned fl_uart_timeout_autobaud_interrupt(const unsigned uart) { 00124 return *FL_UART(uart, IIR) & (1U<<9); 00125 } 00126 00127 /* call is more or less mandatory for application (page 305) */ 00128 static inline void fl_uart_enable_fifos(const unsigned uart) { 00129 *FL_UART(uart, FCR) |= 1U<<0; 00130 } 00131 /* disable/enable cycle clears fifo */ 00132 static inline void fl_uart_disable_fifos(const unsigned uart) { 00133 *FL_UART(uart, FCR) &= ~(1U<<0); 00134 } 00135 00136 static inline void fl_uart_reset_rx_fifo(const unsigned uart) { 00137 *FL_UART(uart, FCR) |= 1U<<1; // bit is self-clearing 00138 } 00139 00140 static inline void fl_uart_reset_tx_fifo(const unsigned uart) { 00141 *FL_UART(uart, FCR) |= 1U<<2; // bit is self-clearing 00142 } 00143 00144 static inline void fl_uart_enable_dma_mode(const unsigned uart, const unsigned state) { 00145 if (state) *FL_UART(uart, FCR) |= 1U<<3 ; 00146 else *FL_UART(uart, FCR) &= ~(1U<<3); 00147 } 00148 00149 static inline void fl_uart_set_rx_trigger_level(const unsigned uart, const unsigned level) { 00150 if (level != 14) *FL_UART(uart, FCR) &= ~(3U<<6); 00151 switch(level) { 00152 default: return; 00153 case 4: *FL_UART(uart, FCR) |= 1U<<6; return; 00154 case 8: *FL_UART(uart, FCR) |= 2U<<6; return; 00155 case 14: *FL_UART(uart, FCR) |= 3U<<6; return; 00156 } 00157 } 00158 00159 #define FL_UART_5BIT 0 00160 #define FL_UART_6BIT 1 00161 #define FL_UART_7BIT 2 00162 #define FL_UART_8BIT 3 00163 00164 #define FL_UART_1STOPBIT 0 00165 #define FL_UART_2STOPBITS 1 00166 00167 #define FL_UART_NO_PARITY 0 00168 #define FL_UART_PARITY 1 00169 00170 #define FL_UART_ODD 0 00171 #define FL_UART_EVEN 1 00172 #define FL_UART_FORCE1 2 00173 #define FL_UART_FORCE0 3 00174 00175 static inline void fl_uart_line_config(const unsigned uart, const unsigned wordlength, const unsigned stopbit, \ 00176 const unsigned parity_enable, const unsigned parity_type) { 00177 const unsigned combined = wordlength | (stopbit << 2) | (parity_enable << 3) | (parity_type << 4); 00178 *FL_UART(uart, LCR) &= ~(0x3fU); 00179 *FL_UART(uart, LCR) |= combined; 00180 } 00181 00182 static inline void fl_uart_break_transmission(const unsigned uart, const unsigned state) { 00183 if (state) *FL_UART(uart, LCR) |= 1U<<6 ; 00184 else *FL_UART(uart, LCR) &= ~(1U<<6); 00185 } 00186 00187 static inline unsigned fl_uart_get_line_status(const unsigned uart) { 00188 return *FL_UART(uart, LSR); 00189 } 00190 00191 /* read status first and use functions below to test what is happening */ 00192 /* the reason for this is that a status read clears several bits */ 00193 00194 #define FL_LSR_TEST(what, where) \ 00195 static inline unsigned fl_uart_##what(const unsigned status) { \ 00196 return status & (where); \ 00197 } 00198 00199 FL_LSR_TEST(rx_fifo_not_empty, 1U<<0); 00200 FL_LSR_TEST(rx_fifo_overun_error, 1U<<1); 00201 FL_LSR_TEST(rx_parity_error, 1U<<2); 00202 FL_LSR_TEST(rx_framing_error, 1U<<3); 00203 FL_LSR_TEST(rx_break_interrupt, 1U<<4); /* associated with top of fifo */ 00204 FL_LSR_TEST(tx_send_register_empty, 1U<<5); 00205 FL_LSR_TEST(tx_empty, 1U<<6); /* both send and status register */ 00206 FL_LSR_TEST(rx_error_entered_fifo, 1U<<7); 00207 00208 static inline void fl_uart_write_scratch_pad(const unsigned uart, const unsigned byte) { 00209 *FL_UART(uart, SCR) = byte & 0xff; 00210 } 00211 00212 static inline unsigned fl_uart_read_scratch_pad(const unsigned uart) { 00213 return *FL_UART(uart, SCR); 00214 } 00215 00216 static inline void fl_uart_autobaud_config(const unsigned uart, const unsigned mode, const unsigned autorestart) { 00217 *FL_UART(uart, ACR) = (mode << 1) | (autorestart << 2); // writing zeroes to other bits has no impact (p.308/309) 00218 } 00219 00220 static inline void fl_uart_start_autobaud(const unsigned uart) { 00221 *FL_UART(uart, ACR) |= 1; // bit is auto-clearing 00222 } 00223 00224 static inline void fl_uart_clear_end_of_autobaud_interrupt(const unsigned uart) { 00225 *FL_UART(uart, ACR) |= 1U<<8; 00226 } 00227 00228 static inline void fl_uart_clear_autobaud_timeout_interrupt(const unsigned uart) { 00229 *FL_UART(uart, ACR) |= 1U<<9; 00230 } 00231 00232 static inline void fl_uart_set_fractional_divider(const unsigned uart, const unsigned divaddval, const unsigned mulval) { 00233 *FL_UART(uart, FDR) &= ~(0xff); 00234 *FL_UART(uart, FDR) |= divaddval | (mulval<<4); 00235 } 00236 00237 static inline unsigned fl_uart_get_fractional_divider(const unsigned uart) { 00238 return *FL_UART(uart, FDR); 00239 } 00240 00241 static inline void fl_uart_transmitter_enable(const unsigned uart, const unsigned state) { 00242 if (state) *FL_UART(uart, TER) |= 1U<<7 ; 00243 else *FL_UART(uart, TER) &= ~(1U<<7); 00244 } 00245 00246 // infrared mode only works on uart0, 2 and 3 00247 00248 static inline void fl_uart_infrared_mode(const unsigned uart, const unsigned state) { 00249 if (state) *FL_UART(uart, ICR) |= 1U<<0; 00250 else *FL_UART(uart, ICR) &= ~(1U<<0); 00251 } 00252 static inline void fl_uart_infrared_input_inverted(const unsigned uart, const unsigned state) { 00253 if (state) *FL_UART(uart, ICR) |= 1U<<1; 00254 else *FL_UART(uart, ICR) &= ~(1U<<1); 00255 } 00256 static inline void fl_uart_infrared_fixed_pulsewidth(const unsigned uart, const unsigned state) { 00257 if (state) *FL_UART(uart, ICR) |= 1U<<2; 00258 else *FL_UART(uart, ICR) &= ~(1U<<2); 00259 } 00260 // see UM10360 page 312 for pulsediv values (0-7) 00261 static inline void fl_uart_infrared_config_pulse(const unsigned uart, const unsigned pulsediv) { 00262 *FL_UART(uart, ICR) &= ~(7U<<3); 00263 *FL_UART(uart, ICR) |= pulsediv << 3; 00264 } 00265 00266 00267 // functions below only work for uart1 (full modem interface) 00268 00269 static inline void fl_modem_status_interrupt_enable(const unsigned state) { 00270 if (state) *FL_UART(1, IER) |= (1U<<3); 00271 else *FL_UART(1, IER) &= ~(1U<<3); 00272 } 00273 00274 static inline void fl_modem_cts_interrupt_enable(const unsigned state) { 00275 if (state) *FL_UART(1, IER) |= (1U<<7); 00276 else *FL_UART(1, IER) &= ~(1U<<7); 00277 } 00278 00279 static inline void fl_modem_control(const unsigned dtr_control, const unsigned rts_control, const unsigned loopback, 00280 const unsigned rts, const unsigned cts) { 00281 *FL_UART(1, MCR) = dtr_control | (rts_control << 1) | (loopback << 4) | (rts << 6) | (cts << 7); 00282 } 00283 00284 static inline unsigned fl_modem_get_status(void) { 00285 return *FL_UART(1, MSR); 00286 } 00287 00288 /* read status first and use functions below to test what is happening */ 00289 /* the reason for this is that a status read clears several bits */ 00290 00291 #define FL_MSR_TEST(what, where) \ 00292 static inline unsigned fl_modem_##what(const unsigned status) { \ 00293 return status & (where); \ 00294 } 00295 00296 FL_MSR_TEST(cts_state_changed, 1U<<0); 00297 FL_MSR_TEST(dsr_state_changed, 1U<<1); 00298 FL_MSR_TEST(low_to_high_ri, 1U<<2); 00299 FL_MSR_TEST(dcd_state_changed, 1U<<3); 00300 FL_MSR_TEST(cts_state, 1U<<4); /* clear to send */ 00301 FL_MSR_TEST(dsr_state, 1U<<5); /* data set ready */ 00302 FL_MSR_TEST(ri_state, 1U<<6); /* ring indicator */ 00303 FL_MSR_TEST(dcd_state, 1U<<7); /* data carrier detect */ 00304 00305 // RS-485/EIA-485 mode functions, also uart1 only 00306 00307 static inline void fl_rs485_normal_multidrop_mode_enable(const unsigned state) { 00308 if (state) *FL_UART(1, RS485CTRL) |= 1U<<0 ; 00309 else *FL_UART(1, RS485CTRL) &= ~(1U<<0); 00310 } 00311 00312 static inline void fl_rs485_receiver_enable(const unsigned state) { 00313 if (state) *FL_UART(1, RS485CTRL) |= 1U<<1 ; 00314 else *FL_UART(1, RS485CTRL) &= ~(1U<<1); 00315 } 00316 00317 static inline void fl_rs485_auto_address_detect_enable(const unsigned state) { 00318 if (state) *FL_UART(1, RS485CTRL) |= 1U<<2 ; 00319 else *FL_UART(1, RS485CTRL) &= ~(1U<<2); 00320 } 00321 00322 static inline void fl_rs485_auto_direction_control_enable(const unsigned state) { 00323 if (state) *FL_UART(1, RS485CTRL) |= 1U<<4 ; 00324 else *FL_UART(1, RS485CTRL) &= ~(1U<<4); 00325 } 00326 00327 static inline void fl_rs485_direction_control_on_rts_pin(void) { 00328 *FL_UART(1, RS485CTRL) &= ~(1U<<3); 00329 } 00330 00331 static inline void fl_rs485_direction_control_on_dtr_pin(void) { 00332 *FL_UART(1, RS485CTRL) |= 1U<<3; 00333 } 00334 00335 static inline void fl_rs485_direction_control_polarity(const unsigned oinv) { 00336 if (oinv) *FL_UART(1, RS485CTRL) |= 1U<<5 ; 00337 else *FL_UART(1, RS485CTRL) &= ~(1U<<5); 00338 } 00339 00340 static inline void fl_rs485_set_address_match(const unsigned byte) { 00341 *FL_UART(1, RS485ADRMATCH) = byte & 0xff; 00342 } 00343 00344 static inline void fl_rs485_set_delay_time(const unsigned byte) { 00345 *FL_UART(1, RS485DLY) = byte & 0xff; 00346 } 00347 00348 #endif
Generated on Thu Jul 14 2022 22:04:23 by 1.7.2