Unable to Read/Write OctoSPI in Hyperbus mode.
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);
}
