RT-Thread Integration Guide
The Artok HMI Runtime is designed to work seamlessly with the RT-Thread ecosystem. By leveraging the RT-Thread Device Driver framework (LCD, Touch, and SPI Flash), Artok can be integrated into a multi-threaded environment with standard POSIX-like calls and high reliability.
📦 1. System Requirements
To run Artok effectively within an RT-Thread environment, ensure your rtconfig.h allows for sufficient stack and heap allocation:
| Requirement | Recommended Spec | Benefit |
|---|---|---|
| RTOS Task Stack | 4KB - 8KB | Sufficient depth for Lua scripts and UI parsing. |
| Heap Memory | 32KB+ Free | Dynamic allocation for UI widget registries. |
| Device Drivers | LCD, Touch, SPI | Uses the standard rt_device interface. |
🔧 2. Hardware Abstraction (RT-Thread Drivers)
In RT-Thread, we avoid direct register access. Instead, we wrap the rt_device_t operations inside the Artok HAL.
Storage & Display Bridge
#include <rtthread.h>
#include <rtdevice.h>
#include "atk_runtime.h"
static rt_device_t lcd_dev;
static rt_device_t flash_dev;
// 1. Flash Read (Using RT-Thread SFUD/FAL)
uint32_t rt_artok_flash_read(uint8_t* p_buffer, uint32_t address, uint32_t size) {
// Offset 0 maps to the UI binary in your flash partition
return rt_device_read(flash_dev, address, p_buffer, size);
}
// 2. Display Flush (Using RT-Thread LCD Device)
void rt_artok_disp_flush(void *p_disp_drv, int32_t x1, int32_t y1, int32_t x2, int32_t y2, void *p_color) {
struct rt_device_rect_info rect;
rect.x = x1;
rect.y = y1;
rect.width = x2 - x1 + 1;
rect.height = y2 - y1 + 1;
rt_device_control(lcd_dev, RTGRAPHIC_CTRL_RECT_UPDATE, &rect);
rt_device_write(lcd_dev, 0, p_color, rect.width * rect.height * 2);
// Signal transfer complete
ART_FlushComplete();
}
🚀 3. The 4-Tier Initialization Sequence
In RT-Thread, the initialization should happen within a dedicated UI thread. This ensures the HMI doesn't block other system-critical threads (like networking or motor control).
static void artok_thread_entry(void *parameter) {
HMI_Hardware_Interface_t rt_hal;
// Find devices
lcd_dev = rt_device_find("lcd");
flash_dev = rt_device_find("W25Q");
// TIER 1: Core System Init
ART_Init();
// Prepare HAL Structure
rt_hal.read_flash = rt_artok_flash_read;
rt_hal.disp_flush_cb = rt_artok_disp_flush;
rt_hal.disp_buffer_1 = rt_malloc(ART_LCD_WIDTH * 20 * 2);
rt_hal.disp_buffer_size_bytes = ART_LCD_WIDTH * 20 * 2;
rt_hal.comm_send = rt_uart_send;
// TIER 2 & 3: Connectivity and Input
ART_InitComm(&rt_hal, NULL, 0);
ART_InitDisplay(&rt_hal);
ART_InitInput(&rt_hal);
// TIER 4: Start HMI Logic
if (ART_StartHMI(0, &rt_hal)) {
while (1) {
ART_MainLoop();
rt_thread_mdelay(5); // Yield to other threads
}
}
}
int artok_system_init(void) {
rt_thread_t thread = rt_thread_create("artok", artok_thread_entry, RT_NULL, 4096, 20, 10);
if (thread != RT_NULL) rt_thread_startup(thread);
return 0;
}
INIT_APP_EXPORT(artok_system_init);
🎮 4. Interaction API
Control your widgets via their UUIDs from any other thread in RT-Thread. Because Artok is thread-safe internally, you can push data from your sensor thread directly.
void sensor_thread_entry(void* param) {
while(1) {
float temp = read_temperature();
char buf[16];
sprintf(buf, "%.2f C", temp);
// Update UI via UUID from a different thread
atk_api_set_text("UUID_TEMP_DISPLAY", buf);
rt_thread_mdelay(1000);
}
}
🛡️ 5. RT-Thread Performance Notes
- FinSH Integration: You can export Artok status commands to the FinSH console (e.g., list_widgets) to debug UUIDs in real-time.
- Memory Management: Use rt_malloc and rt_free to ensure Artok uses the system's centralized heap manager.
- Wait Queues: If your SPI Flash is shared with a File System (like LittleFS), Artok handles the device locking via RT-Thread's internal semaphore system automatically.