Skip to main content
Explorer
June 13, 2024
Question

Problem with interfacing with S26KL128S flash chip

  • June 13, 2024
  • 1 reply
  • 1014 views

Dear All,

I have a board that uses the STM32U599NJH6Q as MCU and the S26KL128S is attached to the OCTOSPI1 peripheral of the said MCU.

I need to be able to erase a sector and/or a page, write data to the device and then be able to read them back.

What I am unsure of at the moment is the initialization code. Specifically, I am not sure if I need to use Octo SPI mode or Hyperbus.

Currently I am going with Octo SPI and my MX_OCTOSPI1_Init looks like this:

void MX_OCTOSPI1_Init(void)
{

 /* USER CODE BEGIN OCTOSPI1_Init 0 */

 /* USER CODE END OCTOSPI1_Init 0 */

 OSPIM_CfgTypeDef sOspiManagerCfg = {0};
 HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};

 /* USER CODE BEGIN OCTOSPI1_Init 1 */

 /* USER CODE END OCTOSPI1_Init 1 */
 hospi1.Instance = OCTOSPI1;
 hospi1.Init.FifoThreshold = 4;
 hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
 hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX;
 hospi1.Init.DeviceSize = 26;
 hospi1.Init.ChipSelectHighTime = 2;
 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 = 4;
 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 = 0;
 if (HAL_OSPI_Init(&hospi1) != HAL_OK)
 {
 Error_Handler();
 }
 sOspiManagerCfg.ClkPort = 1;
 sOspiManagerCfg.DQSPort = 1;
 sOspiManagerCfg.NCSPort = 1;
 sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
 sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
 if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
 HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
 if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN OCTOSPI1_Init 2 */

 /* USER CODE END OCTOSPI1_Init 2 */

}

 In my main I am doing the following:

