cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to Read/Write OctoSPI in Hyperbus mode.

ashutoshtekriwal
Associate III

Hello,

We have interfaced a NOR flash (S26KL512SDABHN020) with STM32L562 over OctoSPI in Hyperbus mode. The Low level drivers were found from one of the forums of ST community and were ported in our code. We are unable to read/write data at the base address (0x90000000). We are also unsure about the offset to be provided in the below API. Should this offset be Sector/Page size ?

OctoSPI configuration settings in Hyperbus mode are also provided below for your reference. Clock frequency for OctoSPI is set to 60MHz.

 

(1) OctoSPI Initialization:

static void MX_OCTOSPI1_Init(void)

{

 

/* USER CODE BEGIN OCTOSPI1_Init 0 */

 

/* USER CODE END OCTOSPI1_Init 0 */

 

OSPI_HyperbusCfgTypeDef sHyperBusCfg = {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_HYPERBUS;

hospi1.Init.DeviceSize = 32;

hospi1.Init.ChipSelectHighTime = 1;

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 = 1;

hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;

hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;

hospi1.Init.ChipSelectBoundary = 0;

hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;

hospi1.Init.Refresh = 0;

if (HAL_OSPI_Init(&hospi1) != 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();

}

/* USER CODE BEGIN OCTOSPI1_Init 2 */

 

/* USER CODE END OCTOSPI1_Init 2 */

 

}

 

(2) Flash Write API (lld_WriteBufferProgramOp):

 

DEVSTATUS lld_WriteBufferProgramOp

(

FLASHDATA * base_addr, /* device base address in system */

ADDRESS offset, /* address offset from base address */

WORDCOUNT word_count, /* number of words to program */

FLASHDATA *data_buf /* buffer containing data to program */

)

{

ADDRESS last_loaded_addr;

ADDRESS current_offset;

ADDRESS end_offset;

FLASHDATA wcount;

FLASHDATA status_reg;

 

/* Initialize variables */

current_offset = offset;

end_offset = offset + word_count - 1;

last_loaded_addr = offset;

 

/* don't try with a count of zero */

if (!word_count)

{

return(DEV_NOT_BUSY);

}

 

/* Issue Load Write Buffer Command Sequence */

lld_WriteToBufferCmd(base_addr, offset);

 

/* Write # of locations to program */

wcount = (FLASHDATA)word_count - 1;

wcount *= LLD_DEV_MULTIPLIER; /* For interleaving devices */

 

/* In the datasheets of some latest Cypress devices, such as GLP, GLS, etc, the

command sequence of "write to buffer" command states the address of word count is

"Sector Address". Notice that to make LLD backward compatibility, the actual word

count address implemented is "Sector Address + LLD_UNLOCK_ADDR2", since the lower

address bits (a0-a15) are "don't care" bits and will be ignored anyway.

*/

FLASH_WR(base_addr, offset & SA_OFFSET_MASK , wcount);

 

/* Load Data into Buffer */

while(current_offset <= end_offset)

{

/* Store last loaded address & data value (for polling) */

last_loaded_addr = current_offset;

 

/* Write Data */

FLASH_WR(base_addr, current_offset, *data_buf++);

current_offset++;

}

 

/* Issue Program Buffer to Flash command */

lld_ProgramBufferToFlashCmd(base_addr, offset);

 

status_reg = lld_Poll(base_addr, last_loaded_addr);

 

if( status_reg & DEV_SEC_LOCK_MASK )

return( DEV_SECTOR_LOCK ); /* sector locked */

 

if( (status_reg & DEV_PROGRAM_MASK) == DEV_PROGRAM_MASK )

return( DEV_PROGRAM_ERROR ); /* program error */

 

return( DEV_NOT_BUSY ); /* program complete */

}

 

(3) Flash Read API (lld_ReadOp:(

 

FLASHDATA lld_ReadOp

(

FLASHDATA * base_addr, /* device base address is system */

ADDRESS offset /* address offset from base address */

)

{

FLASHDATA data;

 

data = FLASH_RD(base_addr, offset);

 

return(data);

}

#ifdef USER_SPECIFIC_CMD_3 //added NOR Page Read

/******************************************************************************

*

* lld_PageReadOp - Read memory array operation

*

* RETURNS: NA

*

*/

void lld_PageReadOp

(

FLASHDATA * base_addr, /* device base address is system */

ADDRESS offset, /* address offset from base address */

FLASHDATA * read_buf, /* read data */

FLASHDATA cnt /* read count */

)

{

FLASH_PAGE_RD(base_addr, offset, read_buf, cnt);

}

5 REPLIES 5
KDJEM.1
ST Employee

Hello @ashutoshtekriwal and welcome to the Community :),

Could you please share the memory datasheet?

What is the memory size?

If the memory size is 64 Mbytes, hospi1.Init.DeviceSize = 26;

In DDR mode, the Delay hold quarter cycle must be enabled

hospi1.Init.DelayHoldQuarterCycle = HHAL_OSPI_DHQC_ENABLE;

Could you please refer to memory datasheet and check the Write zero latency and the latency mode.

May Table 8. STM32CubeMX - Configuration of OCTOSPI parameters in AN5050 can help you.

Also could you please take a look at the Errata sheet and precisely 2.5.14 At least six cycles memory latency must be set when DQS is used for HyperBus™ memories.

I hope this help you.

Kaouthar

 

 

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.

Hello,

The above settings recommended by you have been tried out but we are unable to even read the Device ID itself.

We read Device ID as 0xFFFFFF.  We are completely stuck. Kindly suggest us more.

 

KDJEM.1
ST Employee

Hi @ashutoshtekriwal ,

I think the access time also is wrong:

 

sHyperBusCfg.AccessTime = 0;

 

and should be 

 

sHyperBusCfg.AccessTime = 6;

 

Access time (TACC) is expressed in number of OCTOSPI clock cycles, configured depending on the memory datasheet.

Could you please try to decrease the OCTOSPI clock frequency.

Could you check the RDP level and the hardware connections?

Please share the memory datasheet. 

I hope this help you.

Kaouthar

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.

Hello @KDJEM.1 ,

We have tried with the recommendations provided by you:

1. Set the Access time as 6.

2. Checked for different OCTOSPI frequencies: 4MHz, 15MHz, 20MHz, 30MHz and 60MHz.

3. RDP level is already at 0 as read in Option-Bytes using STM Programmer.

4. Hardware wise all the necessary pins are connected between NOR Flash and STM32L562. These pins are

     

All of these above settings have been tried but we could not read Device ID.

The datasheet is also being attached herewith. Our NOR Flash is S26KL512.

Please help with more ideas.

 

KDJEM.1
ST Employee

Hello @ashutoshtekriwal ,

 

I recommend you to take a look at these examples and get inspired to configure the OCTOSPI interface:

May this discussion can help you Solved: Looking for sample code for Hyperflash erase/progr... - STMicroelectronics Community.

 

Thank you.

Kaouthar

 

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.