Skip to main content
Version: v2.4.0 (Current)

FreeRTOS Integration Guide

The Artok HMI Runtime is fully thread-safe and designed to thrive in FreeRTOS environments. By isolating the HMI engine into its own high-priority task, you can ensure smooth 60FPS animations even while the CPU is performing heavy background processing like TCP/IP networking or Motor Control.


📦 1. Task Configuration​

To run Artok on FreeRTOS, you must allocate a dedicated task. Because the runtime handles Lua scripting and complex UI parsing, we recommend the following stack settings:

ParameterRecommended ValueDescription
Task PriorityconfigMAX_PRIORITIES - 1High priority ensures UI responsiveness.
Stack Size2048 - 4096 wordsDepends on UI complexity and Lua usage.
Tick Rate1000 HzRequired for accurate 1ms timing via ART_IncTick.

🔧 2. Hardware Abstraction (Safe HAL)​

In FreeRTOS, hardware resources (SPI/I2C) are often shared. You must use Mutexes within your HAL callbacks to prevent data corruption.

Thread-Safe Callbacks​

#include "FreeRTOS.h"
#include "semphr.h"
#include "atk_runtime.h"

SemaphoreHandle_t xFlashMutex;

// 1. Thread-Safe Flash Read
uint32_t freertos_flash_read(uint8_t* buf, uint32_t addr, uint32_t size) {
uint32_t read_len = 0;
if (xSemaphoreTake(xFlashMutex, portMAX_DELAY) == pdTRUE) {
// Perform SPI Flash Read
// read_len = W25Q_Read(buf, addr, size);
xSemaphoreGive(xFlashMutex);
}
return read_len;
}

// 2. Display Flush with DMA Notification
void freertos_disp_flush(void *drv, int32_t x1, int32_t y1, int32_t x2, int32_t y2, void *color) {
// Start DMA transfer to LCD
// LCD_DMA_Transmit(color, size);

// Note: ART_FlushComplete() should be called from the DMA TC Interrupt
}

🚀 3. The 4-Tier Initialization Sequence​

In FreeRTOS, the HMI should be initialized inside the Task Entry function. This ensures that the scheduler is already running when the HMI starts allocating its internal resources.

void vArtokGUITask(void *pvParameters) {
HMI_Hardware_Interface_t rtos_hal;
xFlashMutex = xSemaphoreCreateMutex();

// TIER 1: Core System Init
ART_Init();

// Prepare HAL Structure
rtos_hal.read_flash = freertos_flash_read;
rtos_hal.disp_flush_cb = freertos_disp_flush;
rtos_hal.disp_buffer_1 = pvPortMalloc(ART_LCD_WIDTH * 20 * 2);
rtos_hal.disp_buffer_size_bytes = ART_LCD_WIDTH * 20 * 2;
rtos_hal.comm_send = rtos_uart_send;

// TIER 2 & 3: Connectivity and Input
ART_InitComm(&rtos_hal, NULL, 0);
ART_InitDisplay(&rtos_hal);
ART_InitInput(&rtos_hal);

// TIER 4: Launch HMI
if (ART_StartHMI(0x00000000, &rtos_hal)) {
while (1) {
// Main UI Heartbeat
ART_MainLoop();

// Yield for 5ms to allow lower priority tasks to run
vTaskDelay(pdMS_TO_TICKS(5));
}
}
}

🎮 4. Interaction API (Cross-Task Updates)​

The atk_api functions are designed to be called from any task. For example, your "Sensor Task" can update a Label UUID directly without needing complex message queues.

void vSensorTask(void *pvParameters) {
while(1) {
int32_t current_val = read_adc();

// Directly push data to the HMI Task via UUID
// The Artok Engine handles the internal synchronization
atk_api_set_value("UUID_SENSOR_GAUGE", current_val);

vTaskDelay(pdMS_TO_TICKS(500));
}
}

🛡️ 5. FreeRTOS Best Practices​

  • Tick Provider: Ensure ART_IncTick(1) is called every 1ms. The best place for this is vApplicationTickHook() or a dedicated high-priority timer interrupt.

  • Memory Management: Use pvPortMalloc for your display buffers to ensure they are managed by the FreeRTOS heap (Heap_4 or Heap_5 recommended).

  • Interrupt Safety: If you trigger UI updates from an ISR, ensure you use the appropriate FromISR wrappers if your specific port requires them, though atk_api is best called from Task context.

  • Watchdog: If using a Task Watchdog, ensure ART_MainLoop() is called frequently enough to prevent a system reset during heavy UI transitions.