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

Topics

 The hand-written-extern lesson

Functions

uint32_t calculate_idle_percentage (void)
 GFX idle-percent source — bind it to LV_SYSMON_GET_IDLE.

Variables

TaskHandle_t rtos_cm55_gfx_task_handle
 GFX task handle, owned by tesaiot_display_init() — never touch it from outside.
volatile tesaiot_display_diag_t g_tesaiot_display_diag
 Display diagnostics struct — use the ipc_ui_platform_diag() accessor, not the struct.
cy_stc_scb_i2c_context_t disp_touch_i2c_controller_context
 Shared display/touch I2C context — consumer writes the extern; bounded timeouts only.

Detailed Description

The archive's diagnostics surface and the exported symbols whose only declarations are the consumer's own — the display diagnostics struct and its accessor discipline, the GFX task handle, the shared display/touch I2C context, and the GFX idle-percent source. The generated bento_secure_undeclared.h and the hand-written-extern pattern that goes with it are covered in The hand-written-extern lesson.

Variant
mtb-mpy and mtb-only

Function Documentation

◆ calculate_idle_percentage()

uint32_t calculate_idle_percentage ( void )

GFX idle-percent source — bind it to LV_SYSMON_GET_IDLE.

Contract
The GFX idle-percent source the archive exports; the one real call is inside the archived Edge AI page's diag string (page_edge_ai.c:1461). The template's only use — and the exemplar to ship — is the LVGL configuration binding: LV_USE_SYSMON 1, the extern guarded by __ASSEMBLER__, and LV_SYSMON_GET_IDLE defined to this function, so LVGL's own system monitor reads the same number ipc_ui_platform_diag() reports as word 9.
Variant
mtb-mpy and mtb-only
#define LV_USE_SYSMON 1
#if LV_USE_SYSMON
/*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/
#ifndef __ASSEMBLER__
extern uint32_t calculate_idle_percentage(void);
#endif
#define LV_SYSMON_GET_IDLE calculate_idle_percentage

Variable Documentation

◆ rtos_cm55_gfx_task_handle

TaskHandle_t rtos_cm55_gfx_task_handle
extern

GFX task handle, owned by tesaiot_display_init() — never touch it from outside.

Contract
Created and owned by tesaiot_display_init(); its two references are internal (tesaiot_display.c:190 xTaskNotifyFromISR from the DC ISR, :212 the xTaskCreate out-parameter). Anti-example: never use it directly — never notify, suspend or delete the GFX task from outside. Declared in tesaiot_display.h despite the generated undeclared-list entry; do not add a conflicting hand-written extern.
Variant
mtb-mpy and mtb-only
Example (authored — no shipped call site)
/* Hand-written extern (bento_secure_undeclared.h lists the symbol;
* dist/cm55_core/include/tesaiot_display.h carries the declaration but
* drags the whole display include chain). Type per tesaiot_display.h: */
extern TaskHandle_t rtos_cm55_gfx_task_handle;
static void bento_ex_rtos_cm55_gfx_task_handle(void)
{
/* WRONG — do not do any of this:
*
* vTaskSuspend(rtos_cm55_gfx_task_handle); // display freezes
* vTaskDelete(rtos_cm55_gfx_task_handle); // LVGL orphaned
* vTaskPrioritySet(rtos_cm55_gfx_task_handle, ...); // starves I2C
*
* The handle is owned by tesaiot_display_init(). Right usage of this
* symbol is: none. */
}

◆ g_tesaiot_display_diag

volatile tesaiot_display_diag_t g_tesaiot_display_diag
extern

Display diagnostics struct — use the ipc_ui_platform_diag() accessor, not the struct.

