cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f100 SPI RX DMA, TX no dma, possible?

CanisSomnolentus
Associate III
Posted on November 15, 2017 at 17:13

Hey.

I have a board with the smallest STM32F100, with 4K RAM and 16K flash.

It has only DMA1. I am using CH3 for circular DAC output already. So, for the only SPI(1) on that MCU, the DMA map in the refman tells me, only DMA1 Ch2, for SPI1 RX, is free, for TX it collides with DAC. This *could* be okay, depending on what I want to do generally works.

I am using the standard periph lib.

I am using a tiny FAT implementation to read from SDcard via SPI, reading directly into the currently 'inactive' half of the DMA doublebuffer (no processing necessary, just straightforward playing). (elm chan PetitFAT, I changed the mmc example to use HW SPI instead bit bang) So far configured as software, i.e. byte per byte, SPI, it sorta works, but is way too slow. SPI is confgured @ div2, i.e. 12 MHz on this MCU, I get valid data, so in general the sdcard seems to be fine with the speed, so it should be able to be sped up by using DMA.

Now the question: Can I configure things such that I can use SPI TX in software, bytewise mode, whereas RX is done via DMA?

I have seen that, in theory, everything can be configured in a separate way.

My attempt at doing that failed so far: Initializing SPI, then DMA channel and DMA, then giving SPI I2S DMA command for RX, I the wait for the channel2 TransferComplete flag - forever... it never comes.

Here some code: (at 'wait until data is received', Line 47, never finishes)

SPI is configured as SPI_Direction_2Lines_FullDuplex - but I also tried to change that shortly to '2Lines RX only' before doing RX, didn't help.

void init()
{
// ...
// ... SPI / GPIO init as before - works without DMA
// ...
// DMA Init
DMA_DeInit( MMC_DMA_CHANNEL );
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) 0; // later... 
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 0; // later... 
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & MMC_SPI->DR;
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_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init( MMC_DMA_CHANNEL, &DMA_InitStructure );
DMA_Cmd( MMC_DMA_CHANNEL, ENABLE );
}

static voiddma_spi_do_one_rx_transfer(uint8_t* buf, uint32_t len)
{
//
// Update the buffer settings
//
DMA_Cmd( MMC_DMA_CHANNEL, DISABLE );
//
MMC_DMA_CHANNEL->CMAR = (uint32_t) buf;
MMC_DMA_CHANNEL->CNDTR = len;
//
DMA_Cmd( MMC_DMA_CHANNEL, ENABLE );
DMA_ClearFlag( MMC_DMA_CHANNEL_FLAG_TC ); // TC2, for SPI1 RX
 SPI_I2S_DMACmd( MMC_SPI , SPI_I2S_DMAReq_Rx, ENABLE );
// Wait until the data is received
while ( ! (MMC_DMA->ISR & MMC_DMA_CHANNEL_FLAG_TC ) );
SPI_I2S_DMACmd( MMC_SPI , SPI_I2S_DMAReq_Rx, DISABLE );
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

#dma-spi-rx-receive #dma #spi #stm32f1
3 REPLIES 3
Posted on November 16, 2017 at 00:35

Now the question: Can I configure things such that I can use SPI TX in software, bytewise mode, whereas RX is done via DMA?

Should be viable, but if the SPI is master, there should be some provision to transmit, otherwise there's no clock and without clock there's no reception (other option is to use the Rx-only mode, but that then provides clocks automatically until disabled, and that may not be an option in certain applications - I don't know if this applies to you).

I don't use SPL so don't understand that snippet of code.

S.Ma
Principal
Posted on November 16, 2017 at 04:58

Looks like DMA2 can cater for DAC Channel 1 or 2 (only one source) in the ref man page 151.

Use DMA1 for SPI.

I guess the tables were not created randomly.

Posted on November 16, 2017 at 18:43

KIC8462852 EPIC204278916 wrote:

Looks like DMA2 can cater [...]

I guess the tables were not created randomly.

No, presumably not. Just like my first statement in the second line of my first post, about my F100 only having DMA1, wasn't made randomly . I was being totally serious.

To Jan: When I have time again I'll probably translate the SPL gibberish to CMSIS 😉