2024-11-22 10:57 AM
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, DATAI 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:
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.
Solved! Go to Solution.
2024-11-22 5:36 PM
UPDATE:
Adjusting stack and heap memory size using zephyr k_configs fixed the issue.
2024-11-22 5:36 PM
UPDATE:
Adjusting stack and heap memory size using zephyr k_configs fixed the issue.