APM:Libraries
dma.c
Go to the documentation of this file.
1 /******************************************************************************
2  * The MIT License
3  *
4  (c) 2017 night_ghost@ykoctpa.ru
5 
6 based on:
7 
8  * Copyright (c) 2010 Michael Hope.
9  *
10  * Permission is hereby granted, free of charge, to any person
11  * obtaining a copy of this software and associated documentation
12  * files (the "Software"), to deal in the Software without
13  * restriction, including without limitation the rights to use, copy,
14  * modify, merge, publish, distribute, sublicense, and/or sell copies
15  * of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *****************************************************************************/
30 
31 
38 #pragma GCC optimize ("O2")
39 
40 #include "dma.h"
41 #include "bitband.h"
42 #include <string.h>
43 #include "util.h"
44 #include "nvic.h"
45 
46 /*
47  * Devices
48  */
49 
50 static Handler dma1_handlers[8] IN_CCM;
51 
52 static const dma_dev dma1 = {
53  .regs = (dma_reg_map *)DMA1_BASE,
54  .clk_id = RCC_AHB1Periph_DMA1,
55  .irq_lines = { DMA1_Stream0_IRQn, DMA1_Stream1_IRQn, DMA1_Stream2_IRQn, DMA1_Stream3_IRQn, DMA1_Stream4_IRQn, DMA1_Stream5_IRQn, DMA1_Stream6_IRQn, DMA1_Stream7_IRQn},
56  .handlers = dma1_handlers
57 };
59 //const dma_dev * const _DMA1 = &dma1;
60 
61 
62 static Handler dma2_handlers[8] IN_CCM;
63 
64 static const dma_dev dma2 = {
65  .regs = (dma_reg_map *)DMA2_BASE,
66  .clk_id = RCC_AHB1Periph_DMA2,
67  .irq_lines = { DMA2_Stream0_IRQn, DMA2_Stream1_IRQn, DMA2_Stream2_IRQn, DMA2_Stream3_IRQn, DMA2_Stream4_IRQn, DMA2_Stream5_IRQn, DMA2_Stream6_IRQn, DMA2_Stream7_IRQn},
68  .handlers = dma2_handlers
69 
70 };
72 //const dma_dev * const _DMA2 = &dma2;
73 
74 static const dma_dev * const DMAS[] = { &dma1, &dma2 };
75 
76 /*
77  * Convenience routines
78  */
79 
84 //void dma_init(const dma_dev *dev) {
85 void dma_init(dma_stream stream) {
86  const dma_dev * dev=DMAS[(stream>>4) & 3];
87  stream &= 0xF;
88 
89  memset(dev->handlers, 0, 8 * sizeof(Handler));
90 
91  RCC_AHB1PeriphClockCmd(dev->clk_id, ENABLE);
92 
93  dev->regs->STREAM[stream].CR &= ~DMA_CR_EN;
94 }
95 
108 void dma_attach_interrupt(dma_stream stream, Handler handler, uint8_t flag) {
109 
110  const dma_dev * dev=DMAS[(stream>>4) & 3];
111  stream &= 0xF;
112 
113  dev->handlers[stream] = handler;
114  IRQn_Type irq = dev->irq_lines[stream];
115 
117 
118  dev->regs->STREAM[stream].CR |= flag;
119 }
120 
133  const dma_dev * dev=DMAS[(stream>>4) & 3];
134  stream &= 0xF;
135 
136  NVIC_DisableIRQ(dev->irq_lines[stream]);
137  dev->handlers[stream] = 0;
138 
139  dev->regs->STREAM[stream].CR &= ~ (DMA_CR_TCIE | DMA_CR_HTIE | DMA_CR_TEIE | DMA_CR_DMEIE ); //0x1e;
140 }
141 
142 
143 // ST similar way
145  uint32_t tmpreg;
146 
147  const dma_dev * dev=DMAS[(stream>>4) & 3];
148  stream &= 0xF;
149  dma_stream_t *DMAy_Streamx = &dev->regs->STREAM[stream];
150 
151  DMAy_Streamx->CR &= ~DMA_CR_EN; // disable
152  DMAy_Streamx->PAR = (uint32_t)v->DMA_PeripheralBaseAddr;
153  DMAy_Streamx->M0AR = (uint32_t)v->DMA_Memory0BaseAddr;
154  DMAy_Streamx->NDTR = v->DMA_BufferSize;
155 
156  /*------------------------- DMAy Streamx CR Configuration ------------------*/
157  /* Get the DMAy_Streamx CR value */
158  tmpreg = DMAy_Streamx->CR;
159 
160  /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */
161  tmpreg &= ((uint32_t)~(DMA_SxCR_CHSEL | DMA_SxCR_MBURST | DMA_SxCR_PBURST | \
162  DMA_SxCR_PL | DMA_SxCR_MSIZE | DMA_SxCR_PSIZE | \
163  DMA_SxCR_MINC | DMA_SxCR_PINC | DMA_SxCR_CIRC | \
164  DMA_SxCR_DIR));
165 
166  /* Configure DMAy Streamx: */
167  /* Set CHSEL bits according to DMA_CHSEL value */
168  /* Set DIR bits according to DMA_DIR value */
169  /* Set PINC bit according to DMA_PeripheralInc value */
170  /* Set MINC bit according to DMA_MemoryInc value */
171  /* Set PSIZE bits according to DMA_PeripheralDataSize value */
172  /* Set MSIZE bits according to DMA_MemoryDataSize value */
173  /* Set CIRC bit according to DMA_Mode value */
174  /* Set PL bits according to DMA_Priority value */
175  /* Set MBURST bits according to DMA_MemoryBurst value */
176  /* Set PBURST bits according to DMA_PeripheralBurst value */
177  tmpreg |= v->DMA_flags;
178 /*
179  tmpreg |= v->DMA_Channel | v->DMA_DIR |
180  v->DMA_PeripheralInc | v->DMA_MemoryInc |
181  v->DMA_PeripheralDataSize | v->DMA_MemoryDataSize |
182  v->DMA_Mode | v->DMA_Priority |
183  v->DMA_MemoryBurst | v->DMA_PeripheralBurst;
184 */
185 
186  /* Write to DMAy Streamx CR register */
187  DMAy_Streamx->CR = tmpreg;
188 
189  /*------------------------- DMAy Streamx FCR Configuration -----------------*/
190  /* Get the DMAy_Streamx FCR value */
191  tmpreg = DMAy_Streamx->FCR;
192 
193  /* Clear DMDIS and FTH bits */
194  tmpreg &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);
195 
196  /* Configure DMAy Streamx FIFO:
197  Set DMDIS bits according to DMA_FIFOMode value
198  Set FTH bits according to DMA_FIFOThreshold value */
199  tmpreg |= v->DMA_FIFO_flags;
200 
201  /* Write to DMAy Streamx FCR */
202  DMAy_Streamx->FCR = tmpreg;
203 }
204 
205 
206 void dma_set_num_transfers(dma_stream stream, uint16_t num_transfers) {
207  const dma_dev * dev=DMAS[(stream>>4) & 3];
208  stream &= 0xF;
209  dev->regs->STREAM[stream].NDTR = num_transfers;
210 }
211 
212 
213 void dma_enable(dma_stream stream) {
214  const dma_dev * dev=DMAS[(stream>>4) & 3];
215  stream &= 0xF;
216  dev->regs->STREAM[stream].CR |= DMA_CR_EN;
217 }
218 
219 void dma_disable(dma_stream stream) {
220  const dma_dev * dev=DMAS[(stream>>4) & 3];
221  stream &= 0xF;
222  dev->regs->STREAM[stream].CR &= ~DMA_CR_EN;
223 }
224 
231  const dma_dev * dev=DMAS[(stream>>4) & 3];
232  stream &= 0xF;
233  return (uint8_t)(dev->regs->STREAM[stream].CR & DMA_CR_EN);
234 }
235 
236 
238  const dma_dev * dev=DMAS[(stream>>4) & 3];
239  stream &= 0xF;
240 
241  switch (stream) {
242  case 0:
243  dev->regs->LIFCR|= 0x0000003d;
244  break;
245  case 1:
246  dev->regs->LIFCR|=0x00000f40;
247  break;
248  case 2:
249  dev->regs->LIFCR|=0x003d0000;
250  break;
251  case 3:
252  dev->regs->LIFCR|=0x0f400000;
253  break;
254  case 4:
255  dev->regs->HIFCR|=0x0000003d;
256  break;
257  case 5:
258  dev->regs->HIFCR|=0x00000f40;
259  break;
260  case 6:
261  dev->regs->HIFCR|=0x003d0000;
262  break;
263  case 7:
264  dev->regs->HIFCR|=0x0f400000;
265  break;
266 
267  default:
268  break;
269  }
270 }
271 
272 uint8_t dma_get_isr_bits(dma_stream stream) {
273  const dma_dev * dev=DMAS[(stream>>4) & 3];
274  stream &= 0xF;
275 
276  uint32_t reg;
277 
278  switch (stream) {
279  case 0:
280  case 1:
281  case 2:
282  case 3:
283  reg = dev->regs->LISR;
284  break;
285 
286  default:
287  reg = dev->regs->HISR;
288  break;
289  }
290 
291 
292  switch (stream) {
293  case 0:
294  return (reg >> 0) & 0x0000003d;
295  case 1:
296  return (reg >> 6) & 0x0000003d;
297  case 2:
298  return (reg >> 16) & 0x0000003d;
299  case 3:
300  return (reg >> 22) & 0x0000003d;
301 
302  case 4:
303  return (reg >> 0) & 0x0000003d;
304  case 5:
305  return (reg >> 6) & 0x0000003d;
306  case 6:
307  return (reg >> 16) & 0x0000003d;
308  case 7:
309  return (reg >> 22) & 0x0000003d;
310 
311  default:
312  return 0;
313  }
314 }
315 
316 
317 /*
318  * IRQ handlers
319  */
320 
321 static void dispatch_handler(dma_stream stream) {
322 #ifdef ISR_PERF
323  t = stopwatch_getticks();
324 #endif
325  const dma_dev * dev=DMAS[(stream>>4) & 3];
326 
327  Handler handler = dev->handlers[stream & 0xF];
328  if (handler) {
329  revo_call_handler(handler, (uint32_t)stream);
330  }
331  dma_clear_isr_bits(stream); /* in case handler doesn't */
332 #ifdef ISR_PERF
333  t = stopwatch_getticks() - t;
334  isr_time += t;
335  if(t>max_isr_time) max_isr_time=t;
336 #endif
337 }
338 
341 }
342 
345 }
346 
349 }
350 
353 }
354 
357 }
358 
361 }
362 
365 }
366 
369 }
370 
373 }
374 
377 }
378 
381 }
382 
385 }
386 
389 }
390 
393 }
394 
397 }
398 
401 }
402 
IRQn_Type irq_lines[8]
Definition: dma.h:203
void DMA2_Stream0_IRQHandler(void)
Definition: dma.c:371
dma_stream_t STREAM[8]
Definition: dma.h:88
static uint32_t stopwatch_getticks()
Definition: stopwatch.h:33
__IO uint32_t LIFCR
Definition: dma.h:86
static void dispatch_handler(dma_stream stream)
Definition: dma.c:321
static const dma_dev *const DMAS[]
Definition: dma.c:74
uint32_t DMA_flags
Definition: dma.h:275
void DMA1_Stream1_IRQHandler(void)
Definition: dma.c:343
void dma_set_num_transfers(dma_stream stream, uint16_t num_transfers)
Definition: dma.c:206
uint32_t DMA_PeripheralBaseAddr
Definition: dma.h:259
__IO uint32_t PAR
Definition: dma.h:53
__IO uint32_t CR
Definition: dma.h:51
void dma_clear_isr_bits(dma_stream stream)
Clear the ISR status bits for a given DMA stream.
Definition: dma.c:237
void DMA1_Stream3_IRQHandler(void)
Definition: dma.c:351
void DMA1_Stream6_IRQHandler(void)
Definition: dma.c:363
#define DMA_CR_TEIE
Definition: dma.h:144
DMA register map type.
Definition: dma.h:83
void DMA1_Stream5_IRQHandler(void)
Definition: dma.c:359
__IO uint32_t HISR
Definition: dma.h:85
__IO uint32_t FCR
Definition: dma.h:56
uint8_t dma_get_isr_bits(dma_stream stream)
Get the ISR status bits for a DMA stream.
Definition: dma.c:272
uint8_t dma_is_stream_enabled(dma_stream stream)
Check if a DMA stream is enabled.
Definition: dma.c:230
__IO uint32_t LISR
Definition: dma.h:84
static AP_HAL::OwnPtr< AP_HAL::Device > dev
Definition: ICM20789.cpp:16
void DMA1_Stream0_IRQHandler(void)
Definition: dma.c:339
void DMA2_Stream2_IRQHandler(void)
Definition: dma.c:379
void enable_nvic_irq(uint8_t irq, uint8_t prio)
Definition: nvic.c:8
Miscellaneous utility macros and procedures.
void DMA2_Stream1_IRQHandler(void)
Definition: dma.c:375
void DMA2_Stream6_IRQHandler(void)
Definition: dma.c:395
static const dma_dev dma1
Definition: dma.c:52
float v
Definition: Printf.cpp:15
void DMA1_Stream4_IRQHandler(void)
Definition: dma.c:355
uint32_t DMA_FIFO_flags
Definition: dma.h:270
void dma_detach_interrupt(dma_stream stream)
Detach a DMA transfer interrupt handler.
Definition: dma.c:132
dma_reg_map * regs
Definition: dma.h:201
Bit-banding utility functions.
enum Dma_stream dma_stream
void DMA2_Stream4_IRQHandler(void)
Definition: dma.c:387
#define DMA_IOC_INT_PRIORITY
Definition: Config.h:46
__IO uint32_t HIFCR
Definition: dma.h:87
Handler * handlers
Definition: dma.h:204
uint32_t clk_id
Definition: dma.h:202
uint32_t DMA_BufferSize
Definition: dma.h:265
void dma_disable(dma_stream stream)
Definition: dma.c:219
void dma_init_transfer(dma_stream stream, DMA_InitType *v)
Definition: dma.c:144
void DMA2_Stream7_IRQHandler(void)
Definition: dma.c:399
#define DMA_CR_EN
Definition: dma.h:146
#define DMA_CR_HTIE
Definition: dma.h:143
void dma_attach_interrupt(dma_stream stream, Handler handler, uint8_t flag)
Attach an interrupt to a DMA transfer.
Definition: dma.c:108
#define DMA_CR_TCIE
Definition: dma.h:142
uint32_t DMA_Memory0BaseAddr
Definition: dma.h:261
static const dma_dev dma2
Definition: dma.c:64
void DMA1_Stream7_IRQHandler(void)
Definition: dma.c:367
static Handler dma1_handlers [8] IN_CCM
Definition: dma.c:50
void dma_init(dma_stream stream)
Initialize a DMA device.
Definition: dma.c:85
void uint32_t uint32_t uint32_t flag
Definition: systick.h:80
#define DMA_CR_DMEIE
Definition: dma.h:145
uint64_t Handler
Definition: hal_types.h:19
__IO uint32_t NDTR
Definition: dma.h:52
void revo_call_handler(Handler h, uint32_t arg)
Definition: Scheduler.cpp:1420
DMA stream type.
Definition: dma.h:50
void DMA2_Stream5_IRQHandler(void)
Definition: dma.c:391
void dma_enable(dma_stream stream)
Definition: dma.c:213
__IO uint32_t M0AR
Definition: dma.h:54
void DMA2_Stream3_IRQHandler(void)
Definition: dma.c:383
Definition: dma.h:200
void DMA1_Stream2_IRQHandler(void)
Definition: dma.c:347