cancel
Showing results for 
Search instead for 
Did you mean: 

External vs. internal flash memory for touchGFX assets

HP
Senior III

When developing touchGFX applications you tend to get a pretty high memory need.

I'm working with the CubeIDE integration of TouchGFX and tried to add a third screen (with a third background image). I got an error saying that the application would not fit in my FLASH.

After a bit of digging it seems that the linker files don't mention the QSPI at all.

I can add that to the linker files but I would like to know if there is an official way of doing this?

I found some documentation on this but I'm not sure if this is the right way to go about it.

What goes where in the memory and how do I control it? if at all?

Thanks!

40 REPLIES 40
BPark.3
Associate II

Having the same issue over here, I don't think its an issue with the contents of the QSPI as the images will display fine when running through the debugger- as configured in the thread by charles. Something about running in debug fixes the issue but if you try to run out of debug then the images are garbage.

Anyone know how debug mode differs from normal? the only thing i can think of is that there will be longer delays.

That is quite interesting.. I'm working in debug mode all along and I can't for the life of me get the damn memory to work as expected.

Did you change the linker script in the same way I did?

Did you have problems with adding the external loader as Charles did? I could find it through the list after pressing 'scan' but he mentioned that he was having trouble with that process.

HP
Senior III

Looking with a fresh pair of eyes I could not believe that I could take a complex application example from touchGFX Designer and see it work directly on my F746 board while my painstakingly pieced together code running in CubeIDE would not.

I have now looked into the TouchGFX Designer code and look what I found:

This is the QSPI init code:

hqspi.Instance = QUADSPI;
    hqspi.Init.ClockPrescaler = 1;
    hqspi.Init.FifoThreshold = 4;
    hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
    hqspi.Init.FlashSize = 24;
    hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;
    hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
    hqspi.Init.FlashID = QSPI_FLASH_ID_1;
    hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;

A quick look at my (CubeMX generated) code revealed that THEY ARE NOT THE SAME!!!!!!!!!!!!11111oneoneone

Please, can someone verify that this is not just me?

I have now changed my MX_QUADSPI_Init() code for the above one and hey. It works!

I now have external flash programming as part of the debugging routine as per Charles' post mentioned above. No need for external loaders.

I'm still en debug though...

HP
Senior III

I'm posting this for continuity in the thread. This have solved my issue with not being able to load from QSPI outside the debugging environment:

I'm running my application from cubeIDE so that's a prerequisite.

You will need to do the following:

  1. launch TouchGFX designer and load an application template.
  2. Generate the code and go the the folder where the sources are located.
  3. From the folder Driver-> BSP-> STM32746G-Discovery copy the qspi files - there should be 2, a 'c' and a 'h' file (code and header)
  4. paste the files into your project, preferably into the directory 'STM32746G-Discovery' which you might have in your project root.
  5. Add the following include to the top of your main.cpp file:
#include <stm32746g_discovery_qspi.h>

6. change your MX_QUADSPI_Init to this:

    hqspi.Instance = QUADSPI;
        hqspi.Init.ClockPrescaler = 1;
        hqspi.Init.FifoThreshold = 4;
        hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
        hqspi.Init.FlashSize = 24;
        hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;
        hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
        hqspi.Init.FlashID = QSPI_FLASH_ID_1;
        hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
     
     
      if (HAL_QSPI_Init(&hqspi) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN QUADSPI_Init 2 */
      BSP_QSPI_Init();
     
          BSP_QSPI_MemoryMappedMode();
          HAL_NVIC_DisableIRQ(QUADSPI_IRQn);
     
          MPU_Region_InitTypeDef MPU_InitStruct;
          MPU_InitStruct.Enable = MPU_REGION_ENABLE;
          MPU_InitStruct.BaseAddress = 0x90000000;
          MPU_InitStruct.Size = MPU_REGION_SIZE_256MB;
          MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
          MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
          MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
          MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
          MPU_InitStruct.Number = MPU_REGION_NUMBER2;
          MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
          MPU_InitStruct.SubRegionDisable = 0x00;
          MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
     
          HAL_MPU_ConfigRegion(&MPU_InitStruct);
     
          /* Configure the MPU attributes as WT for QSPI (used 16Mbytes) */
          MPU_InitStruct.Enable = MPU_REGION_ENABLE;
          MPU_InitStruct.BaseAddress = 0x90000000;
          MPU_InitStruct.Size = MPU_REGION_SIZE_16MB; /* NOTE! Change this if you change QSPI flash size! */
          MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
          MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
          MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
          MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
          MPU_InitStruct.Number = MPU_REGION_NUMBER3;
          MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
          MPU_InitStruct.SubRegionDisable = 0x00;
          MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
     
          HAL_MPU_ConfigRegion(&MPU_InitStruct);
          HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

The code should be able to compile and debug. Try unplugging the board and plugging it back in. Does it work now?

BPark.3
Associate II

Yep, changed the linker script in the same way, although my QSPI stuff generated with the same parameters as below. I didn't have a problem finding the external loader.

Does your program run properly if you restart the board (i.e. reboots to the correct screen and loads images fine)?

HP
Senior III

Yes, after I implemented the changes in the QSPI init and qspi driver files. Can you see my post below this comment?

Worked for me too, thanks!

BPark.3
Associate II

Thank you HP,

Has completely fixed my issues! Knight in shining armour.

HP
Senior III

@George Journeaux​  and @BPark.3​ 

Nice to know! I was pretty excited when I got my board to run yesterday evening so thank you both for verifying this!

I did a video of the initial configuration for youtube and during the preparation of that (remember the step where you copy the touchscreen driver?) there is also a qspi driver, but in the original video Martin deletes those files.

I had to delete it too since the video guide I did only covers the initial config with internal memory.

Seeing this it raises another question - the SDRAM driver is also not loaded. could it be possible to run without external SDRAM? That would make a PCB design even cheaper 🙂

Yeah, you have to enable SDRAM bank 1 in CubeMX and then tell your LTDC layer + TouchGFX 1 to use the start of SDRAM. It is possibe to use internal as well, no problem. Instead of providing an address you just declare an array (framebuffer) in internal ram and provide that address instead.

/Martin