cancel
Showing results for 
Search instead for 
Did you mean: 

Configuring OSPI in QSPI with Memory Mapped

sternpost_0122
Associate II

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 */

 

}

 

 

6 REPLIES 6
liaifat85
Senior II

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

sternpost_0122
Associate II

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..."?

FBL
ST Employee

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 

FBelaid_0-1704720274625.png

 

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.

sternpost_0122
Associate II

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?

sternpost_0122
Associate II

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);

 

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.

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