mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
Enable Micropython gc (Garbage Collection) on lvgl. This is controlled by LV_ENABLE_GC macro defined in lv_conf.h. When enabled, lv_conf.h should also define LV_MEM_CUSTOM_REALLOC, LV_MEM_CUSTOM_GET_SIZE, LV_GC_INCLUDE and LV_GC_ROOT
This commit is contained in:
parent
d44a618169
commit
f5bd68fa77
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
**/*.o
|
||||
**/*.swp
|
||||
**/*.swo
|
||||
|
@ -19,6 +19,11 @@
|
||||
#include "../lv_misc/lv_ufs.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "../lv_misc/lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
# include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -43,11 +48,6 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_obj_t * def_scr = NULL;
|
||||
static lv_obj_t * act_scr = NULL;
|
||||
static lv_obj_t * top_layer = NULL;
|
||||
static lv_obj_t * sys_layer = NULL;
|
||||
static lv_ll_t scr_ll; /*Linked list of screens*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -62,6 +62,11 @@ static lv_ll_t scr_ll; /*Linked list of screens*/
|
||||
*/
|
||||
void lv_init(void)
|
||||
{
|
||||
LV_GC_ROOT(def_scr) = NULL;
|
||||
LV_GC_ROOT(act_scr) = NULL;
|
||||
LV_GC_ROOT(top_layer) = NULL;
|
||||
LV_GC_ROOT(sys_layer) = NULL;
|
||||
|
||||
LV_LOG_TRACE("lv_init started");
|
||||
|
||||
/*Initialize the lv_misc modules*/
|
||||
@ -85,19 +90,19 @@ void lv_init(void)
|
||||
lv_refr_init();
|
||||
|
||||
/*Create the default screen*/
|
||||
lv_ll_init(&scr_ll, sizeof(lv_obj_t));
|
||||
def_scr = lv_obj_create(NULL, NULL);
|
||||
lv_ll_init(&LV_GC_ROOT(scr_ll), sizeof(lv_obj_t));
|
||||
LV_GC_ROOT(def_scr) = lv_obj_create(NULL, NULL);
|
||||
|
||||
act_scr = def_scr;
|
||||
LV_GC_ROOT(act_scr) = LV_GC_ROOT(def_scr);
|
||||
|
||||
top_layer = lv_obj_create(NULL, NULL);
|
||||
lv_obj_set_style(top_layer, &lv_style_transp_fit);
|
||||
LV_GC_ROOT(top_layer) = lv_obj_create(NULL, NULL);
|
||||
lv_obj_set_style(LV_GC_ROOT(top_layer), &lv_style_transp_fit);
|
||||
|
||||
sys_layer = lv_obj_create(NULL, NULL);
|
||||
lv_obj_set_style(sys_layer, &lv_style_transp_fit);
|
||||
LV_GC_ROOT(sys_layer) = lv_obj_create(NULL, NULL);
|
||||
lv_obj_set_style(LV_GC_ROOT(sys_layer), &lv_style_transp_fit);
|
||||
|
||||
/*Refresh the screen*/
|
||||
lv_obj_invalidate(act_scr);
|
||||
lv_obj_invalidate(LV_GC_ROOT(act_scr));
|
||||
|
||||
#if LV_INDEV_READ_PERIOD != 0
|
||||
/*Init the input device handling*/
|
||||
@ -127,7 +132,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
|
||||
if(parent == NULL) {
|
||||
LV_LOG_TRACE("Screen create started");
|
||||
|
||||
new_obj = lv_ll_ins_head(&scr_ll);
|
||||
new_obj = lv_ll_ins_head(&LV_GC_ROOT(scr_ll));
|
||||
lv_mem_assert(new_obj);
|
||||
if(new_obj == NULL) return NULL;
|
||||
|
||||
@ -350,7 +355,7 @@ lv_res_t lv_obj_del(lv_obj_t * obj)
|
||||
/*Remove the object from parent's children list*/
|
||||
lv_obj_t * par = lv_obj_get_parent(obj);
|
||||
if(par == NULL) { /*It is a screen*/
|
||||
lv_ll_rem(&scr_ll, obj);
|
||||
lv_ll_rem(&LV_GC_ROOT(scr_ll), obj);
|
||||
} else {
|
||||
lv_ll_rem(&(par->child_ll), obj);
|
||||
}
|
||||
@ -406,7 +411,7 @@ void lv_obj_invalidate(const lv_obj_t * obj)
|
||||
{
|
||||
if(lv_obj_get_hidden(obj)) return;
|
||||
|
||||
/*Invalidate the object only if it belongs to the 'act_scr'*/
|
||||
/*Invalidate the object only if it belongs to the 'LV_GC_ROOT(act_scr)'*/
|
||||
lv_obj_t * obj_scr = lv_obj_get_screen(obj);
|
||||
if(obj_scr == lv_scr_act() ||
|
||||
obj_scr == lv_layer_top() ||
|
||||
@ -451,9 +456,9 @@ void lv_obj_invalidate(const lv_obj_t * obj)
|
||||
*/
|
||||
void lv_scr_load(lv_obj_t * scr)
|
||||
{
|
||||
act_scr = scr;
|
||||
LV_GC_ROOT(act_scr) = scr;
|
||||
|
||||
lv_obj_invalidate(act_scr);
|
||||
lv_obj_invalidate(LV_GC_ROOT(act_scr));
|
||||
}
|
||||
|
||||
/*--------------------
|
||||
@ -1000,7 +1005,7 @@ void lv_obj_refresh_style(lv_obj_t * obj)
|
||||
void lv_obj_report_style_mod(lv_style_t * style)
|
||||
{
|
||||
lv_obj_t * i;
|
||||
LL_READ(scr_ll, i) {
|
||||
LL_READ(LV_GC_ROOT(scr_ll), i) {
|
||||
if(i->style_p == style || style == NULL) {
|
||||
lv_obj_refresh_style(i);
|
||||
}
|
||||
@ -1297,7 +1302,7 @@ void lv_obj_animate(lv_obj_t * obj, lv_anim_builtin_t type, uint16_t time, uint1
|
||||
*/
|
||||
lv_obj_t * lv_scr_act(void)
|
||||
{
|
||||
return act_scr;
|
||||
return LV_GC_ROOT(act_scr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1306,7 +1311,7 @@ lv_obj_t * lv_scr_act(void)
|
||||
*/
|
||||
lv_obj_t * lv_layer_top(void)
|
||||
{
|
||||
return top_layer;
|
||||
return LV_GC_ROOT(top_layer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1316,7 +1321,7 @@ lv_obj_t * lv_layer_top(void)
|
||||
*/
|
||||
lv_obj_t * lv_layer_sys(void)
|
||||
{
|
||||
return sys_layer;
|
||||
return LV_GC_ROOT(sys_layer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,12 @@
|
||||
#include "../lv_hal/lv_hal_disp.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_misc/lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
# include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -30,7 +36,6 @@
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_disp_t * disp_list = NULL;
|
||||
static lv_disp_t * active;
|
||||
|
||||
/**********************
|
||||
@ -49,6 +54,7 @@ static lv_disp_t * active;
|
||||
*/
|
||||
void lv_disp_drv_init(lv_disp_drv_t * driver)
|
||||
{
|
||||
LV_GC_ROOT(disp_list) = NULL;
|
||||
driver->disp_fill = NULL;
|
||||
driver->disp_map = NULL;
|
||||
driver->disp_flush = NULL;
|
||||
@ -81,12 +87,12 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver)
|
||||
node->next = NULL;
|
||||
|
||||
/* Set first display as active by default */
|
||||
if(disp_list == NULL) {
|
||||
disp_list = node;
|
||||
if(LV_GC_ROOT(disp_list) == NULL) {
|
||||
LV_GC_ROOT(disp_list) = node;
|
||||
active = node;
|
||||
lv_obj_invalidate(lv_scr_act());
|
||||
} else {
|
||||
disp_list->next = node;
|
||||
((lv_disp_t*)LV_GC_ROOT(disp_list))->next = node;
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -120,10 +126,10 @@ lv_disp_t * lv_disp_get_active(void)
|
||||
lv_disp_t * lv_disp_next(lv_disp_t * disp)
|
||||
{
|
||||
if(disp == NULL) {
|
||||
return disp_list;
|
||||
return LV_GC_ROOT(disp_list);
|
||||
} else {
|
||||
if(disp_list->next == NULL) return NULL;
|
||||
else return disp_list->next;
|
||||
if(((lv_disp_t*)LV_GC_ROOT(disp_list))->next == NULL) return NULL;
|
||||
else return ((lv_disp_t*)LV_GC_ROOT(disp_list))->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,12 @@
|
||||
*********************/
|
||||
#include "../lv_hal/lv_hal_indev.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
#include "../lv_misc/lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
# include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -22,7 +28,6 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_indev_t * indev_list = NULL;
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -44,6 +49,7 @@ static lv_indev_t * indev_list = NULL;
|
||||
*/
|
||||
void lv_indev_drv_init(lv_indev_drv_t * driver)
|
||||
{
|
||||
LV_GC_ROOT(indev_list) = NULL;
|
||||
driver->read = NULL;
|
||||
driver->type = LV_INDEV_TYPE_NONE;
|
||||
driver->user_data = NULL;
|
||||
@ -70,10 +76,10 @@ lv_indev_t * lv_indev_drv_register(lv_indev_drv_t * driver)
|
||||
node->group = NULL;
|
||||
node->btn_points = NULL;
|
||||
|
||||
if(indev_list == NULL) {
|
||||
indev_list = node;
|
||||
if(LV_GC_ROOT(indev_list) == NULL) {
|
||||
LV_GC_ROOT(indev_list) = node;
|
||||
} else {
|
||||
lv_indev_t * last = indev_list;
|
||||
lv_indev_t * last = LV_GC_ROOT(indev_list);
|
||||
while(last->next)
|
||||
last = last->next;
|
||||
|
||||
@ -92,7 +98,7 @@ lv_indev_t * lv_indev_next(lv_indev_t * indev)
|
||||
{
|
||||
|
||||
if(indev == NULL) {
|
||||
return indev_list;
|
||||
return LV_GC_ROOT(indev_list);
|
||||
} else {
|
||||
if(indev->next == NULL) return NULL;
|
||||
else return indev->next;
|
||||
|
@ -14,6 +14,12 @@
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "lv_task.h"
|
||||
#include "lv_math.h"
|
||||
#include "lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
# include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -34,7 +40,6 @@ static bool anim_ready_handler(lv_anim_t * a);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_ll_t anim_ll;
|
||||
static uint32_t last_task_run;
|
||||
static bool anim_list_changed;
|
||||
|
||||
@ -51,7 +56,7 @@ static bool anim_list_changed;
|
||||
*/
|
||||
void lv_anim_init(void)
|
||||
{
|
||||
lv_ll_init(&anim_ll, sizeof(lv_anim_t));
|
||||
lv_ll_init(&LV_GC_ROOT(anim_ll), sizeof(lv_anim_t));
|
||||
last_task_run = lv_tick_get();
|
||||
lv_task_create(anim_task, LV_REFR_PERIOD, LV_TASK_PRIO_MID, NULL);
|
||||
}
|
||||
@ -67,7 +72,7 @@ void lv_anim_create(lv_anim_t * anim_p)
|
||||
if(anim_p->fp != NULL) lv_anim_del(anim_p->var, anim_p->fp); /*fp == NULL would delete all animations of var*/
|
||||
|
||||
/*Add the new animation to the animation linked list*/
|
||||
lv_anim_t * new_anim = lv_ll_ins_head(&anim_ll);
|
||||
lv_anim_t * new_anim = lv_ll_ins_head(&LV_GC_ROOT(anim_ll));
|
||||
lv_mem_assert(new_anim);
|
||||
if(new_anim == NULL) return;
|
||||
|
||||
@ -97,13 +102,13 @@ bool lv_anim_del(void * var, lv_anim_fp_t fp)
|
||||
lv_anim_t * a;
|
||||
lv_anim_t * a_next;
|
||||
bool del = false;
|
||||
a = lv_ll_get_head(&anim_ll);
|
||||
a = lv_ll_get_head(&LV_GC_ROOT(anim_ll));
|
||||
while(a != NULL) {
|
||||
/*'a' might be deleted, so get the next object while 'a' is valid*/
|
||||
a_next = lv_ll_get_next(&anim_ll, a);
|
||||
a_next = lv_ll_get_next(&LV_GC_ROOT(anim_ll), a);
|
||||
|
||||
if(a->var == var && (a->fp == fp || fp == NULL)) {
|
||||
lv_ll_rem(&anim_ll, a);
|
||||
lv_ll_rem(&LV_GC_ROOT(anim_ll), a);
|
||||
lv_mem_free(a);
|
||||
anim_list_changed = true; /*Read by `anim_task`. It need to know if a delete occurred in the linked list*/
|
||||
del = true;
|
||||
@ -352,12 +357,12 @@ static void anim_task(void * param)
|
||||
(void)param;
|
||||
|
||||
lv_anim_t * a;
|
||||
LL_READ(anim_ll, a) {
|
||||
LL_READ(LV_GC_ROOT(anim_ll), a) {
|
||||
a->has_run = 0;
|
||||
}
|
||||
|
||||
uint32_t elaps = lv_tick_elaps(last_task_run);
|
||||
a = lv_ll_get_head(&anim_ll);
|
||||
a = lv_ll_get_head(&LV_GC_ROOT(anim_ll));
|
||||
|
||||
while(a != NULL) {
|
||||
/*It can be set by `lv_anim_del()` typically in `end_cb`. If set then an animation delete happened in `anim_ready_handler`
|
||||
@ -385,8 +390,8 @@ static void anim_task(void * param)
|
||||
|
||||
/* If the linked list changed due to anim. delete then it's not safe to continue
|
||||
* the reading of the list from here -> start from the head*/
|
||||
if(anim_list_changed) a = lv_ll_get_head(&anim_ll);
|
||||
else a = lv_ll_get_next(&anim_ll, a);
|
||||
if(anim_list_changed) a = lv_ll_get_head(&LV_GC_ROOT(anim_ll));
|
||||
else a = lv_ll_get_next(&LV_GC_ROOT(anim_ll), a);
|
||||
}
|
||||
|
||||
last_task_run = lv_tick_get();
|
||||
@ -396,7 +401,7 @@ static void anim_task(void * param)
|
||||
* Called when an animation is ready to do the necessary thinks
|
||||
* e.g. repeat, play back, delete etc.
|
||||
* @param a pointer to an animation descriptor
|
||||
* @return true: animation delete occurred nnd the `anim_ll` has changed
|
||||
* @return true: animation delete occurred nnd the `LV_GC_ROOT(anim_ll)` has changed
|
||||
* */
|
||||
static bool anim_ready_handler(lv_anim_t * a)
|
||||
{
|
||||
@ -408,7 +413,7 @@ static bool anim_ready_handler(lv_anim_t * a)
|
||||
(a->repeat == 0 && a->playback == 1 && a->playback_now == 1)) {
|
||||
void (*cb)(void *) = a->end_cb;
|
||||
void * p = a->var;
|
||||
lv_ll_rem(&anim_ll, a);
|
||||
lv_ll_rem(&LV_GC_ROOT(anim_ll), a);
|
||||
lv_mem_free(a);
|
||||
anim_list_changed = true;
|
||||
|
||||
|
@ -11,6 +11,11 @@
|
||||
|
||||
#include "lv_ll.h"
|
||||
#include <string.h>
|
||||
#include "lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
# include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -30,7 +35,6 @@ static lv_fs_drv_t * lv_fs_get_drv(char letter);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_ll_t drv_ll;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -45,7 +49,7 @@ static lv_ll_t drv_ll;
|
||||
*/
|
||||
void lv_fs_init(void)
|
||||
{
|
||||
lv_ll_init(&drv_ll, sizeof(lv_fs_drv_t));
|
||||
lv_ll_init(&LV_GC_ROOT(drv_ll), sizeof(lv_fs_drv_t));
|
||||
}
|
||||
|
||||
|
||||
@ -449,7 +453,7 @@ void lv_fs_add_drv(lv_fs_drv_t * drv_p)
|
||||
{
|
||||
/*Save the new driver*/
|
||||
lv_fs_drv_t * new_drv;
|
||||
new_drv = lv_ll_ins_head(&drv_ll);
|
||||
new_drv = lv_ll_ins_head(&LV_GC_ROOT(drv_ll));
|
||||
lv_mem_assert(new_drv);
|
||||
if(new_drv == NULL) return;
|
||||
|
||||
@ -466,7 +470,7 @@ char * lv_fs_get_letters(char * buf)
|
||||
lv_fs_drv_t * drv;
|
||||
uint8_t i = 0;
|
||||
|
||||
LL_READ(drv_ll, drv) {
|
||||
LL_READ(LV_GC_ROOT(drv_ll), drv) {
|
||||
buf[i] = drv->letter;
|
||||
i++;
|
||||
}
|
||||
@ -589,7 +593,7 @@ static lv_fs_drv_t * lv_fs_get_drv(char letter)
|
||||
{
|
||||
lv_fs_drv_t * drv;
|
||||
|
||||
LL_READ(drv_ll, drv) {
|
||||
LL_READ(LV_GC_ROOT(drv_ll), drv) {
|
||||
if(drv->letter == letter) {
|
||||
return drv;
|
||||
}
|
||||
|
40
lv_misc/lv_gc.c
Normal file
40
lv_misc/lv_gc.c
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file lv_gc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if (!defined(LV_ENABLE_GC)) || LV_ENABLE_GC == 0
|
||||
LV_ROOTS
|
||||
#endif /* LV_ENABLE_GC */
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
77
lv_misc/lv_gc.h
Normal file
77
lv_misc/lv_gc.h
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @file lv_gc.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GC_H
|
||||
#define LV_GC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "lv_mem.h"
|
||||
#include "lv_ll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_GC_ROOTS(prefix) \
|
||||
prefix lv_ll_t lv_task_ll; /*Linked list to store the lv_tasks*/ \
|
||||
prefix lv_ll_t scr_ll; /*Linked list of screens*/ \
|
||||
prefix lv_ll_t drv_ll;\
|
||||
prefix lv_ll_t file_ll;\
|
||||
prefix lv_ll_t anim_ll;\
|
||||
prefix void * def_scr;\
|
||||
prefix void * act_scr;\
|
||||
prefix void * top_layer;\
|
||||
prefix void * sys_layer;\
|
||||
prefix void * task_act;\
|
||||
prefix void * indev_list;\
|
||||
prefix void * disp_list;\
|
||||
|
||||
|
||||
#define LV_NO_PREFIX
|
||||
#define LV_ROOTS LV_GC_ROOTS(LV_NO_PREFIX)
|
||||
|
||||
#if LV_ENABLE_GC == 1
|
||||
# if LV_MEM_CUSTOM != 1
|
||||
# error "GC requires CUSTOM_MEM"
|
||||
# endif /* LV_MEM_CUSTOM */
|
||||
#else /* LV_ENABLE_GC */
|
||||
# define LV_GC_ROOT(x) x
|
||||
LV_GC_ROOTS(extern)
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_GC_H*/
|
@ -31,7 +31,7 @@
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
#if LV_ENABLE_GC == 0 /*gc custom allocations must not include header*/
|
||||
/*The size of this union must be 4 bytes (uint32_t)*/
|
||||
typedef union {
|
||||
struct {
|
||||
@ -45,7 +45,7 @@ typedef struct {
|
||||
lv_mem_header_t header;
|
||||
uint8_t first_data; /*First data byte in the allocated data (Just for easily create a pointer)*/
|
||||
} lv_mem_ent_t;
|
||||
|
||||
#endif
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
@ -133,6 +133,9 @@ void * lv_mem_alloc(uint32_t size)
|
||||
#endif
|
||||
|
||||
#else /*Use custom, user defined malloc function*/
|
||||
#if LV_ENABLE_GC == 1 /*gc must not include header*/
|
||||
alloc = LV_MEM_CUSTOM_ALLOC(size);
|
||||
#else
|
||||
/*Allocate a header too to store the size*/
|
||||
alloc = LV_MEM_CUSTOM_ALLOC(size + sizeof(lv_mem_header_t));
|
||||
if(alloc != NULL) {
|
||||
@ -140,6 +143,7 @@ void * lv_mem_alloc(uint32_t size)
|
||||
((lv_mem_ent_t *) alloc)->header.used = 1;
|
||||
alloc = &((lv_mem_ent_t *) alloc)->first_data;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(alloc == NULL) LV_LOG_WARN("Couldn't allocate memory");
|
||||
@ -161,9 +165,11 @@ void lv_mem_free(const void * data)
|
||||
memset((void *)data, 0xbb, lv_mem_get_size(data));
|
||||
#endif
|
||||
|
||||
#if LV_ENABLE_GC==0
|
||||
/*e points to the header*/
|
||||
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *) data - sizeof(lv_mem_header_t));
|
||||
e->header.used = 0;
|
||||
#endif
|
||||
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
#if LV_MEM_AUTO_DEFRAG
|
||||
@ -181,7 +187,11 @@ void lv_mem_free(const void * data)
|
||||
}
|
||||
#endif
|
||||
#else /*Use custom, user defined free function*/
|
||||
#if LV_ENABLE_GC==0
|
||||
LV_MEM_CUSTOM_FREE(e);
|
||||
#else
|
||||
LV_MEM_CUSTOM_FREE((void*)data);
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -194,6 +204,10 @@ void lv_mem_free(const void * data)
|
||||
*/
|
||||
void * lv_mem_realloc(void * data_p, uint32_t new_size)
|
||||
{
|
||||
#if LV_ENABLE_GC==1
|
||||
return LV_MEM_CUSTOM_REALLOC(data_p, new_size);
|
||||
#else
|
||||
|
||||
/*data_p could be previously freed pointer (in this case it is invalid)*/
|
||||
if(data_p != NULL) {
|
||||
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *) data_p - sizeof(lv_mem_header_t));
|
||||
@ -230,6 +244,7 @@ void * lv_mem_realloc(void * data_p, uint32_t new_size)
|
||||
if(new_p == NULL) LV_LOG_WARN("Couldn't allocate memory");
|
||||
|
||||
return new_p;
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -316,12 +331,16 @@ void lv_mem_monitor(lv_mem_monitor_t * mon_p)
|
||||
*/
|
||||
uint32_t lv_mem_get_size(const void * data)
|
||||
{
|
||||
#if LV_ENABLE_GC==1
|
||||
return LV_MEM_CUSTOM_GET_SIZE(data);
|
||||
#else
|
||||
if(data == NULL) return 0;
|
||||
if(data == &zero_mem) return 0;
|
||||
|
||||
lv_mem_ent_t * e = (lv_mem_ent_t *)((uint8_t *) data - sizeof(lv_mem_header_t));
|
||||
|
||||
return e->header.d_size;
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
}
|
||||
|
||||
/**********************
|
||||
|
@ -10,6 +10,11 @@
|
||||
#include <stddef.h>
|
||||
#include "lv_task.h"
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
# include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -28,12 +33,10 @@ static bool lv_task_exec(lv_task_t * lv_task_p);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_ll_t lv_task_ll; /*Linked list to store the lv_tasks*/
|
||||
static bool lv_task_run = false;
|
||||
static uint8_t idle_last = 0;
|
||||
static bool task_deleted;
|
||||
static bool task_created;
|
||||
static lv_task_t * task_act;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -48,7 +51,7 @@ static lv_task_t * task_act;
|
||||
*/
|
||||
void lv_task_init(void)
|
||||
{
|
||||
lv_ll_init(&lv_task_ll, sizeof(lv_task_t));
|
||||
lv_ll_init(&LV_GC_ROOT(lv_task_ll), sizeof(lv_task_t));
|
||||
|
||||
/*Initially enable the lv_task handling*/
|
||||
lv_task_enable(true);
|
||||
@ -84,33 +87,33 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
end_flag = true;
|
||||
task_deleted = false;
|
||||
task_created = false;
|
||||
task_act = lv_ll_get_head(&lv_task_ll);
|
||||
while(task_act) {
|
||||
LV_GC_ROOT(task_act) = lv_ll_get_head(&LV_GC_ROOT(lv_task_ll));
|
||||
while(LV_GC_ROOT(task_act)) {
|
||||
/* The task might be deleted if it runs only once ('once = 1')
|
||||
* So get next element until the current is surely valid*/
|
||||
next = lv_ll_get_next(&lv_task_ll, task_act);
|
||||
next = lv_ll_get_next(&LV_GC_ROOT(lv_task_ll), LV_GC_ROOT(task_act));
|
||||
|
||||
/*We reach priority of the turned off task. There is nothing more to do.*/
|
||||
if(task_act->prio == LV_TASK_PRIO_OFF) {
|
||||
if(((lv_task_t *)LV_GC_ROOT(task_act))->prio == LV_TASK_PRIO_OFF) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*Here is the interrupter task. Don't execute it again.*/
|
||||
if(task_act == task_interrupter) {
|
||||
if(LV_GC_ROOT(task_act) == task_interrupter) {
|
||||
task_interrupter = NULL; /*From this point only task after the interrupter comes, so the interrupter is not interesting anymore*/
|
||||
task_act = next;
|
||||
LV_GC_ROOT(task_act) = next;
|
||||
continue; /*Load the next task*/
|
||||
}
|
||||
|
||||
/*Just try to run the tasks with highest priority.*/
|
||||
if(task_act->prio == LV_TASK_PRIO_HIGHEST) {
|
||||
lv_task_exec(task_act);
|
||||
if(((lv_task_t *)LV_GC_ROOT(task_act))->prio == LV_TASK_PRIO_HIGHEST) {
|
||||
lv_task_exec(LV_GC_ROOT(task_act));
|
||||
}
|
||||
/*Tasks with higher priority then the interrupted shall be run in every case*/
|
||||
else if(task_interrupter) {
|
||||
if(task_act->prio > task_interrupter->prio) {
|
||||
if(lv_task_exec(task_act)) {
|
||||
task_interrupter = task_act; /*Check all tasks again from the highest priority */
|
||||
if(((lv_task_t *)LV_GC_ROOT(task_act))->prio > task_interrupter->prio) {
|
||||
if(lv_task_exec(LV_GC_ROOT(task_act))) {
|
||||
task_interrupter = LV_GC_ROOT(task_act); /*Check all tasks again from the highest priority */
|
||||
end_flag = false;
|
||||
break;
|
||||
}
|
||||
@ -119,8 +122,8 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
/* It is no interrupter task or we already reached it earlier.
|
||||
* Just run the remaining tasks*/
|
||||
else {
|
||||
if(lv_task_exec(task_act)) {
|
||||
task_interrupter = task_act; /*Check all tasks again from the highest priority */
|
||||
if(lv_task_exec(LV_GC_ROOT(task_act))) {
|
||||
task_interrupter = LV_GC_ROOT(task_act); /*Check all tasks again from the highest priority */
|
||||
end_flag = false;
|
||||
break;
|
||||
}
|
||||
@ -129,7 +132,7 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
|
||||
if(task_deleted) break; /*If a task was deleted then this or the next item might be corrupted*/
|
||||
if(task_created) break; /*If a task was deleted then this or the next item might be corrupted*/
|
||||
|
||||
task_act = next; /*Load the next task*/
|
||||
LV_GC_ROOT(task_act) = next; /*Load the next task*/
|
||||
}
|
||||
} while(!end_flag);
|
||||
|
||||
@ -164,24 +167,24 @@ lv_task_t * lv_task_create(void (*task)(void *), uint32_t period, lv_task_prio_t
|
||||
lv_task_t * tmp;
|
||||
|
||||
/*Create task lists in order of priority from high to low*/
|
||||
tmp = lv_ll_get_head(&lv_task_ll);
|
||||
tmp = lv_ll_get_head(&LV_GC_ROOT(lv_task_ll));
|
||||
if(NULL == tmp) { /*First task*/
|
||||
new_lv_task = lv_ll_ins_head(&lv_task_ll);
|
||||
new_lv_task = lv_ll_ins_head(&LV_GC_ROOT(lv_task_ll));
|
||||
lv_mem_assert(new_lv_task);
|
||||
if(new_lv_task == NULL) return NULL;
|
||||
} else {
|
||||
do {
|
||||
if(tmp->prio <= prio) {
|
||||
new_lv_task = lv_ll_ins_prev(&lv_task_ll, tmp);
|
||||
new_lv_task = lv_ll_ins_prev(&LV_GC_ROOT(lv_task_ll), tmp);
|
||||
lv_mem_assert(new_lv_task);
|
||||
if(new_lv_task == NULL) return NULL;
|
||||
break;
|
||||
}
|
||||
tmp = lv_ll_get_next(&lv_task_ll, tmp);
|
||||
tmp = lv_ll_get_next(&LV_GC_ROOT(lv_task_ll), tmp);
|
||||
} while(tmp != NULL);
|
||||
|
||||
if(tmp == NULL) { /*Only too high priority tasks were found*/
|
||||
new_lv_task = lv_ll_ins_tail(&lv_task_ll);
|
||||
new_lv_task = lv_ll_ins_tail(&LV_GC_ROOT(lv_task_ll));
|
||||
lv_mem_assert(new_lv_task);
|
||||
if(new_lv_task == NULL) return NULL;
|
||||
}
|
||||
@ -205,11 +208,11 @@ lv_task_t * lv_task_create(void (*task)(void *), uint32_t period, lv_task_prio_t
|
||||
*/
|
||||
void lv_task_del(lv_task_t * lv_task_p)
|
||||
{
|
||||
lv_ll_rem(&lv_task_ll, lv_task_p);
|
||||
lv_ll_rem(&LV_GC_ROOT(lv_task_ll), lv_task_p);
|
||||
|
||||
lv_mem_free(lv_task_p);
|
||||
|
||||
if(task_act == lv_task_p) task_deleted = true; /*The active task was deleted*/
|
||||
if(LV_GC_ROOT(task_act) == lv_task_p) task_deleted = true; /*The active task was deleted*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,16 +224,16 @@ void lv_task_set_prio(lv_task_t * lv_task_p, lv_task_prio_t prio)
|
||||
{
|
||||
/*Find the tasks with new priority*/
|
||||
lv_task_t * i;
|
||||
LL_READ(lv_task_ll, i) {
|
||||
LL_READ(LV_GC_ROOT(lv_task_ll), i) {
|
||||
if(i->prio <= prio) {
|
||||
if(i != lv_task_p) lv_ll_move_before(&lv_task_ll, lv_task_p, i);
|
||||
if(i != lv_task_p) lv_ll_move_before(&LV_GC_ROOT(lv_task_ll), lv_task_p, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*There was no such a low priority so far then add the node to the tail*/
|
||||
if(i == NULL) {
|
||||
lv_ll_move_before(&lv_task_ll, lv_task_p, NULL);
|
||||
lv_ll_move_before(&LV_GC_ROOT(lv_task_ll), lv_task_p, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,6 +14,12 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "lv_gc.h"
|
||||
|
||||
#if defined(LV_GC_INCLUDE)
|
||||
# include LV_GC_INCLUDE
|
||||
#endif /* LV_ENABLE_GC */
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -32,7 +38,6 @@ static lv_ufs_ent_t * lv_ufs_ent_new(const char * fn);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_ll_t file_ll;
|
||||
static bool inited = false;
|
||||
|
||||
/**********************
|
||||
@ -48,7 +53,7 @@ static bool inited = false;
|
||||
*/
|
||||
void lv_ufs_init(void)
|
||||
{
|
||||
lv_ll_init(&file_ll, sizeof(lv_ufs_ent_t));
|
||||
lv_ll_init(&LV_GC_ROOT(file_ll), sizeof(lv_ufs_ent_t));
|
||||
|
||||
lv_fs_drv_t ufs_drv;
|
||||
memset(&ufs_drv, 0, sizeof(lv_fs_drv_t)); /*Initialization*/
|
||||
@ -202,7 +207,7 @@ lv_fs_res_t lv_ufs_remove(const char * fn)
|
||||
/*Can not be deleted is opened*/
|
||||
if(ent->oc != 0) return LV_FS_RES_DENIED;
|
||||
|
||||
lv_ll_rem(&file_ll, ent);
|
||||
lv_ll_rem(&LV_GC_ROOT(file_ll), ent);
|
||||
lv_mem_free(ent->fn_d);
|
||||
ent->fn_d = NULL;
|
||||
if(ent->const_data == 0) {
|
||||
@ -412,9 +417,9 @@ lv_fs_res_t lv_ufs_dir_read(void * dir_p, char * fn)
|
||||
lv_ufs_dir_t * ufs_dir_p = dir_p;
|
||||
|
||||
if(ufs_dir_p->last_ent == NULL) {
|
||||
ufs_dir_p->last_ent = lv_ll_get_head(&file_ll);
|
||||
ufs_dir_p->last_ent = lv_ll_get_head(&LV_GC_ROOT(file_ll));
|
||||
} else {
|
||||
ufs_dir_p->last_ent = lv_ll_get_next(&file_ll, ufs_dir_p->last_ent);
|
||||
ufs_dir_p->last_ent = lv_ll_get_next(&LV_GC_ROOT(file_ll), ufs_dir_p->last_ent);
|
||||
}
|
||||
|
||||
if(ufs_dir_p->last_ent != NULL) {
|
||||
@ -472,7 +477,7 @@ static lv_ufs_ent_t * lv_ufs_ent_get(const char * fn)
|
||||
{
|
||||
lv_ufs_ent_t * fp;
|
||||
|
||||
LL_READ(file_ll, fp) {
|
||||
LL_READ(LV_GC_ROOT(file_ll), fp) {
|
||||
if(strcmp(fp->fn_d, fn) == 0) {
|
||||
return fp;
|
||||
}
|
||||
@ -490,7 +495,7 @@ static lv_ufs_ent_t * lv_ufs_ent_get(const char * fn)
|
||||
static lv_ufs_ent_t * lv_ufs_ent_new(const char * fn)
|
||||
{
|
||||
lv_ufs_ent_t * new_ent = NULL;
|
||||
new_ent = lv_ll_ins_head(&file_ll); /*Create a new file*/
|
||||
new_ent = lv_ll_ins_head(&LV_GC_ROOT(file_ll)); /*Create a new file*/
|
||||
lv_mem_assert(new_ent);
|
||||
if(new_ent == NULL) return NULL;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user