1 /**
2 * @file lv_nuttx_entry.h
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_nuttx_entry.h"
10
11 #if LV_USE_NUTTX
12
13 #include <time.h>
14 #include <nuttx/tls.h>
15 #include <nuttx/clock.h>
16 #include <syslog.h>
17 #include <pthread.h>
18 #include "lv_nuttx_cache.h"
19 #include "lv_nuttx_image_cache.h"
20 #include "../../core/lv_global.h"
21 #include "lv_nuttx_profiler.h"
22
23 #include "../../../lvgl.h"
24
25 /*********************
26 * DEFINES
27 *********************/
28
29 #define nuttx_ctx_p (LV_GLOBAL_DEFAULT()->nuttx_ctx)
30
31 #if (LV_USE_FREETYPE || LV_USE_THORVG)
32 #define LV_NUTTX_MIN_STACK_SIZE (32 * 1024)
33 #else
34 #define LV_NUTTX_MIN_STACK_SIZE (8 * 1024)
35 #endif
36
37 /**********************
38 * TYPEDEFS
39 **********************/
40
41 /**********************
42 * STATIC PROTOTYPES
43 **********************/
44
45 static uint32_t millis(void);
46 #if LV_USE_LOG
47 static void syslog_print(lv_log_level_t level, const char * buf);
48 #endif
49 static void check_stack_size(void);
50
51 #ifdef CONFIG_LV_USE_NUTTX_LIBUV
52 static void lv_nuttx_uv_loop(lv_nuttx_result_t * result);
53 #endif
54
55 /**********************
56 * STATIC VARIABLES
57 **********************/
58
59 /**********************
60 * MACROS
61 **********************/
62
63 /**********************
64 * GLOBAL FUNCTIONS
65 **********************/
66
67 #if LV_ENABLE_GLOBAL_CUSTOM
68
69 static int lv_nuttx_tlskey = -1;
70
lv_global_free(void * data)71 static void lv_global_free(void * data)
72 {
73 if(data) {
74 free(data);
75 }
76 }
77
lv_global_default(void)78 lv_global_t * lv_global_default(void)
79 {
80 lv_global_t * data = NULL;
81
82 if(lv_nuttx_tlskey < 0) {
83 lv_nuttx_tlskey = task_tls_alloc(lv_global_free);
84 }
85
86 if(lv_nuttx_tlskey >= 0) {
87 data = (lv_global_t *)task_tls_get_value(lv_nuttx_tlskey);
88 if(data == NULL) {
89 data = (lv_global_t *)calloc(1, sizeof(lv_global_t));
90 task_tls_set_value(lv_nuttx_tlskey, (uintptr_t)data);
91 }
92 }
93 return data;
94 }
95 #endif
96
lv_nuttx_dsc_init(lv_nuttx_dsc_t * dsc)97 void lv_nuttx_dsc_init(lv_nuttx_dsc_t * dsc)
98 {
99 if(dsc == NULL)
100 return;
101
102 lv_memzero(dsc, sizeof(lv_nuttx_dsc_t));
103 dsc->fb_path = "/dev/fb0";
104 dsc->input_path = "/dev/input0";
105
106 #ifdef CONFIG_UINPUT_TOUCH
107 dsc->utouch_path = "/dev/utouch";
108 #endif
109 }
110
lv_nuttx_init(const lv_nuttx_dsc_t * dsc,lv_nuttx_result_t * result)111 void lv_nuttx_init(const lv_nuttx_dsc_t * dsc, lv_nuttx_result_t * result)
112 {
113 nuttx_ctx_p = lv_malloc_zeroed(sizeof(lv_nuttx_ctx_t));
114 LV_ASSERT_MALLOC(nuttx_ctx_p);
115
116 #if LV_USE_LOG
117 lv_log_register_print_cb(syslog_print);
118 #endif
119 lv_tick_set_cb(millis);
120
121 check_stack_size();
122
123 lv_nuttx_cache_init();
124
125 lv_nuttx_image_cache_init(LV_USE_NUTTX_INDEPENDENT_IMAGE_HEAP);
126
127 #if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN
128 lv_nuttx_profiler_init();
129 #endif
130
131 if(result) {
132 lv_memzero(result, sizeof(lv_nuttx_result_t));
133 }
134
135 #if !LV_USE_NUTTX_CUSTOM_INIT
136
137 if(dsc && dsc->fb_path) {
138 lv_display_t * disp = NULL;
139
140 #if LV_USE_NUTTX_LCD
141 disp = lv_nuttx_lcd_create(dsc->fb_path);
142 #else
143 disp = lv_nuttx_fbdev_create();
144 if(lv_nuttx_fbdev_set_file(disp, dsc->fb_path) != 0) {
145 lv_display_delete(disp);
146 disp = NULL;
147 }
148 #endif
149 if(result) {
150 result->disp = disp;
151 }
152 }
153
154 if(dsc) {
155 #if LV_USE_NUTTX_TOUCHSCREEN
156 if(dsc->input_path) {
157 lv_indev_t * indev = lv_nuttx_touchscreen_create(dsc->input_path);
158 if(result) {
159 result->indev = indev;
160 }
161 }
162
163 if(dsc->utouch_path) {
164 lv_indev_t * indev = lv_nuttx_touchscreen_create(dsc->utouch_path);
165 if(result) {
166 result->utouch_indev = indev;
167 }
168 }
169 #endif
170 }
171
172 #else
173
174 lv_nuttx_init_custom(dsc, result);
175 #endif
176 }
177
lv_nuttx_run(lv_nuttx_result_t * result)178 void lv_nuttx_run(lv_nuttx_result_t * result)
179 {
180 #ifdef CONFIG_LV_USE_NUTTX_LIBUV
181 lv_nuttx_uv_loop(&ui_loop, result);
182 #else
183 while(1) {
184 uint32_t idle;
185 idle = lv_timer_handler();
186
187 /* Minimum sleep of 1ms */
188 idle = idle ? idle : 1;
189 usleep(idle * 1000);
190 }
191 #endif
192 }
193
194 #ifdef CONFIG_SCHED_CPULOAD
195
lv_nuttx_get_idle(void)196 uint32_t lv_nuttx_get_idle(void)
197 {
198 struct cpuload_s cpuload;
199 int ret = clock_cpuload(0, &cpuload);
200 if(ret < 0) {
201 LV_LOG_WARN("clock_cpuload failed: %d", ret);
202 return 0;
203 }
204
205 uint32_t idle = cpuload.active * 100 / cpuload.total;
206 LV_LOG_TRACE("active = %" LV_PRIu32 ", total = %" LV_PRIu32,
207 cpuload.active, cpuload.total);
208
209 return idle;
210 }
211
212 #endif
213
lv_nuttx_deinit(lv_nuttx_result_t * result)214 void lv_nuttx_deinit(lv_nuttx_result_t * result)
215 {
216 #if !LV_USE_NUTTX_CUSTOM_INIT
217 if(result) {
218 if(result->disp) {
219 lv_display_delete(result->disp);
220 result->disp = NULL;
221 }
222
223 if(result->indev) {
224 lv_indev_delete(result->indev);
225 result->indev = NULL;
226 }
227
228 if(result->utouch_indev) {
229 lv_indev_delete(result->utouch_indev);
230 result->utouch_indev = NULL;
231 }
232 }
233 #else
234 lv_nuttx_deinit_custom(result);
235 #endif
236
237 if(nuttx_ctx_p) {
238 lv_nuttx_cache_deinit();
239 lv_nuttx_image_cache_deinit();
240
241 lv_free(nuttx_ctx_p);
242 nuttx_ctx_p = NULL;
243 }
244 }
245
246 /**********************
247 * STATIC FUNCTIONS
248 **********************/
249
millis(void)250 static uint32_t millis(void)
251 {
252 struct timespec ts;
253
254 clock_gettime(CLOCK_MONOTONIC, &ts);
255 uint32_t tick = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
256
257 return tick;
258 }
259
260 #if LV_USE_LOG
syslog_print(lv_log_level_t level,const char * buf)261 static void syslog_print(lv_log_level_t level, const char * buf)
262 {
263 static const int priority[LV_LOG_LEVEL_NUM] = {
264 LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, LOG_CRIT
265 };
266
267 syslog(priority[level], "[LVGL] %s", buf);
268 }
269 #endif
270
271 #ifdef CONFIG_LV_USE_NUTTX_LIBUV
lv_nuttx_uv_loop(lv_nuttx_result_t * result)272 static void lv_nuttx_uv_loop(lv_nuttx_result_t * result)
273 {
274 uv_loop_t loop;
275 lv_nuttx_uv_t uv_info;
276 void * data;
277
278 uv_loop_init(&loop);
279
280 lv_memzero(&uv_info, sizeof(uv_info));
281 uv_info.loop = &loop;
282 uv_info.disp = result->disp;
283 uv_info.indev = result->indev;
284 #ifdef CONFIG_UINPUT_TOUCH
285 uv_info.uindev = result->utouch_indev;
286 #endif
287
288 data = lv_nuttx_uv_init(&uv_info);
289 uv_run(loop, UV_RUN_DEFAULT);
290 lv_nuttx_uv_deinit(&data);
291 }
292 #endif
293
check_stack_size(void)294 static void check_stack_size(void)
295 {
296 pthread_t tid = pthread_self();
297 ssize_t stack_size = pthread_get_stacksize_np(tid);
298 LV_LOG_USER("tid: %d, Stack size : %zd", (int)tid, stack_size);
299
300 if(stack_size < LV_NUTTX_MIN_STACK_SIZE) {
301 LV_LOG_ERROR("Stack size is too small. Please increase it to %d bytes or more.",
302 LV_NUTTX_MIN_STACK_SIZE);
303 }
304 }
305
306 #endif /*LV_USE_NUTTX*/
307
308