mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32 DMA und externes RAM


Autor: Star Keeper (starkeeper)
Datum:

Bewertung
0 lesenswert
nicht 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:
// Clocks usw. einrichten
// ..
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC | RCC_AHBPeriph_DMA1, ENABLE);

// GPIOs einrichten
// ..

// SPI einrichten
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);

// DMA für das Senden Einrichten
DMA_InitTypeDef    DMA_InitStructure;
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)0x00; // <- wird später gesetzt
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 0x00; // <- wird später gesetzt
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC | DMA_IT_TE, ENABLE);

// DMA1 Interrupt einschalten
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


// Später im Programmablauf wird dann der DMA Vorgang getstartet
DMA1_Channel3->CMAR = (u32)pu8SpiBuffer;
DMA1_Channel3->CNDTR = (u16)u32Len;
DMA_Cmd(DMA1_Channel3, ENABLE);
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

// Unmittelbar nach dem einschalten von DMA und dem SPI-Interrupt kommt die Bus Fault Exception

Autor: Star Keeper (starkeeper)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Vollständikeit halber hier die Auflösung des Rätsels. Ich hab im 
Errata zum STM32F103, folgendes gefunden:
2.13 Multimaster access on the FSMC memory map
Description
When multimaster accesses are performed on the FSMC memory map (address space from
0x6000 0000 to 0xA000 0FFF), an error could be generated, leading to either a bus fault or
a DMA transfer error.
A multimaster can be:
● DMA1 and DMA2
● DMA1 and CPU
● DMA2 and CPU
Workaround
If multimaster accesses are required on the FSMC address space, the software must
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!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.