2021-03-19 07:37 AM
Hi everyone,
I have followed the tutorial from ST to set the external loader :
https://www.youtube.com/watch?v=XqCq0xtQmbI
https://github.com/STMicroelectronics/stm32-external-loader/tree/contrib
Here's my HW config :
I use the same QSPI (MX25L51245G) than on the ST example but on an H7 & OSPI interface board. My QSPI runs at 100MHz. I proceed to some modifications on the example in order to get the functions work using the OSPI hal libraries (following stm32l4p5g_discovery example), but I still use the same commands. Using an oscilloscope, it appears to me that I see the correct datas in the signals during the set up.
My problem is that the test fails at last part, where the programs compare the readed buffer in memory mapped mode to the previously written buffer :
I only get 0xFFFFFFFF datas at my QSPI bank address (0x90000000)
My CSP_QSPI_EnableMemoryMappedMode function is a bit different from the ST example, but still, through the oscilloscope the signal also gives me 0xFFFFFFFF (QUAD_IO_READ_CMD 0x6B command).
Though, it's a bit hard to interpret the page program sequence signals with my scope to see if the correct data are written, but I get no errors in the program and the used function is the same than the one used on the ST example.
Have you any guess why I read theses data ? Did I misconfigured a register or something ?
You can download my project here and source file here:
https://github.com/pa0694/EXT_LOADER/blob/master/Core/Inc/octospi.h
https://github.com/pa0694/EXT_LOADER/blob/master/Core/Src/octospi.c
Thanks for the help !
2021-03-19 09:38 AM
My guess would be the issue is writing. You could confirm this by 1/2/4 bit reads using direct access rather than memory mapping. If it is already erased skip that test until you can write half-a-dozen bytes.
I'd start with working BSP code, and then reintegrate with External Loader.
2021-03-25 08:23 AM
Hi @Community member
I tried to run some tests on simple write / read of a single byte in SPI mode with PAGE PROGRAM (PP) and FAST_READ instructions. I noticed a strange behavior on my signals : the writing signal sequence seems in accordance with the datasheet, but concerning the read signal sequence, it appears that the readed data are transferred on the D0 line (IO0/SI) instead of the D1 line (IO1/SO). And my D1 line isn’t high impedance when the read instruction is sended.
Here is the test performed in main (still the same project / initializations than on my first post):
uint8_t qspi_aRxBuffer[MEMORY_SECTOR_SIZE] = {0};
uint8_t qspi_aTxBuffer[MEMORY_SECTOR_SIZE] = {0};
uint32_t var = 0;
CSP_QUADSPI_Init();
for (var = 0; var < MEMORY_SECTOR_SIZE; var++)
{
qspi_aTxBuffer[var] = 0x55; //(var & 0xff);
}
for (var = 0; var < MEMORY_SECTOR_SIZE; var++)
{
if(BSP_PageProgram(&qspi_aTxBuffer[var], var, 1) != HAL_OK)
{
while (1); //breakpoint - error detected
}
if(BSP_ReadPageSTR(&qspi_aRxBuffer[var], var, 1) != HAL_OK) // reads only 0xFF
{
while (1); //breakpoint - error detected
}
}
And my func debugged with scope on 0x55 writting/reading at adress 0x0000002 for ex:
write:
read:
My buffer is still filled with 0xFF because that's the data on the scope.
But I also notice that whatever the page adress aksed for reading is in BSP_ReadPageSTR, the last 8 bits of D0 are the last data written by my BSP_PageProgram.
Thanks for help.
2021-03-25 08:25 AM
Here are my BSP func :
int32_t BSP_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size)
{
OSPI_RegularCmdTypeDef sCommand = {0};
/* Initialize the program command */
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
sCommand.Instruction = QUAD_PAGE_PROG_CMD; // 0x02
sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
sCommand.Address = WriteAddr;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = HAL_OSPI_DATA_1_LINE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DummyCycles = 0U;
sCommand.NbData = Size;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
/* Configure the command */
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
/* Transmission of the data */
if (HAL_OSPI_Transmit(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
uint8_t BSP_ReadPageSTR(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
{
OSPI_RegularCmdTypeDef sCommand;
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
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.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytes = 0x00;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD; //10
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_ONLY_FIRST_CMD;
sCommand.Instruction = FAST_READ; // 0x0B
sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
sCommand.DataMode = HAL_OSPI_DATA_1_LINE;
sCommand.Address = ReadAddr;
sCommand.NbData = Size;
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
if (HAL_OSPI_Receive(&hospi1, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}