Skip to main content
rickard2
Associate III
October 23, 2017
Question

SRAM and DMA in STM32F7

  • October 23, 2017
  • 4 replies
  • 3107 views
Posted on October 23, 2017 at 14:00

I am working on a project where I have a STM32F7 which shall read data from an external SRAM using DMA.

The SRAM has 16 bit adressbus and 8 bit databus. I want the data to be copied to a 16bit buffer in the STM32F7 with DMA. However I only get the 8 bit data in the 16 bitbuffer, highest 8 bits are always 0.

The code looks like:

void PF_Init_DMA()

{

s_bTransferComplete = 0;

s_bTransferError = 0;

__HAL_RCC_DMA2_CLK_ENABLE();

s_hDMA.Init.Channel = DMA_CHANNEL_0; //DMA_CHANNEL_0

s_hDMA.Init.Direction = DMA_MEMORY_TO_MEMORY; //M2M transfer mode

s_hDMA.Init.PeriphInc = DMA_PINC_ENABLE; //Peripheral increment mode Enable

s_hDMA.Init.MemInc = DMA_MINC_ENABLE; //Memory increment mode Enable

s_hDMA.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //Peripheral data alignment : Word

s_hDMA.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD; //memory data alignment : Word

s_hDMA.Init.Mode = DMA_NORMAL; //Normal DMA mode

s_hDMA.Init.Priority = DMA_PRIORITY_HIGH; //priority level : high

s_hDMA.Init.FIFOMode = DMA_FIFOMODE_DISABLE; //FIFO mode disabled

s_hDMA.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

s_hDMA.Init.MemBurst = DMA_MBURST_SINGLE; //Memory burst

s_hDMA.Init.PeriphBurst = DMA_PBURST_SINGLE; //Peripheral burst

s_hDMA.Instance = DMA2_Stream0;

if(HAL_DMA_Init(&s_hDMA) != HAL_OK)

{

}

HAL_DMA_RegisterCallback(&s_hDMA, HAL_DMA_XFER_CPLT_CB_ID, TransferComplete);

HAL_DMA_RegisterCallback(&s_hDMA, HAL_DMA_XFER_ERROR_CB_ID, TransferError);

HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 1);

HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

}

uint8 PF_Init_SRAM()

{

// Init SRAM

/* SRAM device configuration */

__HAL_RCC_FMC_FORCE_RESET();

__HAL_RCC_FMC_RELEASE_RESET();

HAL_SRAM_DeInit(&sramHandle);

sramHandle.Instance = FMC_NORSRAM_DEVICE;

sramHandle.Extended = FMC_NORSRAM_EXTENDED_DEVICE;

/* Timing configuration derived from system clock (up to 216Mhz)

for 72 Mhz as SRAM clock frequency */

Timing.AddressSetupTime = 2;

Timing.AddressHoldTime = 1;

Timing.DataSetupTime = 2;

Timing.BusTurnAroundDuration = 1;

Timing.CLKDivision = 3;

Timing.DataLatency = 2;

Timing.AccessMode = FMC_ACCESS_MODE_A;

sramHandle.Init.NSBank = FMC_NORSRAM_BANK1;

sramHandle.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;

sramHandle.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;

sramHandle.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;

sramHandle.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;

sramHandle.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;

sramHandle.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;

sramHandle.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;

sramHandle.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;

sramHandle.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;

sramHandle.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_ENABLE;

sramHandle.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;

sramHandle.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC;

sramHandle.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;

sramHandle.hdma = PF_DMA_GetHandler();

/* Initialize the SRAM controller */

if(HAL_SRAM_Init(&sramHandle, &Timing, &Timing) != HAL_OK)

{

/* Initialization Error */

printf('SRAM Error\r\n');

SRAMInit = FALSE;

return PF_ERROR;

}

__HAL_RCC_FMC_CLK_ENABLE();

}

void PF_SRAM_Read(uint32_t *pAddress, uint16_t *pDstBuffer, uint32_t BufferSize)

{

HAL_SRAM_Read_DMA(&sramHandle, pAddress, pDstBuffer, BufferSize);

}

I use bank1 and reads data from adress:

#define EMI_START_ADDRESS ((uint32_t)0x60000000)

According to FMC in RM0410 it should be possible to use 8 bit SRAM datawith to 16 bit RAM but either way I try it doesn't work.

