Forum: Mikrocontroller und Digitale Elektronik STM32 DMA und externes RAM


von Star K. (starkeeper)


Lesenswert?

Hi,
ich wollte mal fragen ob es schon jemand hin bekommen hat mit Hilfe des 
DMA, eines STM32, von einem externen Memory die SPI zu beladen.

Ich habe einen Puffer, der in einem externen SRAM liegt, dass mit 16Bit 
über das FSMC angebunden ist. Die Daten sollen in das Datenregister der 
SPI1 geschrieben werden. Die SPI1 ist mit 8Bit eingerichtet.

Immer wenn ich den DMA-Kanal einschalte, damit er den Transfer beginnt, 
bekomme ich eine Bus Fault Exception. Wie kann ich nun herausfinden, 
warum die Bus Fault Exception ausgelöst wird?

Hier mal ein Auszug aus meiner Initialisierung:
1
// Clocks usw. einrichten
2
// ..
3
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC | RCC_AHBPeriph_DMA1, ENABLE);
4
5
// GPIOs einrichten
6
// ..
7
8
// SPI einrichten
9
SPI_InitTypeDef SPI_InitStructure;
10
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
11
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
12
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
13
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
14
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
15
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
16
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
17
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
18
SPI_InitStructure.SPI_CRCPolynomial = 7;
19
SPI_Init(SPI1, &SPI_InitStructure);
20
SPI_Cmd(SPI1, ENABLE);
21
22
// DMA für das Senden Einrichten
23
DMA_InitTypeDef    DMA_InitStructure;
24
DMA_DeInit(DMA1_Channel3);
25
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR);
26
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)0x00; // <- wird später gesetzt
27
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
28
DMA_InitStructure.DMA_BufferSize = 0x00; // <- wird später gesetzt
29
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
30
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
31
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
32
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
33
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
34
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
35
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
36
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
37
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC | DMA_IT_TE, ENABLE);
38
39
// DMA1 Interrupt einschalten
40
NVIC_InitTypeDef NVIC_InitStructure;
41
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
42
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
43
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
44
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
45
NVIC_Init(&NVIC_InitStructure);
46
47
48
// Später im Programmablauf wird dann der DMA Vorgang getstartet
49
DMA1_Channel3->CMAR = (u32)pu8SpiBuffer;
50
DMA1_Channel3->CNDTR = (u16)u32Len;
51
DMA_Cmd(DMA1_Channel3, ENABLE);
52
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
53
54
// Unmittelbar nach dem einschalten von DMA und dem SPI-Interrupt kommt die Bus Fault Exception

von Star K. (starkeeper)


Lesenswert?

Der Vollständikeit halber hier die Auflösung des Rätsels. Ich hab im 
Errata zum STM32F103, folgendes gefunden:
1
2.13 Multimaster access on the FSMC memory map
2
Description
3
When multimaster accesses are performed on the FSMC memory map (address space from
4
0x6000 0000 to 0xA000 0FFF), an error could be generated, leading to either a bus fault or
5
a DMA transfer error.
6
A multimaster can be:
7
● DMA1 and DMA2
8
● DMA1 and CPU
9
● DMA2 and CPU
10
Workaround
11
If multimaster accesses are required on the FSMC address space, the software must
12
ensure that accesses are performed one at a time, and not at the same time.

Der Bug ist wohl schon seit 2008 bekannt und wurde noch immern nicht 
gefixt. Wenn also jemand vor hat die DMA mit einer externen Komponente 
zu nutzen: Abhaken!

Der Workaround ist auch lachhaft, wer will schon die DMA benutzen und 
dann doch die cpu aufhalten, um sicherzustellen, dass diese in der 
Zwischenzeit nicht auch auf die gleiche Komponente zugreift! Gerade wenn 
man ein externes SRAM benutzt als RAM-Erweiterung. Oder mehrere externe 
Controller zu bedienen hat! Ganz zu schweigen vom Debuggen im externen 
RAM!

von (prx) A. K. (prx)


Lesenswert?

Star Keeper schrieb:

> Der Bug ist wohl schon seit 2008 bekannt und wurde noch immern nicht
> gefixt.

Die Updatezyklen von Controllern sind eher träge, der hohen Kosten 
wegen. Wenn's nicht allzu schlimm zum Himmel stinkt, dann werden die 
Bugs oft nur dokumentiert und bleiben ungefixt.

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
Noch kein Account? Hier anmelden.