2010-01-20 07:47 PM
DMA confusion / external memory access
2011-05-17 04:38 AM
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?2011-05-17 04:38 AM
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.2011-05-17 04:38 AM
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.2011-05-17 04:38 AM
2011-05-17 04:38 AM
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 occurs2011-05-17 04:38 AM
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?2011-05-17 04:38 AM
Look up point 2.12 in Errata - FSMC multimaster access. Only one master can access FSMC at any given time.
2011-05-17 04:38 AM
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!?