cancel
Showing results for 
Search instead for 
Did you mean: 

DMA confusion / external memory access

dirk1
Associate II
Posted on January 21, 2010 at 04:47

DMA confusion / external memory access

8 REPLIES 8
dirk1
Associate II
Posted on May 17, 2011 at 13:38

Hi,

I experience problems with the DMA and SPI. I want to send data from a buffer stored in external memory to SPI1. The external memory ist 16Bit wide and the SPI1 is configured to send 8Bits. I set up the DMA1-Channel3 for transmitting the data with 8bit width from the ext mem to the spi. Every time I enable the DMA to start transmission, the mcu catches a bus fault exception.

What is wrong? I red on some forums that the DMA is not able to transfer data from external memory, is that true?! It would make the DMA useless for most cases.

In the datasheet, under DMA features, is written:

- Access to Flash, SRAM, peripheral SRAM, APB1, APB2 and AHB peripherals as

source and destination

The external memory is connected to the FSMC, and the FSMC is a peripheral of the AHB. So I would say the DMA must be able to access external memorys. How can I find the fault, when experiencing a bus fault exception?

chikos33
Associate II
Posted on May 17, 2011 at 13:38

Dear dirk1,

The DMA does absolutely work with FSMC interface. All you have to do is to consider it as Memory (just like the internal SRAM).

I personnaly think that your problem is related to data format issue: you use 8 bit from SPI side and 16 bit from memory side but the DMA can't deal with different data formats. You will have to choose either to configure the SPI in 16 bit format, or to configure the FSMC with 8 bit mode (I don't know if it is actually possible for your case).

Also make sure your start address is aligned respectfully to the data format (in case of 16 bit: even addresses). That may sometimes cause problems.

Verify that you configured the DMA as following:

Memory base address = buffer address in the FSMC

Peripheral base address = SPI DR address

Peripheral increment = Disabled

Memory increment = Enabled ....

Finally, make sure that your FSMC configuration is correct (this IP is a little complicated to configure!).

I hope that helps a little :p

Cheers.

dirk1
Associate II
Posted on May 17, 2011 at 13:38

Thanks for your reply!

Good to hear that the DMA should be able to transfer from external memory.

I also thought that the mixing of 8Bit and 16Bit could be the problem. To eliminate this as a potential failure source, I set all involved participants to 16Bit. But the Bus Fault Exception still occurs.

I am sure that the FSMC and the SPI is working, because I debug in the external memory and the SPI worked well without DMA.

chikos33
Associate II
Posted on May 17, 2011 at 13:38

Could you try to perform memory to memory transfer to verify FSMC is OK (transfer from a buffer in internal SRAM to the same buffer that you use in external memory)?

Could you also send the piece of code where you configure the DMA ?

dirk1
Associate II
Posted on May 17, 2011 at 13:38

The initialization is done in two steps. First the SPI and DMA is configured, later when the data shall be transferred the source and size is set and a transfer is initiated.

Here the code fragments:

Code:

// Setup clocks

// ..

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC | RCC_AHBPeriph_DMA1, ENABLE);

// GPIOs

// ..

// Configure SPI

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; // <- is set later

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 0x00; // <- is set later

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);

// Enable DMA1 Int

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);

// ....

// Later in the program the DMA init is finished and the transfer started

DMA1_Channel3->CMAR = (u32)pu8SpiBuffer; // Points to external memory

DMA1_Channel3->CNDTR = (u16)u32Len; // Normally 32 Bytes

DMA_Cmd(DMA1_Channel3, ENABLE);

SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

Right after enableing the SPI Interrupt the bus fault occurs

dirk1
Associate II
Posted on May 17, 2011 at 13:38

Ok now I tried to transfer a buffer from external to internal SRAM and that does not work. Then I tried a transfer from internal to internal SRAM and that works fine. Transfer from external to external SRAM does not work.

It seems that the access of the external SRAM by the DMA causes the bus fault exception, but why?

tomas23
Associate II
Posted on May 17, 2011 at 13:38

Look up point 2.12 in Errata - FSMC multimaster access. Only one master can access FSMC at any given time.

dirk1
Associate II
Posted on May 17, 2011 at 13:38

Yeah thanks, I found that out yesterday evening too. That was the point where I resignated and decided to use NXP next time!

The Bug seems to be found in 2008 and is still in the newest revisions of the chip! I do not think that they will ever fix this within a reasonable time. So the DMA of this device is just useless for bigger designs with external components. The workaround is risible, who wants to use a DMA and then stop the cpu from working because it not allowed to access the same resources like the DMA!?