STM32F4 + Timer 3 + DMA1 schreibt nicht ins ODR => TEIF

OP (Firma: Student) #3729470
Lesenswert?

Moin, Leute!

Ich möchte mit dem folgenden Code durch den Timer 3 den Speicherinhalt 
aus LED_PIN_SET[10] in das OutputDatenRegister (ODR) von GPIO Port E 
schreiben.

Einfach, schon tausend mal gelesen ... möchte man glauben...
1
#include "stm32f4xx.h"
2
#include "stm32f4xx_tim.h"
3
#include "stm32f4xx_dma.h"
4

5
// togglet Pin 5 bei jedem CC4 Event
6
uint16_t LED_PIN_SET[10] = { GPIO_Pin_5, 0x0000,
7
                             GPIO_Pin_5, 0x0000,
8
                             GPIO_Pin_5, 0x0000,
9
                             GPIO_Pin_5, 0x0000,
10
                             GPIO_Pin_5, 0x0000 };
11

12

13
void TIM3_Config()
14
{
15
  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
16

17
  DMA_InitTypeDef       DMA_InitStructure;
18

19
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
20
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
21

22
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
23
  TIM_TimeBaseStructure.TIM_Period = 42000-1; // 1Hz
24
  TIM_TimeBaseStructure.TIM_Prescaler = 1000-1; // 42 kHz
25
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
26
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
27
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
28

29
  TIM_SetCompare4(TIM3,41999);
30

31
  TIM_DMAConfig(TIM3,TIM_DMABase_SR,TIM_DMABurstLength_1Transfer);
32

33
  TIM_DMACmd(TIM3,TIM_DMA_CC4,ENABLE);
34

35
  DMA_InitStructure.DMA_Channel = DMA_Channel_5;
36
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(GPIOE->ODR);
37
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&LED_PIN_SET;
38
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
39
  DMA_InitStructure.DMA_BufferSize = 10;
40
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
41
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
42
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
43

44
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
45
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
46
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
47
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
48
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
49
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
50
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
51

52
  DMA_Init(DMA1_Stream2, &DMA_InitStructure);
53
  DMA_Cmd(DMA1_Stream2, ENABLE);
54

55
  //TIM_Cmd(TIM3, ENABLE);
56

57
}
58

59
void init_gpio( void ) {
60

61
  GPIO_InitTypeDef      GPIO_InitStructure;
62

63
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOE, ENABLE);
64

65
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
66
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
67
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
68
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
69
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
70

71
  GPIO_Init(GPIOE, &GPIO_InitStructure);
72

73
}
74

75
int main( void ) {
76

77
    uint32_t i;
78

79
    i = 0;
80

81
    SystemInit();
82

83
    RCC_ClocksTypeDef rcctdef;
84

85
    RCC_GetClocksFreq(&rcctdef);
86

87
    init_gpio();
88

89
    TIM3_Config();
90

91
    TIM_Cmd(TIM3, ENABLE);
92

93
    while(1) {
94

95
         i++;
96
    }
97

98
    // sollte nicht erreicht werden
99
    return 1;
100

101
}




ABER:

er tut einfach nicht. Sobald der Timer aktiviert wird und der erste 
Request über die Bühne geht (ob manuell ausgelöst (TIM3->EGR) oder 
automatisch) stirbt das DMA enable Flag und es erscheint ein hässliches 
Transfer Error Interrupt Flag (TEIF) an dessen Statt.

Jetzt kommt es: Nach einem Tag verzweifelten Hin- und Herschieben, 
Fremdcodewälzen versuche ich es mal mit dem Timer 1 auf DMA2Stream4.

Und tada ... alles läuft wie es soll.

Leider verstehe ich immer noch nicht, was an obiger Konfiguration so 
daneben geht? Kann mir jemand erklären, warum der Code dort oben nicht 
funktioniert?
OP (Firma: Student) #3729940
Lesenswert?

Oh ja, danke für den Tip. Was ihr hier seht, ist das Ergebnis eines 
taglangen Experimentes. Da wurden schon viele Werte ausprobiert.

Da stand vorher
1
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;

und eigentlich sollte dort auch stehen
1
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

Auch die BufferSize stand ursprünglich mal auf 2.

Sorry für die Schlampigkeit.

Im Anhang findet ihr die aufgeräumte, funktionierende Version für Timer 
1 durch DMA2.

Hat jemand eine Idee, was ich übersehen habe bzw. warum das für den 
Timer3 DMA1 nicht funktioniert?
Angehängte Dateien:
OP (Firma: Student) #3730155
Lesenswert?

So, jetzt hab ich das ganze Spielchen noch für den

(TIM1 DMA2)*läuft*
(TIM8 DMA2)*läuft*

und

(TIM2 DMA1)*zonk*
(TIM3 DMA1)*zonk*

ausprobiert.

Also darf man vermuten, dass DMA1 bzw. der APB1 die Problemkinder sind 
(abgesehen von dem Typ hinter dem Bildschirm :)?
OP (Firma: Student) #3730473
Lesenswert?

@Uwe: ja, dass Mem2Mem bei DMA1 nicht geht habe ich auch festgestellt, 
aber GPIO ... das wirft immer noch Fragen auf.

@Marcus: Die Tabellen für das Request Mapping (Tab. 43/44) kenne ich 
natürlich und musste die ja auch bei der Wahl des DMAs/Streams und 
Channels berücksichtigen. Sonst würde das Event den Request ja gar nicht 
erst auslösen.

Auf meinen Verdacht hin habe ich mir Abb. 33 angesehen konnte dort aber 
keinen Widerspruch zu meiner Implementierung feststellen bzw. dort 
verstehe ich die AHB-APB-bridges nicht so recht ...
( Anhang seht ihr die Abbildung nochmal )
links:Eingang rechts:Ausgang?

Heißt das, dass ich nur TIM1 oder TIM8 verwenden kann, um vom Speicher 
auf die GPIOs zu schreiben?
Angehängte Dateien:
OP (Firma: Student) #3730538
Lesenswert?

Danke, aber ich hab das Rauchen vor Jahren aufgegeben.

Nur zwei Timer für die DMA-gesteuerte Ausgabe so vieler Pins ... finde 
ich ein bissl spärlich. Dann sind die auch noch nur 16 Bit "groß".

Enttäuschend.

Danke für die Klärung meiner Verständnisprobleme. Ich denke dieser 
Thread ist damit geschlossen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren