2024-01-08 04:47 AM
I am trying to setup my STM32H725 to use serial RAM in memory mapped mode. The memory I am using is:
IS66WVS4M8ALL RAM Datasheet
I have used IOC to setup the OCTOSPI1 as a QSPI peripheral and mapped CS IO0/1/2/3 CLK from the uC to the RAM.
I have tried to firstly set the RAM for 4 pin access, then setup the cfg for read and write, finally enable the memory mapped mode. Though it does not work, in debug mode it typically crashes at some point.
I have modified the init for Octospi accordingly:
static void MX_OCTOSPI1_Init(void)
{
/* USER CODE BEGIN OCTOSPI1_Init 0 */
/* USER CODE END OCTOSPI1_Init 0 */
OSPIM_CfgTypeDef sOspiManagerCfg = {0};
/* USER CODE BEGIN OCTOSPI1_Init 1 */
/* USER CODE END OCTOSPI1_Init 1 */
/* OCTOSPI1 parameter configuration*/
hospi1.Instance = OCTOSPI1;
hospi1.Init.FifoThreshold = 1;
hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
hospi1.Init.DeviceSize = 25;
hospi1.Init.ChipSelectHighTime = 5;
hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
hospi1.Init.ClockPrescaler = 2;
hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
hospi1.Init.ChipSelectBoundary = 0;
hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
hospi1.Init.MaxTran = 0;
hospi1.Init.Refresh = 241;
if (HAL_OSPI_Init(&hospi1) != HAL_OK)
{
Error_Handler();
}
sOspiManagerCfg.ClkPort = 1;
sOspiManagerCfg.NCSPort = 1;
sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN OCTOSPI1_Init 2 */
OSPI_RegularCmdTypeDef sCommand;
OSPI_MemoryMappedTypeDef sMemMappedCfg;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_ENABLE;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = HAL_OSPI_DATA_1_LINE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_ENABLE;
sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
sCommand.Address = 0;
sCommand.NbData = 1;
sCommand.DummyCycles = 0;
/* Command SPI to be in QSPI Mode */
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.Instruction = 0x35; //set to quad mode
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) !=
HAL_OK)
{
Error_Handler();
}
uint8_t dummyData[] = {0,0,0,0};
if (HAL_OSPI_Transmit(&hospi1, dummyData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) !=
HAL_OK)
{
Error_Handler();
}
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
/* Configure write operations */
sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
sCommand.Instruction = 0x38;
sCommand.DummyCycles = 0;
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) !=
HAL_OK)
{
Error_Handler();
}
/* Configure read operations */
sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
sCommand.Instruction = 0xEB; //QCmd, QIO, upto 104MHz
sCommand.DummyCycles = 6;
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) !=
HAL_OK)
{
Error_Handler();
}
sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;
/*Enable memory mapped mode*/
if (HAL_OSPI_MemoryMapped(&hospi1, &sMemMappedCfg) != HAL_OK)
{
Error_Handler();
}
volatile uint32_t *externalFlash = 0x90000000;
uint32_t val1 = externalFlash[0];
HAL_Delay(1);
uint32_t val2 = externalFlash[1];
HAL_Delay(1);
externalFlash[0] = 10;
HAL_Delay(1);
externalFlash[1] = 10;
HAL_Delay(1);
val1 = externalFlash[0];
HAL_Delay(1);
val2 = externalFlash[1];
HAL_Delay(1);
/* USER CODE END OCTOSPI1_Init 2 */
}
2024-01-08 04:51 AM
Utilize the debugging features of your development environment. Check if there are any specific error codes returned by the HAL functions. Also, monitor the SPI signals using an oscilloscope if possible to ensure that the signals are as expected
2024-01-08 04:54 AM
Sure - so I was able to do that for the config sections and that helped a lot. Now I am stepping line by line towards the end. The write commands run (I will have a scope to test it) but the read commands hang the device. I do not know how I could debug these lines of code? I just get "Target is not responding, retrying..."?
2024-01-08 05:28 AM
Hello @sternpost_0122
You need to configure your target in Single SPI mode then to enter QuadMode, you need to set AddressMode, DataMode to None
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-01-08 05:33 AM
Thanks - I did try that but I wasn't sure how to send that command. So if I set the DataMode/AddreMode to none it will use HAL_OSPI_Command to send the command as well?
2024-01-08 06:51 AM
Found a few topics:
STM32H723 - Problem with Serial RAM in memory mapp... - Page 2 - STMicroelectronics Community
stm32h7 - STM32H723 - Problem with Serial RAM in memory mapped mode - Stack Overflow
Seems that it just doesn't work.... I copied most of the code from the second link and based on the advice that uint_64 works I just cast(is that the term) my byte array as a uint64_t.
Not the prettiest solution but I am getting sumerr = 0 always now.
//Write in byte format
for(uint32_t i = 0; i < 8000; i++){
NMB[i] = i;
}
uint64_t *internal_buffer =(uint64_t *) NMB;
uint64_t *external_flash = (uint64_t *) 0x90000000;
//Pretend it is a uint64_t
for(uint32_t i = 0; i < 1000; i++){
external_flash[i] = internal_buffer[i];
}
//Clear local copy
for(uint32_t i = 0; i < 8000; i++){
NozzleMaskBuffer[i] = 0;
}
uint32_t sumerr = 0;
//Get new version (assuming its uint64_t)
for(uint32_t i = 0; i < 1000; i++){
internal_buffer[i] = external_flash[i];
}
//Compare
for(uint32_t i = 0; i < 8000; i++){
if(NMB[i] != (i%256)){
sumerr++;}
}
HAL_Delay(10);
2024-01-08 07:47 AM
With Memory Mapped it is just stuffing templates filled with the address of the interaction.
To debug the operations it will be easier to use the direct commands, and validate expectations there. That way you're less likely to stall the processor, and lose debug access.
Also I'd strongly recommend clearing complex structures used as auto/local variables, so random stack junk is not applied to the peripheral registers.