Please help me understand what is wrong here.

    This topic has been closed for replies.

    4 replies

    waclawek.jan
    Super User
    October 23, 2017
    Posted on October 23, 2017 at 14:29

    Direct mode is not allowed when memory-to-memory is used.

    While the HW appears to enable FIFO implicitly in that case, I'd try to set it explicitly, together with setting the peripheral size to halfword.

    I'd also try to read the halfwords from the external memory by the processor first.

    JW

    rickard2
    rickard2Author
    Associate III
    October 23, 2017
    Posted on October 23, 2017 at 14:58

    So it need to be burst mode? And it should be memory to memory, not peripeheral to memory?

    I changed accrdoing to your comments:

    s_hDMA.Init.Channel = DMA_CHANNEL_0; //DMA_CHANNEL_0

    s_hDMA.Init.Direction = DMA_MEMORY_TO_MEMORY; //M2M transfer mode

    s_hDMA.Init.PeriphInc = DMA_PINC_ENABLE; //Peripheral increment mode Enable

    s_hDMA.Init.MemInc = DMA_MINC_ENABLE; //Memory increment mode Enable

    s_hDMA.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //Peripheral data alignment : Word

    s_hDMA.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD; //memory data alignment : Word

    s_hDMA.Init.Mode = DMA_NORMAL; //Normal DMA mode

    s_hDMA.Init.Priority = DMA_PRIORITY_HIGH; //priority level : high

    s_hDMA.Init.FIFOMode = DMA_FIFOMODE_DISABLE; //FIFO mode disabled

    s_hDMA.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

    s_hDMA.Init.MemBurst = DMA_MBURST_INC16; //Memory burst

    s_hDMA.Init.PeriphBurst = DMA_PBURST_INC16; //Peripheral burst

    sramHandle.Init.NSBank = FMC_NORSRAM_BANK1;

    sramHandle.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;

    sramHandle.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;

    sramHandle.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;

    sramHandle.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE;

    sramHandle.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;

    sramHandle.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;

    sramHandle.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;

    sramHandle.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;

    sramHandle.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;

    sramHandle.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_ENABLE;

    sramHandle.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;

    sramHandle.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC;

    sramHandle.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;

    When I run it I get the following (Data in SRAM is 0xAAAA at all adresses).

    Reading witout DMA (using HAL_SRAM_Read_16b(&sramHandle, 0, SRAMData1, 20);):

    Reading SRAM:

    [0]: AAAA

    [1]: 0

    [2]: FFFF

    [3]: FFF

    [4]: 20

    [5]: 0

    [6]: 922A

    [7]: B73A

    [8]: 7EF7

    [9]: DED7

    [10]: 3F69

    [11]: 68FF

    [12]: A3FE

    [13]: 177A

    [14]: 3034

    [15]: FA6D

    [16]: 2BF3

    [17]: BCA

    [18]: 12CD

    [19]: 6D5F

    With DMA:

    RAM fail, read AA at 0 expected AAAA...

    RAM fail, read AA at 1 expected AAAA...

    RAM fail, read AA at 2 expected AAAA...

    RAM fail, read AA at 3 expected AAAA...

    RAM fail, read AA at 4 expected AAAA...

    RAM fail, read AA at 5 expected AAAA...

    RAM fail, read AA at 6 expected AAAA...

    RAM fail, read AA at 7 expected AAAA...

    RAM fail, read AA at 8 expected AAAA...

    RAM fail, read AA at 9 expected AAAA...

    RAM fail, read AA at A expected AAAA...

    RAM fail, read AA at B expected AAAA...

    RAM fail, read AA at C expected AAAA...

    For me it doesn't make sense

    waclawek.jan
    Super User
    October 23, 2017
    Posted on October 23, 2017 at 15:06

    So it need to be burst mode?

    No, bursts are not necessary.

    I said, enable FIFO.

    And it should be memory to memory, not peripeheral to memory?

    It *was* mem-to-mem in your first post.

    I don't Cube. I also don't understand the data you present us here, how did you obtain them. Do you read from various external memory addresses?

    For the DMA case, show us the content of the target (internal) memory.

    JW

    Tesla DeLorean
    Guru
    October 23, 2017
    Posted on October 23, 2017 at 16:49

    Have you throughly validated the memory function in normal, non-cached, usage?

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    rickard2
    rickard2Author
    Associate III
    October 23, 2017
    Posted on October 23, 2017 at 17:00

    Yeah, running without DMA gives the same result.

    waclawek.jan
    Super User
    October 23, 2017
    Posted on October 23, 2017 at 19:19

    Note, that Clive said 'non-cached', not 'non-DMA'.

    And manual bit-banging all the address/control signals, and reading the data lines?

    And what says the LA?

    JW

    rickard2
    rickard2Author
    Associate III
    October 24, 2017
    Posted on October 24, 2017 at 17:04

    I changed everything to just run on 8 bit values:

    __HAL_RCC_FMC_FORCE_RESET();

    __HAL_RCC_FMC_RELEASE_RESET();

    HAL_SRAM_DeInit(&sramHandle);

    sramHandle.Instance = FMC_NORSRAM_DEVICE;

    sramHandle.Extended = FMC_NORSRAM_EXTENDED_DEVICE;

    /* Timing configuration derived from system clock (up to 216Mhz)

    for 72 Mhz as SRAM clock frequency */

    Timing.AddressSetupTime = 2;

    Timing.AddressHoldTime = 1;

    Timing.DataSetupTime = 2;

    Timing.BusTurnAroundDuration = 1;

    Timing.CLKDivision = 3;

    Timing.DataLatency = 2;

    Timing.AccessMode = FMC_ACCESS_MODE_A;

    sramHandle.Init.NSBank = FMC_NORSRAM_BANK1;

    sramHandle.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;

    sramHandle.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;

    sramHandle.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;

    sramHandle.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE;

    sramHandle.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;

    sramHandle.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;

    sramHandle.Init.WriteOperation = FMC_WRITE_OPERATION_DISABLE;

    sramHandle.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;

    sramHandle.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;

    sramHandle.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_ENABLE;

    sramHandle.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;

    sramHandle.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;

    sramHandle.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;

    //sramHandle.hdma = PF_DMA_GetHandler();

    /* Initialize the SRAM controller */

    if(HAL_SRAM_Init(&sramHandle, &Timing, &Timing) != HAL_OK)

    {

    /* Initialization Error */

    printf('SRAM Error\r\n');

    SRAMInit = FALSE;

    return PF_ERROR;

    }

    __FMC_NORSRAM_ENABLE(FMC_NORSRAM_DEVICE, FMC_NORSRAM_BANK1);

    __HAL_RCC_FMC_CLK_ENABLE();

    SRAMInit = TRUE;

    And then I print directly from memory:

    #define EMI_START_ADDRESS ((uint32_t)0x60000000)

    for(i = 0; i < 10; i++)

    {

    printf('[%d] = %X\r\n', i, *(__IO uint8_t *)(EMI_START_ADDRESS + i));

    }

    And now I get every second value 0:

    [0] = AA

    [1] = 0

    [2] = AA

    [3] = 0

    [4] = AA

    [5] = 0

    [6] = AA

    [7] = 0

    [8] = AA

    [9] = 0
    waclawek.jan
    Super User
    October 24, 2017
    Posted on October 24, 2017 at 18:07

    Is there a question?

    Did you fix the address mismatch problem?

    JW

    rickard2
    rickard2Author
    Associate III
    October 25, 2017
    Posted on October 25, 2017 at 08:59

    Sorry panic mode :-).....

    I now connect LA and will check signal by signal by reading one byte at a time

    waclawek.jan
    Super User
    October 25, 2017
    Posted on October 25, 2017 at 09:57

    The setup says adress_data_mux_disable

    And what do the registers say?

    JW

    rickard2
    rickard2Author
    Associate III
    October 25, 2017
    Posted on October 25, 2017 at 10:28

    I am not really sure where to find this. Which adress should I look at?

    rickard2
    rickard2Author
    Associate III
    October 25, 2017
    Posted on October 25, 2017 at 11:11

    I get the followings reading

    [0] = 30DB

    [8] = 30D2

    [16] = 30D2

    [24] = 30D2

    when using this code

    for(i = 0; i < 0x1C; i += 8)

    {

    printf('[%d] = %X\r\n', i, *(__IO uint32_t *)(0xA0000000 + i));

    }

    So I guess this means (ref man RM0410 at page 404)

    FMC_BCR1 = 

    30DB, which menas MUX is enable

    FMC_BCR2 = 

    30D2, which menas MUX is

    enable

    FMC_BCR3= 

    30D2, which menas MUX is

    enable

    FMC_BCR3 = 

    30D2, which menas MUX is

    enable

    So I think mux is enabled on SRAM bank1?? Correcr?