SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
Loading...
Searching...
No Matches

Functions

BaseType_t tesaiot_display_init (void)
 Sole public entry — creates the GFX task before the scheduler starts; compare against pdPASS.
void tesaiot_display_task (void *arg)
 The GFX task body — never create it, never call it.

Variables

volatile uint8_t tesaiot_display_ready
 Tri-state bring-up flag: 0 pending, 1 display + IPC, 2 IPC-only headless.

Detailed Description

Header: tesaiot_display.h. Implementation: archived tesaiot_display.c (libbento_cm55.a). Owns GFXSS, vg_lite and LVGL bring-up, the display and touch I2C bus, the GFX task, and — because it runs the IPC prologue before the display — the whole CM55 boot ordering (see the ipc_core reference).

Variant
mtb-mpy and mtb-only

tesaiot_display_ready is tri-state

0 = pending, 1 = display + IPC up, 2 = IPC-only headless (the panel failed but the IPC path came up). Both shipped callers test == 0, so a headless board proceeds. Testing for == 1 would hang a consumer on a board with a dark panel — which after a debugger reset every board is.

Function Documentation

◆ tesaiot_display_init()

BaseType_t tesaiot_display_init ( void )

Sole public entry — creates the GFX task before the scheduler starts; compare against pdPASS.

Contract
Required order: cybsp_init() then __enable_irq() then this — the GFXSS DC/GPU ISRs are wired during task startup, so interrupts must be on first. Called from main() before vTaskStartScheduler(): it creates the GFX task, it does not run it. Compare the return against pdPASS, not CY_RSLT_SUCCESS. The template hard-fails into distinct LED loops (LED1 = cybsp_init failed, LED2 = this failed) so the two are visually distinct. It is the sole public entry: it creates the GFX task with xTaskCreate(tesaiot_display_task, ...) and stores the handle in rtos_cm55_gfx_task_handle (tesaiot_display.c:210-213). The task brings up IPC before the display so IPC survives a display failure — which is why tesaiot_display_ready has the value 2.
Variant
mtb-mpy and mtb-only
int main(void)
{
cy_rslt_t result;
#if TESAIOT_ENABLE_FACE_RUNTIME && TESAIOT_ENABLE_FACE_RUNTIME_BOOT
/* Alternate boot mode: launch native Face-ID runtime. */
if (face_mode_runtime_requested()) {
face_mode_launch_runtime();
}
#endif
/* Initialize the device and board peripherals */
result = cybsp_init();
if (CY_RSLT_SUCCESS != result)
{
for (;;) {
Cy_GPIO_Inv(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN);
Cy_SysLib_Delay(50);
}
}
/* Enable global interrupts */
__enable_irq();
/* GFX task: GFXSS/LVGL init + IPC + sensorhub UI */
BaseType_t xResult = tesaiot_display_init();
if (pdPASS != xResult) {
for (;;) {
Cy_GPIO_Inv(CYBSP_USER_LED2_PORT, CYBSP_USER_LED2_PIN);
Cy_SysLib_Delay(50);
}
}

◆ tesaiot_display_task()

void tesaiot_display_task ( void * arg)

The GFX task body — never create it, never call it.

Contract
The GFX task body. Referenced only as the xTaskCreate argument inside tesaiot_display_init() (tesaiot_display.c:211). Anti-example: never create it yourself, never call it — a second GFX task means two LVGL owners, two IPC prologues and a double cm55_ipc_communication_setup(). Consumers call tesaiot_display_init() and nothing else.
Variant
mtb-mpy and mtb-only
Example (authored — no shipped call site)
/* Hand-written externs matching dist/cm55_core/include/tesaiot_display.h
* (included here as declarations only, to keep the example free of that
* header's display include chain): */
extern BaseType_t tesaiot_display_init(void);
extern void tesaiot_display_task(void *arg);
static void bento_ex_tesaiot_display_task(void)
{
/* WRONG:
* xTaskCreate(tesaiot_display_task, "gfx2", 4096, NULL, 1, NULL);
* tesaiot_display_task(NULL); // never returns, no init
*
* RIGHT — the one public entry, from main() pre-scheduler: */
if (tesaiot_display_init() != pdPASS) { /* pdPASS, not CY_RSLT_* */
/* distinct LED failure loop in shipped main(); do not continue
* into vTaskStartScheduler() pretending the display exists */
return;
}
}

Variable Documentation

◆ tesaiot_display_ready

volatile uint8_t tesaiot_display_ready
extern

Tri-state bring-up flag: 0 pending, 1 display + IPC, 2 IPC-only headless.

Contract
No shipped header declares it (bento_secure_undeclared.h); the consumer writes its own extern volatile uint8_t, and volatile is mandatory — the GFX task writes it. Poll only from a FreeRTOS task after the scheduler starts, with vTaskDelay — never a busy spin, never from main(). The wait is always bounded (150 x 100 ms, or 10 000 ms) and falls through on timeout rather than hanging. Tri-state: 0 = pending, 1 = display + IPC, 2 = IPC-only headless; both shipped callers test == 0 so headless boots proceed. Purpose per the radar caller: avoid startup bus contention with GFX / IPC bring-up.
Variant
mtb-mpy and mtb-only
Example — app task (template)
static void app_task(void *arg)
{
CY_UNUSED_PARAMETER(arg);
/* Wait for display + IPC initialization to complete
* tesaiot_display_ready: 0=pending, 1=display+IPC, 2=IPC-only (headless) */
extern volatile uint8_t tesaiot_display_ready;
uint32_t wait_count = 0;
while (tesaiot_display_ready == 0)
{
vTaskDelay(pdMS_TO_TICKS(100));
wait_count++;
if (wait_count > 150) {
break;
}
}
Example — millisecond-budget variant (template, radar task)
void tesaiot_radar_task(void *arg)
{
(void)arg;
cy_rslt_t result;
/* Wait until display/IPC core is up to avoid startup bus contention with
* GFX/IPC bring-up on CM55. */
extern volatile uint8_t tesaiot_display_ready;
uint32_t wait_ms = 0U;
while ((tesaiot_display_ready == 0U) && (wait_ms < 10000U)) {
vTaskDelay(pdMS_TO_TICKS(50));
wait_ms += 50U;
}