cancel
Showing results for 
Search instead for 
Did you mean: 

Guide for mapping a new chip as an external flash. Is external loader required ?

rohan_m
Senior

Hello I am in the task of adding a new flash as an external flash via QSPI interface with the MCU STM32F777ZITx.

The flash that I want to add is S25FL256L as an external flash. I am not finding any references which I can use with this flash. Also it is not getting clear to me whether I need to make an external loader for mapping the external flash in memory mapped mode or only configuration is needed ?

rohan_m_0-1709562790625.pngrohan_m_1-1709562824039.pngrohan_m_2-1709562848167.png

 

22 REPLIES 22
STTwo-32
ST Employee

Hello @rohan_m 

I suggest you take a look at this MOOC specially the 3rd video which should be a good guide.

Best Regards.

STTwo-32

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.

Pavel A.
Evangelist III

An "external loader" is needed only if you want CubeIDE debugger load the content of your QSPI flash automatically when you start debugging (or running). Also if you use CubeProgrammer to program the QSPI flash. If you use other way to load the QSPI flash content, external loader is not needed. For example - if the ext. flash is used to store data that your application produces, or receives from outside.

Here is the one part of the ST BSP driver for similar flash chip S25FL512s:

https://github.com/STMicroelectronics/stm32-s25fl512s

 

rohan_m
Senior

I am facing this problem where the call to the CSP_QSPI_EnableMemoryMappedMode does not fail but the external flash looks like this even after writing something

rohan_m_0-1709575608461.png

 

You'll need an External Loader if you want the tools to download content.

To see the memory in the Debugger, etc, you'll need for your code to have successfully brought up the QSPI interface, pins, and external memory itself.

You should be able to implement read, write, and command functions to interact with the memory. Try reading the JEDEC ID and some pages first. Once you have that working you can provide this "Read Template" functionality to the Memory Mapping mode startup process, and then access to the 0x90000000 region will use that to allow the MCU to read the content.

Yours looks like the memory mapping still isn't working, and the access to 0x90000000 is faulting.

Start by reading the data/sheets and manuals for your S25FL256 memory, and get that working in your own BSP code.

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

>>Also it is not getting clear to me whether I need to make an external loader for mapping the external flash in memory mapped mode or only configuration is needed ?

Configuration here, but blank content will be 0xFF

Unconfigured, accesses will Hard Fault. Have a Hard Fault Handler that outputs actionable information so you can diagnose / debug the situation.

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

I mean the confusion I have is that to view the memory map in the debugging window external loader is not needed right ?

No, but the memory needs to be up and running. It needs to be visible to the MCU to be visible in the Debugger.

The way ST does things this will be deep into main() once you've called all the functions. What *ARM* wanted was this do be done in SystemInit(), so the memory is viable for C runtime initialization and the scatter loader, so that in main() you had a nearly complete operating environment working.

In other platforms the alternative is a "Debug Script" which peeks/pokes the system and peripheral registers to bring up the clocks, GPIO, and QSPI peripheral, and the attached memory.

ST could perhaps use the Init() function of the External Loader in-lieu of the platform suitable debugger script, but I'm not sure things are at that level of sophistication a decade in.

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

Also I believe no modifications in the .ld script just to read the manufacturer ID ?

Pavel A.
Evangelist III

No modifications in the .ld script. See below code to read S25FL256 ID on STM32F7. Change the ID for S25FL512 per the data sheet.

 

 

 

 

 


int8_t BSP_QSPI_FlashDetect(struct QSPI_FlashInfo *pInfo;)
{
  uint8_t rc;
  // Ensure it is reset to normal "indirect" mode
  if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK)
  {
    return QSPI_NOT_SUPPORTED;
  }

  HAL_Delay(100); //?? needs delay after reset?

  uint8_t id_buf[6];
  rc = BSP_QSPI_ReadFlashID(id_buf, sizeof(id_buf));
  if (QSPI_OK != rc) {
      dbgprintf("ReadID failed: %u\n", (unsigned)rc);
      return -1;
  }

  // Infineon S25FL256LAGNFI010
  const uint8_t id2_data[] = { 0x01, 0x60, 0x19, };
  // 0x19-> 32MB, 0x18 -> 16 MB
  // see [DS2, table 51]
  unsigned fl_mb = 0;
  if (0 == memcmp(id2_data, id_buf, 2)) {
      qi.FlashModel = 'S';
      switch(id_buf[2]) {
         case 0x18: fl_mb = 16; break;
         case 0x19: fl_mb = 32; break;
         case 0x1A: fl_mb = 64; break;
         default:
          dbgprintf("ERROR: QSPI Flash size code no match: %2.2X\n", id_buf[2]);
          return QSPI_NOT_SUPPORTED;
        }
  } else {
      dbgprintf("ERROR: QSPI Flash ID no match: %2.2X %2.2X\n", id_buf[0], id_buf[1]);
      return QSPI_NOT_SUPPORTED;
  }

  // Fill the flash characteristics:
  // In 3-byte address mode, only 16 MB are available!
  pInfo->FlashSize          = fl_mb * 1024u*1024u;
  pInfo->EraseSectorSize    = 4*1024u;  //4K
  pInfo->BigEraseSectorSize = 64*1024u;  //64K
  pInfo->ProgPageSize       = 256;
  pInfo->EraseSectorsNumber = pInfo->FlashSize/pinfo->EraseSectorSize;
  pInfo->ProgPagesNumber    = pInfo->FlashSize/pInfo->ProgPageSize;
  pInfo->DummyCycles        = 0; //dummy cycles not configured yet! TODO

  return QSPI_OK;
}

int8_t BSP_QSPI_ReadFlashID(uint8_t *id_buf, unsigned size)
{
  QSPI_HandleTypeDef *Ctx = &QSPIHandle;
  if (!id_buf || size < 1 || size > 256) {
      return QSPI_NOT_SUPPORTED;
  }
  QSPI_CommandTypeDef s_command = {
    .InstructionMode   = QSPI_INSTRUCTION_1_LINE,
    .Instruction       = 0x9F,
    .AddressMode       = QSPI_ADDRESS_NONE,
    .AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
    .DataMode          = QSPI_DATA_1_LINE,
    .NbData            = 0,
    .DummyCycles       = 0,
    .DdrMode           = QSPI_DDR_MODE_DISABLE,
    .DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY,
    .SIOOMode          = QSPI_SIOO_INST_EVERY_CMD,
    };
  /* Configure the command */
  s_command.NbData = size;
  if (HAL_QSPI_Command(Ctx, (void*)&s_command, 10) != HAL_OK)
  {
    return QSPI_ERROR;
  }

  /* Reception of the data */
  if (HAL_QSPI_Receive(Ctx, id_buf, 10) != HAL_OK)
  {
    return QSPI_ERROR;
  }

  return QSPI_OK;
}