cancel
Showing results for 
Search instead for 
Did you mean: 

Problems using internal Flash

PJord.1
Associate

Hello,

I'm using an STM32F746 based board from EDT (http://www.edtc.com/sb_readmore.php?id=23), which can be selected as an application template in the TouchGFX Designer and start from there with the IAR toolchain.0693W000000VAymQAG.png

I'm having troubles being able to perform operations on the internal flash (erase/read) after the initialization of touchgfx is done:

STM32F7DMA dma;
ETEM043005XDH6TouchController tc;
STM32F7Instrumentation mcuInstr;
 
#if !defined(USE_BPP) || USE_BPP==16
LCD16bpp display;
#elif USE_BPP==24
LCD24bpp display;
#else
#error Unknown USE_BPP
#endif
 
 
void touchgfx_init()
{
    HAL& hal = touchgfx_generic_init<STM32F7HAL>(dma, display, tc, 480, 272, 0, 0);
    os_inited = true;
 
#if !defined(USE_BPP) || USE_BPP==16
#ifdef SINGLE_FRAME_BUFFER_INTERNAL
    //setup for single buffering
    hal.setFrameBufferStartAddress((uint16_t*)frameBuf0, 16, false, false);
 
    // The optimized strategy for single buffering requires the presence of a
    // task delay function.
    hal.registerTaskDelayFunction(&OSWrappers::taskDelay);
 
    // Enable strategy.
    hal.setFrameRefreshStrategy(HAL::REFRESH_STRATEGY_OPTIM_SINGLE_BUFFER_TFT_CTRL);
#else
    //setup for double buffering.
    hal.setFrameBufferStartAddress((uint16_t*)frameBuf0);
#endif
#elif USE_BPP==24
#ifdef  SINGLE_FRAME_BUFFER_INTERNAL
#error Single frame buffer in internal is only possible in 16bpp due to memory constraints.
#endif
    hal.setFrameBufferStartAddress((uint16_t*)frameBuf0, 24);
#else
#error Unknown USE_BPP
#endif
 
    hal.setTouchSampleRate(2);
    hal.setFingerSize(1);
 
    // By default frame rate compensation is off.
    // Enable frame rate compensation to smooth out animations in case there is periodic slow frame rates.
    hal.setFrameRateCompensation(false);
 
    // This platform can handle simultaneous DMA and TFT accesses to SDRAM, so disable lock to increase performance.
    hal.lockDMAToFrontPorch(false);
 
    mcuInstr.init();
 
    //Set MCU instrumentation and Load calculation
    hal.setMCUInstrumentation(&mcuInstr);
    hal.enableMCULoadCalculation(true);
}

I am able to perform those operations if I don't call touchgfx_init(), which makes me think that there are some instructions in there that may be using the flash or maybe locking the HAL or something like that.

The code used to erase the sector first, and program it with dummy data is:

void main()
{  
   hw_init();
   touchgfx_init()
  
  /* Unlock the Flash to enable the flash control register access *************/
  HAL_FLASH_Unlock();
 
  /* Erase the user Flash area
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
 
  /* Get the 1st sector to erase */
  FirstSector = GetSector(ADDR_FLASH_SECTOR_7 );
  /* Get the number of sector to erase from 1st sector*/
  NbOfSectors = GetSector(FLASH_USER_END_ADDR) - FirstSector + 1;
  /* Fill EraseInit structure*/
  EraseInitStruct.TypeErase     = FLASH_TYPEERASE_SECTORS;
  EraseInitStruct.VoltageRange  = FLASH_VOLTAGE_RANGE_3;
  EraseInitStruct.Sector        = FirstSector;
  EraseInitStruct.NbSectors     = NbOfSectors;
 
 
  if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
  {
    printf("Unable to erase sector\n");
  }
  printf("Sector erased :)\n");
  
  uint16_t i;
  HAL_StatusTypeDef status = HAL_ERROR;
  
  Address = FLASH_USER_START_ADDR;  //ADDR_FLASH_SECTOR_7
  for(i = 0; i < 4; i++)
  {
    // #define DATA_32                 ((uint32_t)0x12345678)
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, DATA_32); 
    Address = Address + 4;
  }
}

I have no clue how to find a solution for this since all the generated cpp code in the touchgfx is quite daunting to me (this is my first time working with embedded).

However, I've spent a good amount of time trying to debug it and I have noticed a few things that might help solving it:

  • When debugging the program step by step, if I step into the erase instruction it does it successfully (if I don't, the debugger is hung there)
  • If I do the same when reaching the program instuction (step-by-step as done above) it is able to do some iterations before it hangs.
  • When hung, if I hit pause it brings up a HardFault Exception "The processor has escalated a configurable-priority exception to HardFault. An unaligned access error has occurred (CFSR. UNALIGNED)". View of the debugger screen below.

0693W000000VB8cQAG.png

pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
 
    0x8008498: 0x6ea1         LDR       R1, [R4, #0x68]
    0x800849a: 0x68c8         LDR       R0, [R1, #0xc]
    0x800849c: 0x68c5         LDR       R5, [R0, #0xc]

This is the instruction that's raising the exception as the fault exception viewer says.

If I can provide anything else of use, please let me know. Thank you so much for reading.

PS: I'll also leave the code of the hw_init() function which is also auto-generated.

void hw_init()
{
    HAL_Init();
 
    SystemClock_Config(); //200MHz overdrive, FL6
 
    /* Initialize the QSPI */
    BSP_QSPI_Init();
    BSP_QSPI_MemoryMappedMode();
    HAL_NVIC_DisableIRQ(QUADSPI_IRQn);
 
#ifndef SINGLE_FRAME_BUFFER_INTERNAL
    BSP_SDRAM_Init();
#endif
 
    BSP_LCD_Init();
    BSP_LCD_LayerInit(0, frameBuf0);
    BSP_LCD_DisplayOn();
    
    MX_TIM12_Init();
 
#ifndef SIMULATOR
    //MX_USART2_UART_Init();
    MX_USART6_UART_Init();  
    //MX_I2C_Init();
    //MX_SPI5_Init();
    MX_GPIO_Init();
#endif
    
    GPIO::init();
    
    
    SCB_EnableDCache();
    SCB_EnableICache();
 
    //Enable CRC engine for STM32 Lock check
    __HAL_RCC_CRC_CLK_ENABLE();
 
    /* Configure unused area of QSPI region as strongly ordered.
     * This is *important* to avoid unintentional fetches from illegal
     * addresses due to cache/speculation which would halt the MCU.
     */
    HAL_MPU_Disable();
    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);
 
    //Deactivate speculative/cache access to first FMC Bank to save FMC bandwidth
    FMC_Bank1->BTCR[0] = 0x000030D2;
}

1 REPLY 1
PJord.1
Associate

I think I've solve it by programming the flash in another task and not in main. However, could anyone point me which is the role that would play having an MPU initialization for the flash region? Like so:

// MPU FOR SECTOR 7 OF FLASH
MPU_InitStruct.BaseAddress = 0x080C0000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256KB;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
 
HAL_MPU_ConfigRegion(&MPU_InitStruct);

I've done it now but I'm not sure if it's making any difference.