STM32F207: SPI Kommunikation mit DMA

Gast #2703673
Lesenswert?

Hallo, für den Datenaustausch zwischen STM32F207 Mikrocontroller und 
einem FPGA benutzte ich die SPI Schnittstelle. Das Senden und Empfangen 
mittels Interrptroutinen funktioniert. Ich kann 16 Bit senden und 
empfange auch 16 Bit. Wenn ich nun eine Anfrage vom STM32 an den FPGA 
via SPI versende soll der FPGA mehrere 16 Bit Datenwerte an den STM32 
senden. Dazu bräuchte ich noch den DMA, der die ankommenden Daten in 
einen Puffer im DMA ablegen soll. Bei der Implementierung des DMA 
zusammen mit der SPI Schnittstelle auf dem STM32 habe ich Probleme. Wie 
könnte die Initialisierung des STM32 dazu aussehen ? Für das Empfangen 
soll ein Interrupthandler verwendet werden.
#2703681
Lesenswert?

Hier einmal einige Ausschnitte von meinem SPI Treiber: vielleicht hilft 
er dir ja weiter:

Init:
1
      // recieve
2
   DMA_DeInit(DMA1_Channel2);
3
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x4001300C;
4
   DMA_InitStructure.DMA_MemoryBaseAddr = NULL;
5
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
6
   DMA_InitStructure.DMA_BufferSize = 0;
7
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
8
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
9
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
10
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
11
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
12
   DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
13
   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
14
   DMA_Init(DMA1_Channel2, &DMA_InitStructure);
15

16
   // Enable the SPI DMA RX Interrupt
17
   NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
18
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
19
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
20
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
21
   NVIC_Init(&NVIC_InitStructure); 
22

23
   // initialize SPI 
24
   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
25
   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
26
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
27
   SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
28
   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
29
   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
30
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
31
   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
32
   SPI_InitStructure.SPI_CRCPolynomial = 7;
33
   SPI_Init(SPI1, &SPI_InitStructure);
34

35
   // Enable SPI DMA requests 
36
   SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);  
37
   SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);  
38
   
39
   // Enable SPI
40
   SPI_Cmd(SPI1, ENABLE);

recieve function
1
bool spiReadBytes(enum spiDevices target, uint8_t dataIn[], uint16_t countIn) {
2
   
3
   if (spiBusy == TRUE) {
4
      return FALSE;
5
   }
6
  
7
   // mark bus as busy 
8
   spiBusy = TRUE;
9

10
   if (selectSpiDevice(target) == FALSE) {
11
      return FALSE;
12
   }
13
   
14
   //increment only the destination buffer, 
15
   DMA1_Channel2->CCR |=  DMA_MemoryInc_Enable;
16
   DMA1_Channel3->CCR &= ~DMA_MemoryInc_Enable;
17
   
18
   // we will transmit only 0x00   
19
   spiDevNull = 0x00;
20
   
21
   //set DMA source address
22
   DMA1_Channel3->CMAR = (uint32_t) &spiDevNull;        
23
   DMA1_Channel2->CMAR = (uint32_t) dataIn;   
24
   
25
   // in duplex we will also recieve the same number of data
26
   DMA1_Channel2->CNDTR = countIn;
27
   DMA1_Channel3->CNDTR = countIn;
28

29
   //activated SPI DMA TC and Error IRQ   
30
   DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
31
   DMA_ITConfig(DMA1_Channel2, DMA_IT_TE, ENABLE);
32
   DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE);   
33
   
34
   // Enable DMA1 Chanel2 and Channel3
35
   DMA_Cmd(DMA1_Channel2, ENABLE);
36
   DMA_Cmd(DMA1_Channel3, ENABLE);
37
        
38
   return TRUE;
39
}

und ein wenig IRQ
1
   // check if the transmission is complete 
2
   if (DMA_GetITStatus(DMA1_IT_TC2) != RESET) {
3
     
4
      // clear Interrupr Flag
5
      DMA_ClearITPendingBit(DMA1_IT_TC2);
6
      
7
      //deactivated DMA TC IRQ   
8
      DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, DISABLE); 
9
   
10
      // Disable DMA1 Channel2 and Channel3
11
      DMA_Cmd(DMA1_Channel2, DISABLE);
12
      DMA_Cmd(DMA1_Channel3, DISABLE);
13
      
14
      // reset all CS Lines      
15
      GPIOA->BSRR = GPIO_Pin_4; // EEPROM
16
      
17
      // mark bus as free
18
      spiBusy = FALSE;
19
   }
Gast #2703727
Lesenswert?

Hi Mike S.,

vielen Dank für den Code. So wie es aussieht verwendest du ebenfalls das 
Evaluationboard STM3220G-EVAL von STMicroelectronics. Ich benutzte die 
SPI2 Schnittstelle.

Folgende Namen sind bei mir nicht definiert:
--> DMA1_Channel2_IRQn;
--> DMA1_Channel2;
--> DMA_DIR_PeripheralSRC;
--> DMA_M2M_Disable;

Wleche DMA MemoryBaseAddr muss ich hier einstellen ? NULL wird nicht 
akzeptiert.
#2703818
Lesenswert?

Mein Code ist eine Mischung aus Library Funktionen und direkten Register 
zugriffen.

Die MemoryBaseAddr ist das Ort im Speicher, wo deine Daten 
hingeschrieben werden sollen.
Bei mir wird die erst später mit
1
DMA1_Channel2->CNDTR = countIn;
gesetzt.

Und wie Markus schon feststellte ist der Code nicht für STM32F2... 
geschrieben sondern noch für einen STM32F103. (Allerdings auf einem 
selbst entworfenem Board.

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