cancel
Showing results for 
Search instead for 
Did you mean: 

Is an unaligned 32 bit read/write with FMC to 16 bit SDRAM possible?

guenniause
Associate II

We want to use external 16 bit SDRAM for heap and stack. The SDRAM is configured with byte enable and MPU. I tried to map the memory to 0xC0000000 and 0x60000000, but it doesn't matter. Also the configuration of MPU with MPU_TEX_LEVEL0 or MPU_TEX_LEVEL1 doesn't matter.

An unaligned read/write with 16 bit is possible. So I think a unaligned read/write with 32 bit should possible too, if the compiler handles the access in the right way.

We use GCC 9.3 and it doesn't work.

Here is a code example, which demonstrates the incorrect reuslts.

int i;

uint8_t* pbyte;

uint16_t* pword;

uint32_t* pdword;

uint32_t address;

volatile uint32_t test;    address = 0xC0000000;

    pbyte = (uint8_t*)address;

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

    {

       pbyte[i] = i + 1;

    }

    test = pbyte[0];  // => test = 0x1

    test = pbyte[1];  // => test = 0x2

    test = pbyte[2];  // => test = 0x3

    test = pbyte[3];  // => test = 0x4

    pword = (uint16_t*)((int)address);

    test = *pword;   // => test = 0x0201

    pword = (uint16_t*)((int)address + 1);

    test = *pword;   // => test = 0x0302

    pdword = (uint32_t*)((int)address);

    test = *pdword;   // => test = 0x04030201

    pdword = (uint32_t*)((int)address + 1);

    test = *pdword;   // => test = 0x05040302

    pdword = (uint32_t*)((int)address + 2);

    test = *pdword;   // => test = 0x06050605 instead of 0x06050403

    pdword = (uint32_t*)((int)address + 3);

    test = *pdword;   // => test = 0x07060506 instead of 0x07060504

Is there someone who had the similar problem and has solved it?

12 REPLIES 12
guenniause
Associate II

The MCU is a STM32H730.

0693W00000aJh9IQAS.pngThat you were able to perform some unaligned accesses, may be coincidental.

JW

Pavel A.
Evangelist III

Perhaps when cached and defined appropriately via MPU. A whole cacheline (32 bytes) loads at aligned address, then unaligned data will be retrieved from the cache ?

guenniause
Associate II

I've enabled dcache and configurated it for SDRAM in the MPU:

..

SCB_EnableDCache();

...

 MPU_InitStruct.Enable = MPU_REGION_ENABLE;

 MPU_InitStruct.BaseAddress = 0xC0000000;

 MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;

 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;

 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

 MPU_InitStruct.Number = MPU_REGION_NUMBER2;

 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;

 MPU_InitStruct.SubRegionDisable = 0x00;

 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

But it still doesn't work.

guenniause
Associate II

I found the option -mno-unaligned-access.

This option should tell the compiler, to convert unaligned 16-bit/32-bit access to two/four 8-bit accesses.

But in our project the assembler code doesn't change with the option, and the unaligned accesses still not works.

Has someone used this option with STM32 and it works?

Douglas MILLER
ST Employee

This forum thread was marked by the moderator as needing a little more investigation, so a Support case was created in your name and will be handled off-line. Should anyone have any similar questions and would like to send a private example to ST, please submit a case to the On-Line Support team at https://my.st.com/ols

Hi @Douglas MILLER​ 

> will be handled off-line

Why? What's so secretive on this case? Couldn't we all learn from it being discussed here, publicly?

JW

@guenniause,

-mno-unaligned-access may be buggy, or dependent on some particular setting or circumstances... I've just tried your snippet (modified to add more volatile, to prevent compiler to guess the result and remove portions of code)​ with gcc v9.2.1 and cortex-m4, and it indeed did split the unaligned halfword access to two byte accesses, but left the unaligned word accesses.

OTOH, detecting indirect unaligned accesses (i.e. via calculated pointer) is not entirely trivial. You may be better off by writing your program so that it explicitly won't attempt unaligned accesses. I understand that this may be not trivial. You may also consider some other target mcu, one which does not have this limitation.

JW

guenniause
Associate II

Unaligned access to 16-Bit SDRAM via FMC is possible in our project with the following settings:

SDCache enabled

MPU enabled

MPU Settings

  MPU_InitStruct.Enable = MPU_REGION_ENABLE;

  MPU_InitStruct.SubRegionDisable = 0x0;

  MPU_InitStruct.Number = MPU_REGION_NUMBER4;

  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

  MPU_InitStruct.BaseAddress = 0xc0000000;

  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

  MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;

  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;

  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;

  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;