cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U599 Hard fault inside touchgfx::Application::draw(touchgfx::Rect&)

bornamm
Associate II

Hello,

I have successfully implemented a Touchgfx based UI app using cubeMX and freertos on the STM32U599 chip. This is a basic application with multiple screens, a number of components all in ARGB2222. I am now in the process of porting my app from FreeRTOS to the zephyr platform. I am able to initialize touchgfx and start the process.

Using gdb I verified the touch gfx process going through my first screen setup and invalidate it. But at some point in touchgfx::Application::draw(touchgfx::Rect&), a hard fault is produced.

I have two theories on how this could be happening:

1- Linker issues. At first zephyr was trying to allocate my UI elements where it saw fit. So I looked at the '.list' generated by cubeIDE to understand where my sections should be placed. Doing so I was able to put together the following linker sections and passed it to zephyr using cmake:

SECTION_PROLOGUE(TouchGFX_Framebuffer, (NOLOAD),) { . = ALIGN(4); __TouchGFX_Framebuffer_start = .; KEEP(*("TouchGFX_Framebuffer")) __TouchGFX_Framebuffer_end = ALIGN(4); } GROUP_DATA_LINK_IN(RAMABLE_REGION,ROMABLE_REGION) /*GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)*/ SECTION_PROLOGUE(FontFlashSection,,) { . = ALIGN(4); __FontFlashSection_start = .; KEEP(*("FontFlashSection")) __FontFlashSection_end = ALIGN(4); } GROUP_DATA_LINK_IN(ROMABLE_REGION, ROMABLE_REGION) SECTION_PROLOGUE(FontSearchFlashSection,,) { . = ALIGN(4); __FontSearchFlashSection_start = .; KEEP(*("FontSearchFlashSection")) __FontSearchFlashSection_end = ALIGN(4); } GROUP_DATA_LINK_IN(ROMABLE_REGION, ROMABLE_REGION) SECTION_PROLOGUE(FontSearchFlashSection,,) { . = ALIGN(4); __FontSearchFlashSection_start = .; KEEP(*("FontSearchFlashSection")) __FontSearchFlashSection_end = ALIGN(4); } GROUP_DATA_LINK_IN(ROMABLE_REGION, ROMABLE_REGION) SECTION_PROLOGUE(TextFlashSection,,) { . = ALIGN(4); __TextFlashSection_start = .; KEEP(*("TextFlashSection")) __TextFlashSection_end = ALIGN(4); } GROUP_DATA_LINK_IN(ROMABLE_REGION, ROMABLE_REGION) SECTION_PROLOGUE(ExtFlashSection,,) { . = ALIGN(4); __ExtFlashSection_start = .; KEEP(*("ExtFlashSection")) __ExtFlashSection_end = ALIGN(4); } GROUP_DATA_LINK_IN(ROMABLE_REGION, ROMABLE_REGION)
View more

The following was part of the output of zephyr's compiled elf object dump. Notice how they get stored on flash and sram:

Sections: Idx Name Size VMA LMA File off Algn 22 TouchGFX_Framebuffer 00012c00 20010a08 0808ded0 00052b98 2**2 ALLOC 23 FontFlashSection 00004bac 0808ded0 0808ded0 0004dfec 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 24 FontSearchFlashSection 000004e8 08092a7c 08092a7c 00052b98 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 25 FontSearchFlashSection 00000000 08092f64 08092f64 0006bc4c 2**0 CONTENTS 26 TextFlashSection 00000f3a 08092f64 08092f64 00053080 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 27 ExtFlashSection 00017c8c 08093ea0 08093ea0 00053fbc 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA

I chose the ramable regions and romable regions based on what cubeIDE produced. I'm wondering if this manual process of section definitions is where draw(touchgfx::Rect&) is failing?

 

2- Cache issues. My second hypothesis is that the ICACHE, DCACHE, and CRC are not working as expected. To address this issue, I used the functions inside HAL library to setup these peripherals manually as I did not find a way to have zephyr accomplish this for me. I defined the following functions directly from HAL:

