I have an STM32H743 Nucleo board, accessing an external 16-bit SRAM memory chip using the Flexible Memory Controller (FMC).
8 and 16-bit writes return the same values when reading them back. However, 32 and 64-bit writes do not.
Writing in 16-bit chunks and then reading to 32-bit or 64-bit variables works OK. It is only 32 and 64-bit variable writes that cause a problem, where the values read afterwards return 0.
According to the user's manual, the FMC should split the write operation into multiple 16-bit ones automatically. Since 8-bit and 16-bit writes work without a problem, I conclude that the problem must be on the software side.
The external SRAM is set to device memory type. I've also tried setting it to strongly-ordered, using the MPU, but the problem remains.
What am I missing?
Below is the test code I am using:
uint8_t data = (uint8_t) 0x08;
*((uint8_t *) (SRAM_BANK_ADDR)) = data;
printf("8bit-value in SRAM 0x%x\n", *((uint8_t *) (SRAM_BANK_ADDR)));
uint16_t data2 = (uint16_t) 0x0016;
*((uint16_t *) (SRAM_BANK_ADDR)) = data2;
printf("16-bit value in SRAM 0x%x\n", *((uint16_t *) (SRAM_BANK_ADDR)));
uint16_t data3 = (uint16_t) 0x0032;
*((uint16_t *) (SRAM_BANK_ADDR)) = data3;
*((uint16_t *) (SRAM_BANK_ADDR | (0x02 << 1))) = data3;
*((uint16_t *) (SRAM_BANK_ADDR | (0x04 << 1))) = data3;
*((uint16_t *) (SRAM_BANK_ADDR | (0x06 << 1))) = data3;
printf("Value in SRAM as 32bit 0x%08lx\n", *((uint32_t *) (SRAM_BANK_ADDR)));
printf("Value in SRAM as 64bit 0x%016llx\n", *((uint64_t *) (SRAM_BANK_ADDR)));
uint32_t data4= (uint32_t) 0x3232;
*((uint32_t *) (SRAM_BANK_ADDR)) = data4;
HAL_Delay(1000); // Just to check whether it is a timing problem (?)
printf("Value in SRAM as 32bit 0x%08lx\n", *((uint32_t *) (SRAM_BANK_ADDR)));
printf("Value in SRAM as 64bit 0x%016llx\n", *((uint64_t *) (SRAM_BANK_ADDR)));
And the corresponding output:
8bit-value in SRAM 0x8
16-bit value in SRAM 0x16
Value in SRAM as 32bit 0x00320032
Value in SRAM as 64bit 0x0032003200320032
Value in SRAM as 32bit 0x00000000
Value in SRAM as 64bit 0x0000000000000000
For reference, this is the FMC configuration generated by the STM32CubeIDE:
/* FMC initialization function */
static void MX_FMC_Init(void)
{
/* USER CODE BEGIN FMC_Init 0 */
/* USER CODE END FMC_Init 0 */
FMC_NORSRAM_TimingTypeDef Timing = {0};
/* USER CODE BEGIN FMC_Init 1 */
/* USER CODE END FMC_Init 1 */
/** Perform the SRAM1 memory initialization sequence
*/
hsram1.Instance = FMC_NORSRAM_DEVICE;
hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
/* hsram1.Init */
hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
hsram1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;
hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
/* Timing */
Timing.AddressSetupTime = 10;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 11;
Timing.BusTurnAroundDuration = 10;
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FMC_ACCESS_MODE_A;
/* ExtTiming */
if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
{
Error_Handler( );
}
HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);
/* USER CODE BEGIN FMC_Init 2 */
/* USER CODE END FMC_Init 2 */
}
==EDIT:
It seems there might actually be a problem with the hardware.
See the following example below:
while(1){
*(uint16_t *) SRAM_BANK_ADDR = 68U;
printf("Content of address: %d\n", *(uint16_t *) SRAM_BANK_ADDR);
//Outputs (in each iteration): 68, 68, 68, 68
}
while(1){
*(uint16_t *) SRAM_BANK_ADDR = 68U;
HAL_Delay(1000);
printf("Content of address: %d\n", *(uint16_t *) SRAM_BANK_ADDR);
//Outputs (in each iteration): 4, 4, 516, 516, 516, 516, 516, ...
}
I'm guessing the chip is damaged, I will try with a new one.
===EDIT NR2:
A second chip shows the same behaviour, I will try a dedicated power supply, instead of powering the board through the debugger port.