Wenn ich das Manual zum xmega32a4 bzw. die application note zu DMA
richtig interpretiere, dann sollte der DMA-Controller erst ein Interrupt
auslösen wenn eine Transaction abgeschlossen ist, im Repeat-Mode also
alle Wiederholungen durchgeführt wurden:
"When a transaction on the DMA channel has been completed, the TRNIF
flag will be set and the optional interrupt is
generated." (AVR Manual)
Trotzdem wird bei mir offenbar bei jedem Triggersignal vom ADC (oder
nach jedem Block) ein Interrupt ausgelöst, ich komm aber nicht dahinter
weshalb. Kann mir da jemand weiterhelfen?
1 | #define NSAMPLE = 12
|
2 |
|
3 | void adc_dma_init()
|
4 | {
|
5 | // Resset DMA and Enable
|
6 | DMA_CTRL = DMA_RESET_bm;
|
7 | while( (DMA_CTRL & DMA_RESET_bm) != 0);
|
8 | DMA_CTRL = DMA_ENABLE_bm | DMA_DBUFMODE_CH01_gc;
|
9 |
|
10 | adc_dma1_init();
|
11 | adc_dma0_init();
|
12 |
|
13 | ADC_DMA0.CTRLA |= (1 << 7);
|
14 |
|
15 | }
|
16 |
|
17 |
|
18 | void adc_dma0_init()
|
19 | {
|
20 | ADC_DMA0.CTRLA = (DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_REPEAT_bm);
|
21 | ADC_DMA0.CTRLB = DMA_CH_TRNINTLVL_LO_gc | DMA_CH_ERRINTLVL_LO_gc;
|
22 | ADC_DMA0.ADDRCTRL = ( DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_TRANSACTION_gc | DMA_CH_DESTDIR_INC_gc );
|
23 |
|
24 | ADC_DMA0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH2_gc;
|
25 | ADC_DMA0.TRFCNTL = 0x06;
|
26 | ADC_DMA0.TRFCNTH = 0x00;
|
27 | ADC_DMA0.REPCNT = NSAMPLE;
|
28 |
|
29 | ADC_DMA0.SRCADDR0 = 0x10; // CH0RESLOW
|
30 | ADC_DMA0.SRCADDR1 = 0x02; // ADCA
|
31 | ADC_DMA0.SRCADDR2 = 0x00;
|
32 |
|
33 | ADC_DMA0.DESTADDR0 = ((uint16_t)&dma0_buff) >> 0;
|
34 | ADC_DMA0.DESTADDR1 = ((uint16_t)&dma0_buff) >> 8;
|
35 | ADC_DMA0.DESTADDR2 = 0x00;
|
36 |
|
37 | //ADC_DMA0.CTRLA |= DMA_CH_ENABLE_bm;
|
38 | }
|
39 |
|
40 | void adc_dma1_init()
|
41 | {
|
42 | ADC_DMA1.CTRLA = (DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_REPEAT_bm);
|
43 | ADC_DMA1.CTRLB = DMA_CH_TRNINTLVL_LO_gc | DMA_CH_ERRINTLVL_LO_gc;
|
44 | ADC_DMA1.ADDRCTRL = ( DMA_CH_SRCRELOAD_BLOCK_gc |DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_TRANSACTION_gc | DMA_CH_DESTDIR_INC_gc );
|
45 |
|
46 | ADC_DMA1.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH2_gc;
|
47 | ADC_DMA1.TRFCNTL = 0x06;
|
48 | ADC_DMA1.TRFCNTH = 0x00;
|
49 | ADC_DMA1.REPCNT = NSAMPLE;
|
50 |
|
51 | ADC_DMA1.SRCADDR0 = 0x10; // CH0RESLOW
|
52 | ADC_DMA1.SRCADDR1 = 0x02; // ADCA
|
53 | ADC_DMA1.SRCADDR2 = 0x00;
|
54 |
|
55 | ADC_DMA1.DESTADDR0 = ((uint16_t)&dma1_buff) >> 0;
|
56 | ADC_DMA1.DESTADDR1 = ((uint16_t)&dma1_buff) >> 8;
|
57 | ADC_DMA1.DESTADDR2 = 0x00;
|
58 |
|
59 | //ADC_DMA1.CTRLA |= DMA_CH_ENABLE_bm;
|
60 | }
|
61 |
|
62 | ISR(DMA_CH0_vect)
|
63 | {
|
64 |
|
65 | if (DMA_INTFLAGS & DMA_CH0TRNIF_bm)
|
66 | {
|
67 | DMA.INTFLAGS = DMA_CH0TRNIF_bm;
|
68 | ADC_DMA0.REPCNT = NSAMPLE;
|
69 | ADC_DMA0.CTRLA |= DMA_CH_REPEAT_bm;
|
70 | adc_process(dma0_buff);
|
71 | }
|
72 | else // DMA Error
|
73 | {
|
74 | DMA.INTFLAGS = DMA_CH0ERRIF_bm;
|
75 | // TODO: Error handling
|
76 | }
|
77 |
|
78 | }
|
79 |
|
80 | ISR(DMA_CH1_vect)
|
81 | {
|
82 |
|
83 | if (DMA_INTFLAGS & DMA_CH1TRNIF_bm)
|
84 | {
|
85 | DMA.INTFLAGS = DMA_CH1TRNIF_bm;
|
86 | ADC_DMA1.REPCNT = NSAMPLE;
|
87 | ADC_DMA1.CTRLA |= DMA_CH_REPEAT_bm;
|
88 | adc_process(dma1_buff);
|
89 | }
|
90 | else // DMA Error
|
91 | {
|
92 | DMA.INTFLAGS = DMA_CH1ERRIF_bm;
|
93 | // TODO: Error handling
|
94 | }
|
95 |
|
96 | }
|
Hier sollte dma0 dma0_buff mit NSAMPLES von ADCA CH0-2 füllen, dann
einen interrupt generieren während dma1 übernimmt und dma1_buff füllt
usw.
Was passiert ist (soweit ich das bisher beobachten konnte), dass dma0
einen Block (nach einem Trigger des ADCs) kopiert, einen interrupt
auslöst, dann dma1 einen block kopiert und einen Interrupt auslöst usw.
Im Grund Verhält es sich so, als wäre der Repeat Mode nicht aktiv.