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

Committer:
Ivop
Date:
Sun Jul 03 17:11:55 2011 +0000
Revision:
0:7a91348b4a02

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Ivop 0:7a91348b4a02 1 /* Copyright (C) 2010, 2011 by Ivo van Poorten <ivop@euronet.nl>
Ivop 0:7a91348b4a02 2 * This file is licensed under the terms of the GNU Lesser
Ivop 0:7a91348b4a02 3 * General Public License, version 3.
Ivop 0:7a91348b4a02 4 */
Ivop 0:7a91348b4a02 5
Ivop 0:7a91348b4a02 6 #ifndef FASTLIB_DMA_H
Ivop 0:7a91348b4a02 7 #define FASTLIB_DMA_H
Ivop 0:7a91348b4a02 8
Ivop 0:7a91348b4a02 9 #include "fastlib/common.h"
Ivop 0:7a91348b4a02 10
Ivop 0:7a91348b4a02 11 #define FL_DMACIntStat ((volatile uint32_t *) 0x50004000)
Ivop 0:7a91348b4a02 12 #define FL_DMACIntTCStat ((volatile uint32_t *) 0x50004004)
Ivop 0:7a91348b4a02 13 #define FL_DMACIntTCClear ((volatile uint32_t *) 0x50004008)
Ivop 0:7a91348b4a02 14 #define FL_DMACIntErrStat ((volatile uint32_t *) 0x5000400C)
Ivop 0:7a91348b4a02 15 #define FL_DMACIntErrClr ((volatile uint32_t *) 0x50004010)
Ivop 0:7a91348b4a02 16 #define FL_DMACRawIntTCStat ((volatile uint32_t *) 0x50004014)
Ivop 0:7a91348b4a02 17 #define FL_DMACRawIntErrStat ((volatile uint32_t *) 0x50004018)
Ivop 0:7a91348b4a02 18 #define FL_DMACEnbldChns ((volatile uint32_t *) 0x5000401C)
Ivop 0:7a91348b4a02 19 #define FL_DMACSoftBReq ((volatile uint32_t *) 0x50004020)
Ivop 0:7a91348b4a02 20 #define FL_DMACSoftSReq ((volatile uint32_t *) 0x50004024)
Ivop 0:7a91348b4a02 21 #define FL_DMACSoftLBReq ((volatile uint32_t *) 0x50004028)
Ivop 0:7a91348b4a02 22 #define FL_DMACSoftLSReq ((volatile uint32_t *) 0x5000402C)
Ivop 0:7a91348b4a02 23 #define FL_DMACConfig ((volatile uint32_t *) 0x50004030)
Ivop 0:7a91348b4a02 24 #define FL_DMACSync ((volatile uint32_t *) 0x50004034)
Ivop 0:7a91348b4a02 25 #define FL_DMAReqSel ((volatile uint32_t *) 0x400FC1C4)
Ivop 0:7a91348b4a02 26
Ivop 0:7a91348b4a02 27 #define FL_DMACC0 0x50004100
Ivop 0:7a91348b4a02 28 #define FL_DMACC1 0x50004120
Ivop 0:7a91348b4a02 29 #define FL_DMACC2 0x50004140
Ivop 0:7a91348b4a02 30 #define FL_DMACC3 0x50004160
Ivop 0:7a91348b4a02 31 #define FL_DMACC4 0x50004180
Ivop 0:7a91348b4a02 32 #define FL_DMACC5 0x500041A0
Ivop 0:7a91348b4a02 33 #define FL_DMACC6 0x500041C0
Ivop 0:7a91348b4a02 34 #define FL_DMACC7 0x500041E0
Ivop 0:7a91348b4a02 35
Ivop 0:7a91348b4a02 36 #define FL_DMA_SrcAddr 0x00
Ivop 0:7a91348b4a02 37 #define FL_DMA_DestAddr 0x04
Ivop 0:7a91348b4a02 38 #define FL_DMA_LLI 0x08
Ivop 0:7a91348b4a02 39 #define FL_DMA_Control 0x0C
Ivop 0:7a91348b4a02 40 #define FL_DMA_Config 0x10
Ivop 0:7a91348b4a02 41
Ivop 0:7a91348b4a02 42 #define FL_DMA(channel, field) \
Ivop 0:7a91348b4a02 43 ((volatile uint32_t *)(fl_dma_channel_to_base(channel) + FL_DMA_##field))
Ivop 0:7a91348b4a02 44
Ivop 0:7a91348b4a02 45 static inline unsigned fl_dma_channel_to_base(const unsigned channel) {
Ivop 0:7a91348b4a02 46 switch(channel) {
Ivop 0:7a91348b4a02 47 case 0: return FL_DMACC0;
Ivop 0:7a91348b4a02 48 case 1: return FL_DMACC1;
Ivop 0:7a91348b4a02 49 case 2: return FL_DMACC2;
Ivop 0:7a91348b4a02 50 case 3: return FL_DMACC3;
Ivop 0:7a91348b4a02 51 case 4: return FL_DMACC4;
Ivop 0:7a91348b4a02 52 case 5: return FL_DMACC5;
Ivop 0:7a91348b4a02 53 case 6: return FL_DMACC6;
Ivop 0:7a91348b4a02 54 default: return FL_DMACC7;
Ivop 0:7a91348b4a02 55 }
Ivop 0:7a91348b4a02 56 }
Ivop 0:7a91348b4a02 57
Ivop 0:7a91348b4a02 58 // channel: 0-7
Ivop 0:7a91348b4a02 59 static inline unsigned fl_dma_channel_has_active_interrupt_request(const unsigned channel) {
Ivop 0:7a91348b4a02 60 return *FL_DMACIntStat & (1U<<channel);
Ivop 0:7a91348b4a02 61 }
Ivop 0:7a91348b4a02 62
Ivop 0:7a91348b4a02 63 static inline unsigned fl_dma_channel_has_active_terminal_count_interrupt_request(const unsigned channel) {
Ivop 0:7a91348b4a02 64 return *FL_DMACIntTCStat & (1U<<channel);
Ivop 0:7a91348b4a02 65 }
Ivop 0:7a91348b4a02 66 static inline void fl_dma_clear_terminal_count_interrupt_request(const unsigned channel) {
Ivop 0:7a91348b4a02 67 *FL_DMACIntTCClear |= 1U<<channel;
Ivop 0:7a91348b4a02 68 }
Ivop 0:7a91348b4a02 69 static inline unsigned fl_dma_channel_has_active_terminal_count_interrupt_request_raw(const unsigned channel) {
Ivop 0:7a91348b4a02 70 return *FL_DMACRawIntTCStat & (1U<<channel); // raw is prior to masking
Ivop 0:7a91348b4a02 71 }
Ivop 0:7a91348b4a02 72
Ivop 0:7a91348b4a02 73 static inline unsigned fl_dma_channel_has_active_error_interrupt_request(const unsigned channel) {
Ivop 0:7a91348b4a02 74 return *FL_DMACIntErrStat & (1U<<channel);
Ivop 0:7a91348b4a02 75 }
Ivop 0:7a91348b4a02 76 static inline void fl_dma_clear_error_interrupt_request(const unsigned channel) {
Ivop 0:7a91348b4a02 77 *FL_DMACIntErrClr |= 1U<<channel;
Ivop 0:7a91348b4a02 78 }
Ivop 0:7a91348b4a02 79 static inline unsigned fl_dma_channel_has_active_error_interrupt_request_raw(const unsigned channel) {
Ivop 0:7a91348b4a02 80 return *FL_DMACRawIntErrStat & (1U<<channel);
Ivop 0:7a91348b4a02 81 }
Ivop 0:7a91348b4a02 82
Ivop 0:7a91348b4a02 83 static inline unsigned fl_dma_channel_is_enabled(const unsigned channel) {
Ivop 0:7a91348b4a02 84 return *FL_DMACEnbldChns & (1U<<channel);
Ivop 0:7a91348b4a02 85 }
Ivop 0:7a91348b4a02 86
Ivop 0:7a91348b4a02 87 static inline void fl_dma_generate_software_burst_request(const unsigned request) {
Ivop 0:7a91348b4a02 88 *FL_DMACSoftBReq |= 1U << request;
Ivop 0:7a91348b4a02 89 }
Ivop 0:7a91348b4a02 90 static inline unsigned fl_dma_software_burst_request_sources(void) {
Ivop 0:7a91348b4a02 91 return *FL_DMACSoftBReq;
Ivop 0:7a91348b4a02 92 }
Ivop 0:7a91348b4a02 93
Ivop 0:7a91348b4a02 94 static inline void fl_dma_generate_software_single_request(const unsigned request) {
Ivop 0:7a91348b4a02 95 *FL_DMACSoftSReq |= 1U << request;
Ivop 0:7a91348b4a02 96 }
Ivop 0:7a91348b4a02 97 static inline unsigned fl_dma_software_single_request_sources(void) {
Ivop 0:7a91348b4a02 98 return *FL_DMACSoftSReq;
Ivop 0:7a91348b4a02 99 }
Ivop 0:7a91348b4a02 100
Ivop 0:7a91348b4a02 101 static inline void fl_dma_generate_software_last_burst_request(const unsigned request) {
Ivop 0:7a91348b4a02 102 *FL_DMACSoftLBReq |= 1U << request;
Ivop 0:7a91348b4a02 103 }
Ivop 0:7a91348b4a02 104 static inline unsigned fl_dma_software_last_burst_request_sources(void) {
Ivop 0:7a91348b4a02 105 return *FL_DMACSoftLBReq;
Ivop 0:7a91348b4a02 106 }
Ivop 0:7a91348b4a02 107
Ivop 0:7a91348b4a02 108 static inline void fl_dma_generate_software_last_single_request(const unsigned request) {
Ivop 0:7a91348b4a02 109 *FL_DMACSoftLSReq |= 1U << request;
Ivop 0:7a91348b4a02 110 }
Ivop 0:7a91348b4a02 111 static inline unsigned fl_dma_software_last_single_request_sources(void) {
Ivop 0:7a91348b4a02 112 return *FL_DMACSoftLSReq;
Ivop 0:7a91348b4a02 113 }
Ivop 0:7a91348b4a02 114
Ivop 0:7a91348b4a02 115 static inline void fl_dma_enable(const unsigned state) {
Ivop 0:7a91348b4a02 116 if (state) *FL_DMACConfig |= 1U<<0 ;
Ivop 0:7a91348b4a02 117 else *FL_DMACConfig &= ~(1U<<0);
Ivop 0:7a91348b4a02 118 }
Ivop 0:7a91348b4a02 119
Ivop 0:7a91348b4a02 120 static inline unsigned fl_dma_is_enabled(void) {
Ivop 0:7a91348b4a02 121 return *FL_DMACConfig & 1;
Ivop 0:7a91348b4a02 122 }
Ivop 0:7a91348b4a02 123
Ivop 0:7a91348b4a02 124 static inline void fl_dma_set_endianness(const unsigned endianness) {
Ivop 0:7a91348b4a02 125 if (endianness) *FL_DMACConfig |= 1U<<1 ;
Ivop 0:7a91348b4a02 126 else *FL_DMACConfig &= ~(1U<<1);
Ivop 0:7a91348b4a02 127 }
Ivop 0:7a91348b4a02 128
Ivop 0:7a91348b4a02 129 static inline void fl_dma_request_synchronization_enable(const unsigned request, const unsigned state) {
Ivop 0:7a91348b4a02 130 if (!state) *FL_DMACSync |= 1U<<request ; // note that 0 is enabled
Ivop 0:7a91348b4a02 131 else *FL_DMACSync &= ~(1U<<request);
Ivop 0:7a91348b4a02 132 }
Ivop 0:7a91348b4a02 133
Ivop 0:7a91348b4a02 134 #define FL_DMA_UART 0
Ivop 0:7a91348b4a02 135 #define FL_DMA_TIMER 1
Ivop 0:7a91348b4a02 136
Ivop 0:7a91348b4a02 137 // select between uart or timer dma requests for inputs 8 through 15
Ivop 0:7a91348b4a02 138 // input: 8-16 which: 0-1
Ivop 0:7a91348b4a02 139 static inline void fl_dma_request_select(const unsigned input, const unsigned which) {
Ivop 0:7a91348b4a02 140 if (which) *FL_DMAReqSel |= 1U<<(which-8) ;
Ivop 0:7a91348b4a02 141 else *FL_DMAReqSel &= ~(1U<<(which-8));
Ivop 0:7a91348b4a02 142 }
Ivop 0:7a91348b4a02 143
Ivop 0:7a91348b4a02 144 // channel: 0-7
Ivop 0:7a91348b4a02 145 static inline void fl_dma_set_srcaddr(const unsigned channel, const void *srcaddr) {
Ivop 0:7a91348b4a02 146 *FL_DMA(channel, SrcAddr) = (unsigned) srcaddr;
Ivop 0:7a91348b4a02 147 }
Ivop 0:7a91348b4a02 148
Ivop 0:7a91348b4a02 149 static inline void fl_dma_set_destaddr(const unsigned channel, const void *destaddr) {
Ivop 0:7a91348b4a02 150 *FL_DMA(channel, DestAddr) = (unsigned) destaddr;
Ivop 0:7a91348b4a02 151 }
Ivop 0:7a91348b4a02 152
Ivop 0:7a91348b4a02 153 // lli must be word-aligned
Ivop 0:7a91348b4a02 154 static inline void fl_dma_set_next_lli(const unsigned channel, const void *lli) {
Ivop 0:7a91348b4a02 155 *FL_DMA(channel, LLI) = (unsigned) lli & (~3U);
Ivop 0:7a91348b4a02 156 }
Ivop 0:7a91348b4a02 157
Ivop 0:7a91348b4a02 158 #define FL_NO_SRC_INCREMENT 0
Ivop 0:7a91348b4a02 159 #define FL_SRC_INCREMENT 1
Ivop 0:7a91348b4a02 160 #define FL_NO_DEST_INCREMENT 0
Ivop 0:7a91348b4a02 161 #define FL_DEST_INCREMENT 1
Ivop 0:7a91348b4a02 162
Ivop 0:7a91348b4a02 163 static inline unsigned fl_dma_size_to_mask(const unsigned size) {
Ivop 0:7a91348b4a02 164 switch(size) {
Ivop 0:7a91348b4a02 165 case 4: return 1;
Ivop 0:7a91348b4a02 166 case 8: return 2;
Ivop 0:7a91348b4a02 167 case 16: return 3;
Ivop 0:7a91348b4a02 168 case 32: return 4;
Ivop 0:7a91348b4a02 169 case 64: return 5;
Ivop 0:7a91348b4a02 170 case 128: return 6;
Ivop 0:7a91348b4a02 171 case 256: return 7;
Ivop 0:7a91348b4a02 172 default: return 0;
Ivop 0:7a91348b4a02 173 }
Ivop 0:7a91348b4a02 174 }
Ivop 0:7a91348b4a02 175
Ivop 0:7a91348b4a02 176 static inline unsigned fl_dma_width_to_mask(const unsigned width) {
Ivop 0:7a91348b4a02 177 switch(width) {
Ivop 0:7a91348b4a02 178 case 16: return 1;
Ivop 0:7a91348b4a02 179 case 32: return 2;
Ivop 0:7a91348b4a02 180 default: return 0;
Ivop 0:7a91348b4a02 181 }
Ivop 0:7a91348b4a02 182 }
Ivop 0:7a91348b4a02 183
Ivop 0:7a91348b4a02 184 // transfer_size: 12 bits
Ivop 0:7a91348b4a02 185 // size: 1, 4, 8, 16, 32, 64, 128 or 256
Ivop 0:7a91348b4a02 186 // width: 8, 16 or 32
Ivop 0:7a91348b4a02 187 // irq: 0-1
Ivop 0:7a91348b4a02 188 static inline void fl_dma_channel_control(const unsigned channel, const unsigned transfer_size,
Ivop 0:7a91348b4a02 189 const unsigned src_burst_size, const unsigned dest_burst_size,
Ivop 0:7a91348b4a02 190 const unsigned src_width, const unsigned dest_width,
Ivop 0:7a91348b4a02 191 const unsigned src_increment, const unsigned dest_increment,
Ivop 0:7a91348b4a02 192 const unsigned terminal_count_irq) {
Ivop 0:7a91348b4a02 193 *FL_DMA(channel, Control) = transfer_size & 0xfff
Ivop 0:7a91348b4a02 194 | (fl_dma_size_to_mask(src_burst_size) << 12)
Ivop 0:7a91348b4a02 195 | (fl_dma_size_to_mask(dest_burst_size) << 15)
Ivop 0:7a91348b4a02 196 | (fl_dma_width_to_mask(src_width) << 18)
Ivop 0:7a91348b4a02 197 | (fl_dma_width_to_mask(dest_width) << 21)
Ivop 0:7a91348b4a02 198 | (src_increment << 26)
Ivop 0:7a91348b4a02 199 | (dest_increment << 27)
Ivop 0:7a91348b4a02 200 | (terminal_count_irq << 31);
Ivop 0:7a91348b4a02 201 }
Ivop 0:7a91348b4a02 202
Ivop 0:7a91348b4a02 203 static inline void fl_dma_channel_control_by_mask(const unsigned channel, const unsigned mask) {
Ivop 0:7a91348b4a02 204 *FL_DMA(channel, Control) = mask;
Ivop 0:7a91348b4a02 205 }
Ivop 0:7a91348b4a02 206
Ivop 0:7a91348b4a02 207 static inline unsigned fl_dma_channel_get_control_mask(const unsigned channel) {
Ivop 0:7a91348b4a02 208 return *FL_DMA(channel, Control);
Ivop 0:7a91348b4a02 209 }
Ivop 0:7a91348b4a02 210
Ivop 0:7a91348b4a02 211 static inline void fl_dma_channel_terminal_count_irq_enable(const unsigned channel, const unsigned state) {
Ivop 0:7a91348b4a02 212 if (state) *FL_DMA(channel, Control) |= 1U<<31 ;
Ivop 0:7a91348b4a02 213 else *FL_DMA(channel, Control) &= ~(1U<<31);
Ivop 0:7a91348b4a02 214 }
Ivop 0:7a91348b4a02 215
Ivop 0:7a91348b4a02 216 // channel configuration constants, src and dest peripherals
Ivop 0:7a91348b4a02 217 #define FL_DMA_SINGLE_REQUEST_SSP0_Tx 0
Ivop 0:7a91348b4a02 218 #define FL_DMA_SINGLE_REQUEST_SSP0_Rx 1
Ivop 0:7a91348b4a02 219 #define FL_DMA_SINGLE_REQUEST_SSP1_Tx 2
Ivop 0:7a91348b4a02 220 #define FL_DMA_SINGLE_REQUEST_SSP1_Rx 3
Ivop 0:7a91348b4a02 221 #define FL_DMA_SINGLE_REQUEST_ADC 4
Ivop 0:7a91348b4a02 222
Ivop 0:7a91348b4a02 223 #define FL_DMA_BURST_REQUEST_SSP0_Tx 0
Ivop 0:7a91348b4a02 224 #define FL_DMA_BURST_REQUEST_SSP0_Rx 1
Ivop 0:7a91348b4a02 225 #define FL_DMA_BURST_REQUEST_SSP1_Tx 2
Ivop 0:7a91348b4a02 226 #define FL_DMA_BURST_REQUEST_SSP1_Rx 3
Ivop 0:7a91348b4a02 227 #define FL_DMA_BURST_REQUEST_ADC 4
Ivop 0:7a91348b4a02 228 #define FL_DMA_BURST_REQUEST_I2S_CH0 5
Ivop 0:7a91348b4a02 229 #define FL_DMA_BURST_REQUEST_I2S_CH1 6
Ivop 0:7a91348b4a02 230 #define FL_DMA_BURST_REQUEST_DAC 7
Ivop 0:7a91348b4a02 231 #define FL_DMA_BURST_REQUEST_UART0_Tx 8
Ivop 0:7a91348b4a02 232 #define FL_DMA_BURST_REQUEST_UART0_Rx 9
Ivop 0:7a91348b4a02 233 #define FL_DMA_BURST_REQUEST_UART1_Tx 10
Ivop 0:7a91348b4a02 234 #define FL_DMA_BURST_REQUEST_uART1_Rx 11
Ivop 0:7a91348b4a02 235 #define FL_DMA_BURST_REQUEST_UART2_Tx 12
Ivop 0:7a91348b4a02 236 #define FL_DMA_BURST_REQUEST_UART2_Rx 13
Ivop 0:7a91348b4a02 237 #define FL_DMA_BURST_REQUEST_UART3_Tx 14
Ivop 0:7a91348b4a02 238 #define FL_DMA_BURST_REQUEST_UART3_Rx 15
Ivop 0:7a91348b4a02 239
Ivop 0:7a91348b4a02 240 #define FL_DMA_PERIPHERAL_IS_MEMORY 0
Ivop 0:7a91348b4a02 241
Ivop 0:7a91348b4a02 242 // transfer types
Ivop 0:7a91348b4a02 243 #define FL_DMA_MEMORY_TO_MEMORY 0
Ivop 0:7a91348b4a02 244 #define FL_DMA_MEMORY_TO_PERIPHERAL 1
Ivop 0:7a91348b4a02 245 #define FL_DMA_PERIPHERAL_TO_MEMORY 2
Ivop 0:7a91348b4a02 246 #define FL_DMA_PERIPHERAL_TO_PERIPHERAL 3
Ivop 0:7a91348b4a02 247
Ivop 0:7a91348b4a02 248 static inline void fl_dma_channel_config(const unsigned channel,
Ivop 0:7a91348b4a02 249 const unsigned enable, const unsigned src_peripheral, const unsigned dest_peripheral,
Ivop 0:7a91348b4a02 250 const unsigned transfer_type, const unsigned mask_error, const unsigned mask_tc) {
Ivop 0:7a91348b4a02 251 *FL_DMA(channel, Config) = enable | (src_peripheral<<1) | (dest_peripheral<<6) |
Ivop 0:7a91348b4a02 252 (transfer_type<<11) | (mask_error<<14) | (mask_tc<<15);
Ivop 0:7a91348b4a02 253 }
Ivop 0:7a91348b4a02 254
Ivop 0:7a91348b4a02 255 // return 0 or !0 (channel fifo has data)
Ivop 0:7a91348b4a02 256 static inline unsigned fl_dma_channel_is_active(const unsigned channel) {
Ivop 0:7a91348b4a02 257 return *FL_DMA(channel, Config) & (1U<<17);
Ivop 0:7a91348b4a02 258 }
Ivop 0:7a91348b4a02 259
Ivop 0:7a91348b4a02 260 static inline void fl_dma_channel_halt(const unsigned channel, const unsigned state) {
Ivop 0:7a91348b4a02 261 if (state) *FL_DMA(channel, Config) |= 1U<<18 ;
Ivop 0:7a91348b4a02 262 else *FL_DMA(channel, Config) &= ~(1U<<18);
Ivop 0:7a91348b4a02 263 }
Ivop 0:7a91348b4a02 264
Ivop 0:7a91348b4a02 265 #endif