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, 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:
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.