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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uart.h Source File

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