Lily58 OLED屏幕切换故障排查求助
Lily58键盘Pomodoro定时器OLED显示故障排查建议
我正在为Lily58键盘开发内置Pomodoro定时器的keymap。当前遇到OLED图像显示问题:我有三个对应不同界面的位图,在keyboard_post_init_user中用memcpy把首个位图复制到显示缓冲区,再在oled_task_user里通过oled_write_raw显示,此时三个界面(启动界面、工作界面、休息界面)都能正常展示。但切换界面时,我通过RPC调用更新从板的定时器状态,在set_slave_pomodoro_state函数中再次用memcpy加载新位图到显示缓冲区后,两块OLED都出现故障。
相关代码
初始memcpy代码
void keyboard_post_init_user(void) { transaction_register_rpc(SYNC_POMODORO_STATE, set_slave_pomodoro_state); memcpy(header, headerBase, HEADER_SIZE); memcpy(statusDisplay, logoBase, STATUS_SIZE); }
OLED更新代码
bool oled_task_user(void) { if (is_keyboard_master()) { oled_write_ln(read_layer_state(), false); oled_write_ln(read_pomodoro_state(), false); } else { update_pomodoro_display(); } return false; } void update_pomodoro_display(void) { // oled_clear(); oled_set_cursor(0, 0); oled_write_raw(header, HEADER_SIZE); oled_set_cursor(0, 1); oled_write_raw(statusDisplay, STATUS_SIZE); }
引发故障的代码(已注释)
void set_slave_pomodoro_state(uint8_t in_buflen, const void *in_data, uint8_t out_buflen, void *out_data) { state = *(pomo_state*)in_data; // if (state == _WORK) { // memcpy(statusDisplay, workBase, STATUS_SIZE); // } else if (state == _REST) { // memcpy(statusDisplay, restBase, STATUS_SIZE); // } }
排查方向
- 内存访问合法性检查:确认
statusDisplay、workBase、restBase的内存定义(如数组大小)是否正确,STATUS_SIZE是否与实际位图的字节数完全一致。如果memcpy的长度或源/目标地址有误,会破坏内存结构,导致OLED驱动或其他模块崩溃。 - 竞态条件处理:
set_slave_pomodoro_state是RPC回调函数,可能在异步上下文执行;而oled_task_user运行在主循环中。如果两个函数同时操作statusDisplay缓冲区,会出现数据竞争,导致显示混乱。建议在回调中只标记更新需求,延迟到oled_task_user的主循环中执行缓冲区拷贝,或者添加简单的互斥锁保护。 - OLED显示清理:从板的
update_pomodoro_display中注释了oled_clear(),切换位图后旧的显示数据可能残留,导致画面错乱。尝试取消注释该函数,确保新位图能完全覆盖原有显示区域。 - RPC数据校验:检查
pomo_state类型的字节大小是否和in_buflen匹配,确保主板传输到从板的状态数据没有截断或错误,避免因state值错误触发错误的memcpy分支。 - 缓冲区内存属性:确认
statusDisplay是全局变量或静态变量,而非栈上的局部变量。如果是局部变量,初始化后可能被栈数据覆盖,后续操作会引发内存访问错误。
内容的提问来源于stack exchange,提问作者CaseyB
相关产品推荐
相关产品推荐

