cancel
Showing results for 
Search instead for 
Did you mean: 

Dual Port SRAM corrupted unless read after write

Zenzizen
Associate II

I have a custom board with an stm32f733zet6 and an stlink-v3mods as a programmer/debugger.

Attached is a CY7C006A-20 dual port static ram which asynchronous and I'm using it without wait. I'm running 216MHz off HSI + PLLCLK

I've set timing values of 1, 1, 3 for AddressSetup, AddressHold and DataSetup respectively and it seems to work as I'm able to write some test data and read it back and it compares the same.

I'm using this setup as a Gameboy cartridge emulator of sorts so I'm writing a specific sequence of bytes which are checked during device boot. I hold the reset line low, write the data, release the reset line, and it begins to boot. This is where things get confusing: if I just write the data, the logo is all garbled on screen. But, if I read the data back before I release the reset line, it all works. The relevant section where I write:

// HAL_Init() etc
// uint8_t data[] { ... } above
for (int i = 0; i < sizeof(data); i++) {
  (*(volatile uint8_t*)(NOR_MEMORY_ADRESS1 + i)) = data[i];
}
HAL_Delay(500);
// If I omit this loop the data is seemingly corrupt
int ii = 0;
for (int i = 0; i < sizeof(data); i++) {
  ii = *(volatile uint8_t*)(NOR_MEMORY_ADRESS1 + i);
}
HAL_GPIO_WritePin(CART_NRST_GPIO_Port, CART_NRST_Pin, GPIO_PIN_SET);
while (true) { HAL_Delay(500); }

I'm not sure what could be causing this.

5 REPLIES 5

Volatile isn't sufficient

You likely need a __DSB() type fencing instruction, and to make sure the cache and write-buffer clear the data.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

FMC?

Set it as Device using MPU, or use the swap with SDRAM bank (which again makes the static bank Device) ​if available in this 'F7.

JW​

I was under​ the impression that DSB was only necessary for inter-thread coherency?

How do I go about ensuring the write buffer​ is actually flushed?

Zenzizen
Associate II

I've added an MPU_Config but to seemingly no effect. Further suggestions would be appreciated!

static void MPU_Config(void)
{
    MPU_Region_InitTypeDef MPU_InitStruct;
 
    /* Disable the MPU */
    HAL_MPU_Disable();
 
    /* Configure the MPU attributes as WT for SRAM */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.BaseAddress = NOR_MEMORY_ADRESS1;
    MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER1;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
 
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
 
    /* Enable the MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
 
int main(void)
{
    MPU_Config();
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_DAC_Init();
    SRAM_HandleTypeDef handle_;
    MX_FMC_Init(handle_);
    MX_I2C1_Init();
    uint8_t data[] {...};
    HAL_SRAM_Write_8b(&handle_, (uint32_t*)NOR_MEMORY_ADRESS1, data, sizeof(data));
    __DSB();
    HAL_GPIO_WritePin(CART_NRST_GPIO_Port, CART_NRST_Pin, GPIO_PIN_SET);
...
}

You have disabled instruction execution on that region. Is that OK or are you executing code from that region? Also check if memory address is aligned to the block size. And you've configured that region as strongly-ordered type, which is an overkill. Actually the memory can be normal cacheable, you just have to do the clean operation on I/D-cache memories.

Read AN4838 and AN4839.