uint8_t ofTxBuffer[] = " **OCTOSPI Flash sample**\r\n";
int main(void)
{
 HAL_Init();
....
 MX_OCTOSPI1_Init();
...
// Configure the memory-mapped mode for S26KL128S
	 OSPI_MemoryMappedTypeDef mMemMappedCfg = {0};

	 // Set command to enter memory-mapped mode
	 OSPI_RegularCmdTypeDef mCommand = {0};
	 mCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
	 mCommand.FlashId = HAL_OSPI_FLASH_ID_1;
	 mCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
	 mCommand.Instruction = 0x00; // Enter the appropriate instruction here
	 mCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
	 mCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
	 mCommand.Address = 0x000000; // Start address of the flash memory
	 mCommand.DataMode = HAL_OSPI_DATA_1_LINE;
	 mCommand.NbData = 1;
	 mCommand.DummyCycles = 0;
	 mCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
	 mCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

	 if (HAL_OSPI_Command(&hospi1, &mCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
	 // Initialization Error
	 Error_Handler();
	 }

	 // Configure memory-mapped mode
	 mMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;

	 if (HAL_OSPI_MemoryMapped(&hospi1, &mMemMappedCfg) != HAL_OK) {
	 // Initialization Error
	 Error_Handler();
	 }
	 __IO uint8_t *mem_addr;
	 mem_addr = (__IO uint8_t *)(OCTOSPI1_BASE);
	 memcpy(mem_addr, &ofTxBuffer, sizeof(ofTxBuffer));
	 uint8_t octoFLASHData[128] = {0};
	 mem_addr = (__IO uint8_t *)(OCTOSPI1_BASE);
	 memcpy(&octoFLASHData, mem_addr, sizeof(ofTxBuffer));


	printk("String in octo flash: %s\r\n", octoFLASHData);
 while(1){}
}

Once the code hits the memcpy point I am getting a hardfault.
Furthermore it is unclear to me how to proceed with actually erasing the flash.

 

Any help would be great.

    This topic has been closed for replies.

    1 reply

    Technical Moderator
    June 13, 2024

    Hello @G_Anastasopoulos ,

     

    The HyperBus protocol must be used when an external HyperRAM or HyperFlash memory is connected to the STM32. For that, I recommend you to take a look at Table 7. STM32CubeMX - Configuration of OCTOSPI signals and mode IV. HyperFlash and HyperRAM memories with Multiplexed mode example and at in AN5050 and get inspired to configure the memory.

    Also, I think STM32CubeU5/Projects/STM32U575I-EV/Examples/OCTOSPI/OSPI_HyperRAM_MemoryMapped at main · STMicroelectronics/STM32CubeU5 · GitHub may help you.

    Thank you.

    Kaouthar

    Explorer
    June 13, 2024

    I have reviewed this example. I am not sure how to bend it to make it work with my chip, as this is meant for a HyperRAM.

    I have reviewed several different tickets in the forum as well, including this:

    https://community.st.com/t5/stm32-mcus-products/looking-for-sample-code-for-hyperflash-erase-programming-with/td-p/126856 which appears to be the closest to my situation, but I have not managed to make it work yet.

    I am not sure what is the exact problem, but based on the code that was provided on your response, I am doing these steps:
    Init:

    void MX_OCTOSPI1_Init(void)
    {
    
     /* USER CODE BEGIN OCTOSPI1_Init 0 */
    
     /* USER CODE END OCTOSPI1_Init 0 */
    
     OSPIM_CfgTypeDef sOspiManagerCfg = {0};
     OSPI_HyperbusCfgTypeDef sHyperBusCfg = {0};
     HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};
    
     /* USER CODE BEGIN OCTOSPI1_Init 1 */
    
     /* USER CODE END OCTOSPI1_Init 1 */
     hospi1.Instance = OCTOSPI1;
     hospi1.Init.FifoThreshold = 4;
     hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
     hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_HYPERBUS;
     hospi1.Init.DeviceSize = 26;
     hospi1.Init.ChipSelectHighTime = 2;
     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 = 4;
     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_USED;
     hospi1.Init.MaxTran = 0;
     hospi1.Init.Refresh = 0;
     if (HAL_OSPI_Init(&hospi1) != HAL_OK)
     {
     Error_Handler();
     }
     sOspiManagerCfg.ClkPort = 1;
     sOspiManagerCfg.DQSPort = 1;
     sOspiManagerCfg.NCSPort = 1;
     sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
     sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
     if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
     {
     Error_Handler();
     }
     sHyperBusCfg.RWRecoveryTime = 0;
     sHyperBusCfg.AccessTime = 0;
     sHyperBusCfg.WriteZeroLatency = HAL_OSPI_NO_LATENCY_ON_WRITE;
     sHyperBusCfg.LatencyMode = HAL_OSPI_VARIABLE_LATENCY;
     if (HAL_OSPI_HyperbusCfg(&hospi1, &sHyperBusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
     {
     Error_Handler();
     }
     HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
     HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
     if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN OCTOSPI1_Init 2 */
    
     /* USER CODE END OCTOSPI1_Init 2 */
    
    }


    Inside the main:

    int main(void)
    {
    ...
     MX_OCTOSPI1_Init();
    ...
     OSPI_HyperbusCmdTypeDef mCommand = {0};
     OSPI_MemoryMappedTypeDef mMemMappedCfg = {0};
     mCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE;
     mCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
     mCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
     mCommand.Address = 0;
     mCommand.NbData = 1;
    
     if (HAL_OSPI_HyperbusCmd(&hospi1, &mCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
     {
     Error_Handler();
     }
     mMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE;
     mMemMappedCfg.TimeOutPeriod = 0x20;
     if (HAL_OSPI_MemoryMapped(&hospi1, &mMemMappedCfg) != HAL_OK)
     {
     Error_Handler();
     }
     __IO uint8_t *mem_addr;
     mem_addr = (__IO uint8_t *)(OCTOSPI1_BASE);
     memcpy(mem_addr, &ofTxBuffer, sizeof(ofTxBuffer));
     uint8_t octoFLASHData[128] = {0};
     memcpy(&octoFLASHData, mem_addr, sizeof(ofTxBuffer));
     printk("String in octo flash: %s\r\n", octoFLASHData);memcpy(mem_addr, &ofTxBuffer, sizeof(ofTxBuffer));
    }

    When it gets to the point where to write to the flash it hard-faults.

    Any ideas?