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 dma.h Source File

dma.h

00001 /* Copyright (C) 2010, 2011 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_DMA_H
00007 #define FASTLIB_DMA_H
00008 
00009 #include "fastlib/common.h"
00010 
00011 #define FL_DMACIntStat          ((volatile uint32_t *) 0x50004000)
00012 #define FL_DMACIntTCStat        ((volatile uint32_t *) 0x50004004)
00013 #define FL_DMACIntTCClear       ((volatile uint32_t *) 0x50004008)
00014 #define FL_DMACIntErrStat       ((volatile uint32_t *) 0x5000400C)
00015 #define FL_DMACIntErrClr        ((volatile uint32_t *) 0x50004010)
00016 #define FL_DMACRawIntTCStat     ((volatile uint32_t *) 0x50004014)
00017 #define FL_DMACRawIntErrStat    ((volatile uint32_t *) 0x50004018)
00018 #define FL_DMACEnbldChns        ((volatile uint32_t *) 0x5000401C)
00019 #define FL_DMACSoftBReq         ((volatile uint32_t *) 0x50004020)
00020 #define FL_DMACSoftSReq         ((volatile uint32_t *) 0x50004024)
00021 #define FL_DMACSoftLBReq        ((volatile uint32_t *) 0x50004028)
00022 #define FL_DMACSoftLSReq        ((volatile uint32_t *) 0x5000402C)
00023 #define FL_DMACConfig           ((volatile uint32_t *) 0x50004030)
00024 #define FL_DMACSync             ((volatile uint32_t *) 0x50004034)
00025 #define FL_DMAReqSel            ((volatile uint32_t *) 0x400FC1C4)
00026 
00027 #define FL_DMACC0   0x50004100
00028 #define FL_DMACC1   0x50004120
00029 #define FL_DMACC2   0x50004140
00030 #define FL_DMACC3   0x50004160
00031 #define FL_DMACC4   0x50004180
00032 #define FL_DMACC5   0x500041A0
00033 #define FL_DMACC6   0x500041C0
00034 #define FL_DMACC7   0x500041E0
00035 
00036 #define FL_DMA_SrcAddr  0x00
00037 #define FL_DMA_DestAddr 0x04
00038 #define FL_DMA_LLI      0x08
00039 #define FL_DMA_Control  0x0C
00040 #define FL_DMA_Config   0x10
00041 
00042 #define FL_DMA(channel, field) \
00043     ((volatile uint32_t *)(fl_dma_channel_to_base(channel) + FL_DMA_##field))
00044 
00045 static inline unsigned fl_dma_channel_to_base(const unsigned channel) {
00046     switch(channel) {
00047     case 0:  return FL_DMACC0;
00048     case 1:  return FL_DMACC1;
00049     case 2:  return FL_DMACC2;
00050     case 3:  return FL_DMACC3;
00051     case 4:  return FL_DMACC4;
00052     case 5:  return FL_DMACC5;
00053     case 6:  return FL_DMACC6;
00054     default: return FL_DMACC7;
00055     }
00056 }
00057 
00058 // channel: 0-7
00059 static inline unsigned fl_dma_channel_has_active_interrupt_request(const unsigned channel) {
00060     return *FL_DMACIntStat & (1U<<channel);
00061 }
00062 
00063 static inline unsigned fl_dma_channel_has_active_terminal_count_interrupt_request(const unsigned channel) {
00064     return *FL_DMACIntTCStat & (1U<<channel);
00065 }
00066 static inline void fl_dma_clear_terminal_count_interrupt_request(const unsigned channel) {
00067     *FL_DMACIntTCClear |= 1U<<channel;
00068 }
00069 static inline unsigned fl_dma_channel_has_active_terminal_count_interrupt_request_raw(const unsigned channel) {
00070     return *FL_DMACRawIntTCStat & (1U<<channel);     // raw is prior to masking
00071 }
00072 
00073 static inline unsigned fl_dma_channel_has_active_error_interrupt_request(const unsigned channel) {
00074     return *FL_DMACIntErrStat & (1U<<channel);
00075 }
00076 static inline void fl_dma_clear_error_interrupt_request(const unsigned channel) {
00077     *FL_DMACIntErrClr |= 1U<<channel;
00078 }
00079 static inline unsigned fl_dma_channel_has_active_error_interrupt_request_raw(const unsigned channel) {
00080     return *FL_DMACRawIntErrStat & (1U<<channel);
00081 }
00082 
00083 static inline unsigned fl_dma_channel_is_enabled(const unsigned channel) {
00084     return *FL_DMACEnbldChns & (1U<<channel);
00085 }
00086 
00087 static inline void fl_dma_generate_software_burst_request(const unsigned request) {
00088     *FL_DMACSoftBReq |= 1U << request;
00089 }
00090 static inline unsigned fl_dma_software_burst_request_sources(void) {
00091     return *FL_DMACSoftBReq;
00092 }
00093 
00094 static inline void fl_dma_generate_software_single_request(const unsigned request) {
00095     *FL_DMACSoftSReq |= 1U << request;
00096 }
00097 static inline unsigned fl_dma_software_single_request_sources(void) {
00098     return *FL_DMACSoftSReq;
00099 }
00100 
00101 static inline void fl_dma_generate_software_last_burst_request(const unsigned request) {
00102     *FL_DMACSoftLBReq |= 1U << request;
00103 }
00104 static inline unsigned fl_dma_software_last_burst_request_sources(void) {
00105     return *FL_DMACSoftLBReq;
00106 }
00107 
00108 static inline void fl_dma_generate_software_last_single_request(const unsigned request) {
00109     *FL_DMACSoftLSReq |= 1U << request;
00110 }
00111 static inline unsigned fl_dma_software_last_single_request_sources(void) {
00112     return *FL_DMACSoftLSReq;
00113 }
00114 
00115 static inline void fl_dma_enable(const unsigned state) {
00116     if (state) *FL_DMACConfig |=   1U<<0 ;
00117     else       *FL_DMACConfig &= ~(1U<<0);
00118 }
00119 
00120 static inline unsigned fl_dma_is_enabled(void) {
00121     return *FL_DMACConfig & 1;
00122 }
00123 
00124 static inline void fl_dma_set_endianness(const unsigned endianness) {
00125     if (endianness) *FL_DMACConfig |=   1U<<1 ;
00126     else            *FL_DMACConfig &= ~(1U<<1);
00127 }
00128 
00129 static inline void fl_dma_request_synchronization_enable(const unsigned request, const unsigned state) {
00130     if (!state) *FL_DMACSync |=   1U<<request ;     // note that 0 is enabled
00131     else        *FL_DMACSync &= ~(1U<<request);
00132 }
00133 
00134 #define FL_DMA_UART     0
00135 #define FL_DMA_TIMER    1
00136 
00137 // select between uart or timer dma requests for inputs 8 through 15
00138 // input: 8-16  which: 0-1
00139 static inline void fl_dma_request_select(const unsigned input, const unsigned which) {
00140     if (which) *FL_DMAReqSel |=   1U<<(which-8) ;
00141     else       *FL_DMAReqSel &= ~(1U<<(which-8));
00142 }
00143 
00144 // channel: 0-7
00145 static inline void fl_dma_set_srcaddr(const unsigned channel, const void *srcaddr) {
00146     *FL_DMA(channel, SrcAddr) = (unsigned) srcaddr;
00147 }
00148 
00149 static inline void fl_dma_set_destaddr(const unsigned channel, const void *destaddr) {
00150     *FL_DMA(channel, DestAddr) = (unsigned) destaddr;
00151 }
00152 
00153 // lli must be word-aligned
00154 static inline void fl_dma_set_next_lli(const unsigned channel, const void *lli) {
00155     *FL_DMA(channel, LLI) = (unsigned) lli & (~3U);
00156 }
00157 
00158 #define FL_NO_SRC_INCREMENT     0
00159 #define FL_SRC_INCREMENT        1
00160 #define FL_NO_DEST_INCREMENT    0
00161 #define FL_DEST_INCREMENT       1
00162 
00163 static inline unsigned fl_dma_size_to_mask(const unsigned size) {
00164     switch(size) {
00165     case 4:     return 1;
00166     case 8:     return 2;
00167     case 16:    return 3;
00168     case 32:    return 4;
00169     case 64:    return 5;
00170     case 128:   return 6;
00171     case 256:   return 7;
00172     default:    return 0;
00173     }
00174 }
00175 
00176 static inline unsigned fl_dma_width_to_mask(const unsigned width) {
00177     switch(width) {
00178     case 16:    return 1;
00179     case 32:    return 2;
00180     default:    return 0;
00181     }
00182 }
00183 
00184 // transfer_size: 12 bits
00185 // size: 1, 4, 8, 16, 32, 64, 128 or 256
00186 // width: 8, 16 or 32
00187 // irq: 0-1
00188 static inline void fl_dma_channel_control(const unsigned channel, const unsigned transfer_size,
00189                                           const unsigned src_burst_size, const unsigned dest_burst_size,
00190                                           const unsigned src_width, const unsigned dest_width,
00191                                           const unsigned src_increment, const unsigned dest_increment,
00192                                           const unsigned terminal_count_irq) {
00193     *FL_DMA(channel, Control) = transfer_size & 0xfff
00194                               | (fl_dma_size_to_mask(src_burst_size)  << 12)
00195                               | (fl_dma_size_to_mask(dest_burst_size) << 15)
00196                               | (fl_dma_width_to_mask(src_width)  << 18)
00197                               | (fl_dma_width_to_mask(dest_width) << 21)
00198                               | (src_increment  << 26)
00199                               | (dest_increment << 27)
00200                               | (terminal_count_irq << 31);
00201 }
00202 
00203 static inline void fl_dma_channel_control_by_mask(const unsigned channel, const unsigned mask) {
00204     *FL_DMA(channel, Control) = mask;
00205 }
00206 
00207 static inline unsigned fl_dma_channel_get_control_mask(const unsigned channel) {
00208     return *FL_DMA(channel, Control);
00209 }
00210 
00211 static inline void fl_dma_channel_terminal_count_irq_enable(const unsigned channel, const unsigned state) {
00212     if (state) *FL_DMA(channel, Control) |=   1U<<31 ;
00213     else       *FL_DMA(channel, Control) &= ~(1U<<31);
00214 }
00215 
00216 // channel configuration constants, src and dest peripherals
00217 #define FL_DMA_SINGLE_REQUEST_SSP0_Tx   0
00218 #define FL_DMA_SINGLE_REQUEST_SSP0_Rx   1
00219 #define FL_DMA_SINGLE_REQUEST_SSP1_Tx   2
00220 #define FL_DMA_SINGLE_REQUEST_SSP1_Rx   3
00221 #define FL_DMA_SINGLE_REQUEST_ADC       4
00222 
00223 #define FL_DMA_BURST_REQUEST_SSP0_Tx    0
00224 #define FL_DMA_BURST_REQUEST_SSP0_Rx    1
00225 #define FL_DMA_BURST_REQUEST_SSP1_Tx    2
00226 #define FL_DMA_BURST_REQUEST_SSP1_Rx    3
00227 #define FL_DMA_BURST_REQUEST_ADC        4
00228 #define FL_DMA_BURST_REQUEST_I2S_CH0    5
00229 #define FL_DMA_BURST_REQUEST_I2S_CH1    6
00230 #define FL_DMA_BURST_REQUEST_DAC        7
00231 #define FL_DMA_BURST_REQUEST_UART0_Tx   8
00232 #define FL_DMA_BURST_REQUEST_UART0_Rx   9
00233 #define FL_DMA_BURST_REQUEST_UART1_Tx   10
00234 #define FL_DMA_BURST_REQUEST_uART1_Rx   11
00235 #define FL_DMA_BURST_REQUEST_UART2_Tx   12
00236 #define FL_DMA_BURST_REQUEST_UART2_Rx   13
00237 #define FL_DMA_BURST_REQUEST_UART3_Tx   14
00238 #define FL_DMA_BURST_REQUEST_UART3_Rx   15
00239 
00240 #define FL_DMA_PERIPHERAL_IS_MEMORY     0
00241 
00242 // transfer types
00243 #define FL_DMA_MEMORY_TO_MEMORY         0
00244 #define FL_DMA_MEMORY_TO_PERIPHERAL     1
00245 #define FL_DMA_PERIPHERAL_TO_MEMORY     2
00246 #define FL_DMA_PERIPHERAL_TO_PERIPHERAL 3
00247 
00248 static inline void fl_dma_channel_config(const unsigned channel,
00249     const unsigned enable, const unsigned src_peripheral, const unsigned dest_peripheral,
00250     const unsigned transfer_type, const unsigned mask_error, const unsigned mask_tc) {
00251     *FL_DMA(channel, Config) = enable | (src_peripheral<<1) | (dest_peripheral<<6) |
00252                                (transfer_type<<11) | (mask_error<<14) | (mask_tc<<15);
00253 }
00254 
00255 // return 0 or !0 (channel fifo has data)
00256 static inline unsigned fl_dma_channel_is_active(const unsigned channel) {
00257     return *FL_DMA(channel, Config) & (1U<<17);
00258 }
00259 
00260 static inline void fl_dma_channel_halt(const unsigned channel, const unsigned state) {
00261     if (state) *FL_DMA(channel, Config) |=   1U<<18 ;
00262     else       *FL_DMA(channel, Config) &= ~(1U<<18);
00263 }
00264 
00265 #endif