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)

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);
}

 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.