Contract
Twenty references, all internal to tesaiot_display.c. The intended external access is the accessor ipc_ui_platform_diag(uint32_t *out, uint16_t max_words) (tesaiot_display.c:593; needs max_words >= 10, returns 10) — document the accessor, not the struct. On mtb-mpy the same ten words are ui._diag(); on mtb-only call the accessor from C. Declared in tesaiot_display.h despite the generated undeclared-list entry.
Variant
mtb-mpy and mtb-only
Example (authored — no shipped call site)
/* Hand-written extern — no shipped header declares this weak-hook
* accessor. Signature copied from the strong definition,
* tesaiot_display.c:593. */
extern uint16_t ipc_ui_platform_diag(uint32_t *out, uint16_t max_words);
static void bento_ex_g_tesaiot_display_diag(void)
{
uint32_t words[10]; /* contract: max_words >= 10 */
uint16_t n = ipc_ui_platform_diag(words, 10u);
if (n != 10u) {
return; /* diag hook absent or buffer small */
}
uint32_t flush_starts = words[5]; /* incrementing = frames are moving */
uint32_t gfx_idle_pct = words[9];
(void)flush_starts;
(void)gfx_idle_pct;
}

◆ disp_touch_i2c_controller_context

cy_stc_scb_i2c_context_t disp_touch_i2c_controller_context
extern

Shared display/touch I2C context — consumer writes the extern; bounded timeouts only.

Contract
No shipped header declares it — the consumer writes the extern. The SCB is initialised by the display bring-up (tesaiot_display.c:203); consumers must not call Cy_SCB_I2C_Init on it. Always paired with DISPLAY_I2C_CONTROLLER_HW as the base, never another SCB. The bus is shared, so every PDL call uses a bounded timeout (2 ms), never 0 / block-forever: these transactions run in the GFX task at MAX-1 priority, and a wedged clock-stretching device once parked the GFX task on the bus and starved every lower-priority CM55 task. Re-initialising touch after another master (OPTIGA) releases the bus must be deferred into the GFX task via the touch_needs_reinit flag drained in the LVGL read callback.
Variant
mtb-mpy and mtb-only
Example — third-party consumer on the shared bus (template)
/*******************************************************************************
* I2C shared with display — extern from lv_port_indev / display init
******************************************************************************/
extern cy_stc_scb_i2c_context_t disp_touch_i2c_controller_context;
#define SENSOR_I2C_HW DISPLAY_I2C_CONTROLLER_HW
#define SENSOR_I2C_CTX (&disp_touch_i2c_controller_context)
/* BOUNDED timeout per PDL byte call. This read runs in the GFX task at MAX-1
* priority: with the old 0 (= block forever), a wedged/clock-stretching 4000T
* parked the GFX task on the bus and starved every lower-priority CM55 task —
* the prime suspect for the USB joystick HID stream stall (JOYSTICK_EVIDENCE).
* 2 ms x ~5 byte-calls caps the worst case at ~10 ms, once, then backoff. */
#define I2C_TIMEOUT_MS (2U)
Example — touch driver init (template)
static void touchpad_init(void)
{
cy_rslt_t result = CY_RSLT_SUCCESS;
#if defined(MTB_CTP_GT911)
result = mtb_gt911_init(DISPLAY_I2C_CONTROLLER_HW,
#elif defined(MTB_CTP_ILI2511)
result = mtb_ctp_ili2511_init(&ctp_ili2511_cfg);
#elif defined(MTB_CTP_FT5406)
result = (cy_rslt_t)mtb_ctp_ft5406_init(&ctp_ft5406_cfg);
#endif
Example — deferred re-init after OPTIGA releases the bus (template)
/* ...context: inside the touchpad read callback - GFX task context ... */
/* Deferred reinit after OPTIGA released I2C bus — runs in GFX task context */
if (touch_needs_reinit) {
touch_needs_reinit = false;
#if defined(MTB_CTP_FT5406)
Cy_SCB_I2C_Disable(DISPLAY_I2C_CONTROLLER_HW,
Cy_SCB_I2C_Enable(DISPLAY_I2C_CONTROLLER_HW);
mtb_ctp_ft5406_init(&ctp_ft5406_cfg);
touch_i2c_error_count = 0;
#elif defined(MTB_CTP_GT911)
touchpad_init();
#elif defined(MTB_CTP_ILI2511)
touchpad_init();
#endif
}