文章目录
1. 引言
本本探究下LVGL使用的数据结构:链表, LVGL使用的链表是带链表头,尾的双列表。
2 数据结构定义
2.1 链表节点的定义
typedef struct {
uint32_t n_size;
lv_ll_node_t * head;
lv_ll_node_t * tail;
} lv_ll_t;
2.2 链表节点的内存分布图
注意: 链表节点的数据结构定义和内存分布是不对应的(64位cpu时)3. LVGL链表结构示意图
4. 链表的基本操作
5. 常用链表数据
LVGL在头文件lv_gc.h, 定义一组跟链表全局变量,用于进行各种类型数据链表的动态管理。
#define LV_ITERATE_ROOTS(f) \
LV_DISPATCH(f, lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \
LV_DISPATCH(f, lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \
LV_DISPATCH(f, lv_ll_t, _lv_indev_ll) /*Linked list of input device*/ \
LV_DISPATCH(f, lv_ll_t, _lv_fsdrv_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_anim_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_group_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_img_decoder_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_obj_style_trans_ll) \
LV_DISPATCH(f, lv_layout_dsc_t *, _lv_layout_list) \
LV_DISPATCH_COND(f, _lv_img_cache_entry_t*, _lv_img_cache_array, LV_IMG_CACHE_DEF, 1) \
LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \
LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \
LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \
LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \
LV_DISPATCH(f, void * , _lv_theme_default_styles) \
LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1)
6. LVGL 常用数据链表
LVGL定义了一组全局链表,用于对一些常用的数据进行动态管理,这个常用的链表咋lvgl初始化时进行初始化,
具体如下。
7. LVGL链表使用的C技巧
如前所述,LVGL链表节点的结构体所占内容和节点实际所占内存(64位cpu)是不一致的,因此定位成员变量head, tail内存地址
需特殊处理。
LVGL 定义了3个宏来用作成员变量偏移计算:
#define LL_NODE_META_SIZE (sizeof(lv_ll_node_t *) + sizeof(lv_ll_node_t *))
#define LL_PREV_P_OFFSET(ll_p) (ll_p->n_size)
#define LL_NEXT_P_OFFSET(ll_p) (ll_p->n_size + sizeof(lv_ll_node_t *))
成员实际地址 = 成员结构体内偏移地址+节点其实地址
static void node_set_prev(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * prev)
{
if(act == NULL) return; /*Can't set the prev node of `NULL`*/
uint8_t * act8 = (uint8_t *)act;
act8 += LL_PREV_P_OFFSET(ll_p); //计算成员head的 实际地址
lv_ll_node_t ** act_node_p = (lv_ll_node_t **) act8;
lv_ll_node_t ** prev_node_p = (lv_ll_node_t **) &prev;
*act_node_p = *prev_node_p;
}
8. 总结
本文总结了链表数据结构在LVGL的应用,也讨论了在链表数据结构应用时使用的一些C语言技巧。了解LVGL的链表数据结构,对我们加深理解LVGL的代码执行,底层数据(对象)如何动态管理很有帮助。
9. 关注我
创作不易,如帮助请点赞,关注。