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.
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 | }
|
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.
Ab STM32F2xx/4xx heißt das auch nicht mehr "DMA1_Channel..." sondern "DMA1_Stream...".
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.
Nochmals danke für eure Hilfe. Das mit der SPI/DMA Konfiguration scheint nicht so leicht zu sein. Mir würde eine Beispielapplikation für den STM32F207 weiterhelfen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.