static void DCACHE_Init(void) { /************************ DCACHE 1 **************************/ /* Set requested read burst type */ MODIFY_REG(DCACHE1->CR, DCACHE_CR_HBURST, DCACHE_READ_BURST_WRAP); /* Enable the selected DCACHE peripheral */ /* Check no ongoing operation */ while (READ_BIT(DCACHE1->SR, (DCACHE_SR_BUSYF | DCACHE_SR_BUSYCMDF)) != 0U) { /* Return busy status */ k_sleep(K_MSEC(1000)); printk("display_interface: DCACHE1 busy.\r\n"); } /* Enable the selected DCACHE peripheral */ SET_BIT(DCACHE1->CR, DCACHE_CR_EN); /************************ DCACHE 2 **************************/ /* Set requested read burst type */ MODIFY_REG(DCACHE2->CR, DCACHE_CR_HBURST, DCACHE_READ_BURST_WRAP); /* Enable the selected DCACHE peripheral */ /* Check no ongoing operation */ while (READ_BIT(DCACHE2->SR, (DCACHE_SR_BUSYF | DCACHE_SR_BUSYCMDF)) != 0U) { /* Return busy status */ k_sleep(K_MSEC(100)); printk("display_interface: DCACHE2 busy.\r\n"); } /* Enable the selected DCACHE peripheral */ SET_BIT(DCACHE2->CR, DCACHE_CR_EN); } static void ICACHE_Init(void) { /* Check cache is not enabled */ while (READ_BIT(ICACHE->CR, ICACHE_CR_EN) != 0U) { /* Return busy status */ k_sleep(K_MSEC(100)); printk("display_interface: ICACHE busy.\r\ndisplay_interface: Disabling and reconfiguring ICACHE\r\n"); /* Reset interrupt enable value */ // WRITE_REG(ICACHE->IER, 0U); /* Clear any pending flags */ // WRITE_REG(ICACHE->FCR, ICACHE_FCR_CBSYENDF | ICACHE_FCR_CERRF); /**** Disable cache then set default associative mode value ****/ CLEAR_BIT(ICACHE->CR, ICACHE_CR_EN); WRITE_REG(ICACHE->CR, ICACHE_CR_WAYSEL); HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0); /* Peripheral interrupt init */ /* ICACHE_IRQn interrupt configuration */ HAL_NVIC_SetPriority(ICACHE_IRQn, 5, 0); HAL_NVIC_EnableIRQ(ICACHE_IRQn); /* Stop monitor and reset monitor values */ // CLEAR_BIT(ICACHE->CR, ICACHE_MONITOR_HIT_MISS); // SET_BIT(ICACHE->CR, (ICACHE_MONITOR_HIT_MISS << 2U)); // CLEAR_BIT(ICACHE->CR, (ICACHE_MONITOR_HIT_MISS << 2U)); /* Reset regions configuration values */ // WRITE_REG(ICACHE->CRR0, ICACHE_REGIONSIZE_2MB << ICACHE_CRRx_RSIZE_Pos); // WRITE_REG(ICACHE->CRR1, ICACHE_REGIONSIZE_2MB << ICACHE_CRRx_RSIZE_Pos); // WRITE_REG(ICACHE->CRR2, ICACHE_REGIONSIZE_2MB << ICACHE_CRRx_RSIZE_Pos); // WRITE_REG(ICACHE->CRR3, ICACHE_REGIONSIZE_2MB << ICACHE_CRRx_RSIZE_Pos); } MODIFY_REG(ICACHE->CR, ICACHE_CR_WAYSEL, ICACHE_1WAY); SET_BIT(ICACHE->CR, ICACHE_CR_EN); } static void CRC_Init(void) { printk("display_interface: CRC Init.\r\n"); SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN); /* initialize peripheral with default generating polynomial */ WRITE_REG(CRC->POL, DEFAULT_CRC32_POLY); MODIFY_REG(CRC->CR, CRC_CR_POLYSIZE, CRC_POLYLENGTH_32B); /* set default CRC initial value */ WRITE_REG(CRC->INIT, DEFAULT_CRC_INITVALUE); /* set input data inversion mode */ MODIFY_REG(CRC->CR, CRC_CR_REV_IN, CRC_INPUTDATA_INVERSION_NONE); /* set output data inversion mode */ MODIFY_REG(CRC->CR, CRC_CR_REV_OUT, CRC_OUTPUTDATA_INVERSION_DISABLE); }
View more

 the execution order after kernel initialization is: 

  1. DCACHE init
  2. ICACHE init
  3. CRC init
  4. TouchGFX init
  5. signalvsync
  6. TOUCHGFX process

Given all of this information, how can I find out what is causing drawCachedAreas() to fail? I believe I am very close to getting touch gfx to work on the zephyr project, I am probably not configuring some peripheral that touchgfx needs. Any help would appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions
bornamm
Associate II

UPDATE:

Adjusting stack and heap memory size using zephyr k_configs fixed the issue.

View solution in original post

1 REPLY 1
bornamm
Associate II

UPDATE:

Adjusting stack and heap memory size using zephyr k_configs fixed the issue.