luat_lib_rtos.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. @module rtos
  3. @summary RTOS底层操作库
  4. @version 1.0
  5. @date 2020.03.30
  6. @tag LUAT_CONF_BSP
  7. */
  8. #include "luat_base.h"
  9. #include "luat_sys.h"
  10. #include "luat_msgbus.h"
  11. #include "luat_timer.h"
  12. #include "luat_malloc.h"
  13. #define LUAT_LOG_TAG "rtos"
  14. #include "luat_log.h"
  15. static uint16_t autogc_config = 100; // TODO 通过API可配置
  16. static uint16_t autogc_counter = 0;
  17. /*
  18. 接受并处理底层消息队列.
  19. @api rtos.receive(timeout)
  20. @int 超时时长,通常是-1,永久等待
  21. @return msgid 如果是定时器消息,会返回定时器消息id及附加信息, 其他消息由底层决定,不向lua层进行任何保证.
  22. -- 本方法通过sys.run()调用, 普通用户不要使用
  23. rtos.receive(-1)
  24. */
  25. static int l_rtos_receive(lua_State *L) {
  26. rtos_msg_t msg = {0};
  27. int re = {0};
  28. size_t total = 0;
  29. size_t used = 0;
  30. size_t max_used = 0;
  31. if (autogc_config > 0) {
  32. if (autogc_counter >= autogc_config) {
  33. autogc_counter = 0;
  34. luat_meminfo_luavm(&total, &used, &max_used);
  35. if ( (used * 100) >= (total * 90))
  36. {
  37. //LLOGD("luavm ram too high! used %d, total %d. Trigger Force-GC", used, total);
  38. // 需要执行2次, 因为userdata在第二次才会被回收
  39. lua_gc(L, LUA_GCCOLLECT, 0);
  40. lua_gc(L, LUA_GCCOLLECT, 0);
  41. }
  42. }
  43. else {
  44. autogc_counter ++;
  45. }
  46. }
  47. re = luat_msgbus_get(&msg, luaL_checkinteger(L, 1));
  48. if (!re) {
  49. //LLOGD("rtos_msg got, invoke it handler=%08X", msg.handler);
  50. lua_pushlightuserdata(L, (void*)(&msg));
  51. return msg.handler(L, msg.ptr);
  52. }
  53. else {
  54. //LLOGD("rtos_msg get timeout");
  55. lua_pushinteger(L, -1);
  56. return 1;
  57. }
  58. }
  59. //------------------------------------------------------------------
  60. static int l_timer_handler(lua_State *L, void* ptr) {
  61. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  62. luat_timer_t *timer = (luat_timer_t *)ptr;
  63. int timer_id = msg->arg1;
  64. if (timer_id > 0) {
  65. timer = luat_timer_get(timer_id);
  66. }
  67. else if (timer != NULL) {
  68. timer_id = timer->id;
  69. timer = luat_timer_get(timer_id);
  70. }
  71. if (timer == NULL)
  72. return 0;
  73. // LLOGD("l_timer_handler id=%ld\n", timer->id);
  74. lua_pushinteger(L, MSG_TIMER);
  75. lua_pushinteger(L, timer->id);
  76. lua_pushinteger(L, timer->repeat);
  77. //lua_pushinteger(L, timer->timeout);
  78. if (timer->repeat == 0) {
  79. // LLOGD("stop timer %d", timer_id);
  80. luat_timer_stop(timer);
  81. luat_heap_free(timer);
  82. }
  83. else if (timer->repeat > 0) {
  84. timer->repeat --;
  85. }
  86. return 3;
  87. }
  88. /*
  89. 启动一个定时器
  90. @api rtos.timer_start(id,timeout,_repeat)
  91. @int 定时器id
  92. @int 超时时长,单位毫秒
  93. @int 重复次数,默认是0
  94. @return id 如果是定时器消息,会返回定时器消息id及附加信息, 其他消息由底层决定,不向lua层进行任何保证.
  95. @usage
  96. -- 用户代码请使用 sys.timerStart
  97. -- 启动一个3秒的循环定时器
  98. rtos.timer_start(10000, 3000, -1)
  99. */
  100. static int l_rtos_timer_start(lua_State *L) {
  101. lua_gettop(L);
  102. size_t timeout = 0;
  103. size_t type = 0;
  104. size_t id = (size_t)luaL_checkinteger(L, 1) / 1;
  105. #if 0
  106. if (lua_isnumber(L, 2)) {
  107. timeout = lua_tonumber(L, 2) * 1000;
  108. type = 1;
  109. } else
  110. #endif
  111. timeout = (size_t)luaL_checkinteger(L, 2);
  112. int repeat = (size_t)luaL_optinteger(L, 3, 0);
  113. // LLOGD("start timer id=%ld", id);
  114. // LLOGD("timer timeout=%ld", timeout);
  115. // LLOGD("timer repeat=%ld", repeat);
  116. if (timeout < 1) {
  117. lua_pushinteger(L, 0);
  118. return 1;
  119. }
  120. luat_timer_t *timer = (luat_timer_t*)luat_heap_malloc(sizeof(luat_timer_t));
  121. timer->id = id;
  122. timer->timeout = timeout;
  123. timer->repeat = repeat;
  124. timer->func = &l_timer_handler;
  125. timer->type = type;
  126. int re = luat_timer_start(timer);
  127. if (re == 0) {
  128. lua_pushinteger(L, 1);
  129. }
  130. else {
  131. LLOGD("start timer fail, free timer %p", timer);
  132. luat_heap_free(timer);
  133. lua_pushinteger(L, 0);
  134. }
  135. return 1;
  136. }
  137. /*
  138. 关闭并释放一个定时器
  139. @api rtos.timer_stop(id)
  140. @int 定时器id
  141. @return nil 无返回值
  142. @usage
  143. -- 用户代码请使用sys.timerStop
  144. rtos.timer_stop(id)
  145. */
  146. static int l_rtos_timer_stop(lua_State *L) {
  147. int timerid = -1;
  148. luat_timer_t *timer = NULL;
  149. if (!lua_isinteger(L, 1)) {
  150. return 0;
  151. }
  152. timerid = lua_tointeger(L, 1);
  153. timer = luat_timer_get(timerid);
  154. if (timer != NULL) {
  155. // LLOGD("timer stop, free timer %d", timerid);
  156. luat_timer_stop(timer);
  157. luat_heap_free(timer);
  158. }
  159. return 0;
  160. }
  161. /*
  162. 设备重启
  163. @api rtos.reboot()
  164. @return nil 无返回值
  165. -- 立即重启设备
  166. rtos.reboot()
  167. */
  168. int l_rtos_reboot(lua_State *L) {
  169. luat_os_reboot(luaL_optinteger(L, 1, 0));
  170. return 0;
  171. }
  172. //-----------------------------------------------------------------
  173. /*
  174. 获取固件编译日期
  175. @api rtos.buildDate()
  176. @return string 固件编译日期
  177. @usage
  178. -- 获取编译日期
  179. local d = rtos.buildDate()
  180. */
  181. static int l_rtos_build_date(lua_State *L) {
  182. lua_pushstring(L, __DATE__);
  183. return 1;
  184. }
  185. /*
  186. 获取硬件bsp型号
  187. @api rtos.bsp()
  188. @return string 硬件bsp型号
  189. @usage
  190. -- 获取硬件bsp型号
  191. local bsp = rtos.bsp()
  192. */
  193. static int l_rtos_bsp(lua_State *L) {
  194. lua_pushstring(L, luat_os_bsp());
  195. return 1;
  196. }
  197. /*
  198. 获取固件版本号
  199. @api rtos.version()
  200. @return string 固件版本号,例如"V0001"
  201. @usage
  202. -- 读取版本号
  203. local luatos_version = rtos.version()
  204. */
  205. static int l_rtos_version(lua_State *L) {
  206. lua_pushstring(L, luat_version_str());
  207. return 1;
  208. }
  209. /*
  210. 进入待机模式, 仅部分设备可用, 本API已废弃, 推荐使用pm库
  211. @api rtos.standy(timeout)
  212. @int 休眠时长,单位毫秒
  213. @return nil 无返回值
  214. @usage
  215. -- 进入待机模式
  216. rtos.standby(5000)
  217. */
  218. static int l_rtos_standy(lua_State *L) {
  219. int timeout = luaL_checkinteger(L, 1);
  220. luat_os_standy(timeout);
  221. return 0;
  222. }
  223. /*
  224. 获取内存信息
  225. @api rtos.meminfo(type)
  226. @type "sys"系统内存, "lua"虚拟机内存, 默认为lua虚拟机内存
  227. @return int 总内存大小,单位字节
  228. @return int 当前已使用的内存大小,单位字节
  229. @return int 历史最高已使用的内存大小,单位字节
  230. @usage
  231. -- 打印内存占用
  232. log.info("mem.lua", rtos.meminfo())
  233. log.info("mem.sys", rtos.meminfo("sys"))
  234. */
  235. static int l_rtos_meminfo(lua_State *L) {
  236. size_t len = 0;
  237. size_t total = 0;
  238. size_t used = 0;
  239. size_t max_used = 0;
  240. const char * str = luaL_optlstring(L, 1, "lua", &len);
  241. if (strcmp("sys", str) == 0) {
  242. //lua_gc(L, LUA_GCCOLLECT, 0);
  243. //lua_gc(L, LUA_GCCOLLECT, 0);
  244. luat_meminfo_sys(&total, &used, &max_used);
  245. }
  246. else {
  247. luat_meminfo_luavm(&total, &used, &max_used);
  248. }
  249. lua_pushinteger(L, total);
  250. lua_pushinteger(L, used);
  251. lua_pushinteger(L, max_used);
  252. return 3;
  253. }
  254. /*
  255. 返回底层描述信息,格式为 LuatOS_$VERSION_$BSP,可用于OTA升级判断底层信息
  256. @api rtos.firmware()
  257. @return string 底层描述信息
  258. @usage
  259. -- 打印底层描述信息
  260. log.info("firmware", rtos.firmware())
  261. */
  262. static int l_rtos_firmware(lua_State *L) {
  263. lua_pushfstring(L, "LuatOS-SoC_%s_%s", luat_version_str(), luat_os_bsp());
  264. return 1;
  265. }
  266. extern char custom_search_paths[4][24];
  267. /*
  268. 设置自定义lua脚本搜索路径,优先级高于内置路径
  269. @api rtos.setPaths(pathA, pathB, pathC, pathD)
  270. @string 路径A, 例如 "/sdcard/%s.luac",若不传值,将默认为"",另外,最大长度不能超过23字节
  271. @string 路径B, 例如 "/sdcard/%s.lua"
  272. @string 路径C, 例如 "/lfs2/%s.luac"
  273. @string 路径D, 例如 "/lfs2/%s.lua"
  274. @usage
  275. -- 挂载sd卡或者spiflash后
  276. rtos.setPaths("/sdcard/user/%s.luac", "/sdcard/user/%s.lua")
  277. require("sd_user_main") -- 将搜索并加载 /sdcard/user/sd_user_main.luac 和 /sdcard/user/sd_user_main.lua
  278. */
  279. static int l_rtos_set_paths(lua_State *L) {
  280. size_t len = 0;
  281. const char* str = NULL;
  282. for (size_t i = 0; i < 4; i++)
  283. {
  284. if (lua_isstring(L, i +1)) {
  285. str = luaL_checklstring(L, i+1, &len);
  286. memcpy(custom_search_paths[i], str, len + 1);
  287. }
  288. else {
  289. custom_search_paths[i][0] = 0x00;
  290. }
  291. }
  292. return 0;
  293. }
  294. /*
  295. 空函数,什么都不做
  296. @api rtos.nop()
  297. @return nil 无返回值
  298. @usage
  299. -- 这个函数单纯就是 lua -> c -> lua 走一遍
  300. -- 没有参数,没有返回值,没有逻辑处理
  301. -- 在绝大多数情况下,不会遇到这个函数的调用
  302. -- 它通常只会出现在性能测试的代码里, 因为它什么都不干.
  303. rtos.nop()
  304. */
  305. static int l_rtos_nop(lua_State *L) {
  306. (void)L;
  307. return 0;
  308. }
  309. // TODO 部分平台不支持LUAT_WEAK
  310. LUAT_WEAK int luat_poweron_reason(void) {
  311. return 0;
  312. }
  313. //uint32_t-高16位重启主原因,低16位详细原因
  314. //高16位:0-上电/复位开机,1-用户主动软件重启,2-RTC开机,3-异常重启,4-唤醒开机
  315. //低16位
  316. //
  317. // static int l_rtos_poweron_reason(lua_State *L) {
  318. // lua_pushinteger(L,luat_poweron_reason());
  319. // return 1;
  320. // }
  321. //------------------------------------------------------------------
  322. #include "rotable2.h"
  323. static const rotable_Reg_t reg_rtos[] =
  324. {
  325. { "timer_start" , ROREG_FUNC(l_rtos_timer_start)},
  326. { "timer_stop", ROREG_FUNC(l_rtos_timer_stop)},
  327. { "receive", ROREG_FUNC(l_rtos_receive)},
  328. { "reboot", ROREG_FUNC(l_rtos_reboot)},
  329. // { "poweron_reason", ROREG_FUNC(l_rtos_poweron_reason)},
  330. { "standy", ROREG_FUNC(l_rtos_standy)},
  331. { "buildDate", ROREG_FUNC(l_rtos_build_date)},
  332. { "bsp", ROREG_FUNC(l_rtos_bsp)},
  333. { "version", ROREG_FUNC(l_rtos_version)},
  334. { "meminfo", ROREG_FUNC(l_rtos_meminfo)},
  335. { "firmware", ROREG_FUNC(l_rtos_firmware)},
  336. { "setPaths", ROREG_FUNC(l_rtos_set_paths)},
  337. { "nop", ROREG_FUNC(l_rtos_nop)},
  338. { "INF_TIMEOUT", ROREG_INT(-1)},
  339. { "MSG_TIMER", ROREG_INT(MSG_TIMER)},
  340. // { "MSG_GPIO", NULL, MSG_GPIO},
  341. // { "MSG_UART_RX", NULL, MSG_UART_RX},
  342. // { "MSG_UART_TXDONE", NULL, MSG_UART_TXDONE},
  343. { NULL, ROREG_INT(0) }
  344. };
  345. LUAMOD_API int luaopen_rtos( lua_State *L ) {
  346. luat_newlib2(L, reg_rtos);
  347. return 1;
  348. }
  349. LUAT_WEAK const char* luat_version_str(void) {
  350. #ifdef LUAT_BSP_VERSION
  351. return LUAT_BSP_VERSION;
  352. #else
  353. return LUAT_VERSION;
  354. #endif
  355. }