luat_lib_mcu.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. @module mcu
  3. @summary 封装mcu一些特殊操作
  4. @version core V0007
  5. @date 2021.08.18
  6. */
  7. #include "luat_base.h"
  8. #include "luat_mcu.h"
  9. #include "luat_zbuff.h"
  10. #include "luat_spi.h"
  11. #define LUAT_LOG_TAG "mcu"
  12. #include "luat_log.h"
  13. /*
  14. 设置主频,单位MHZ
  15. @api mcu.setClk(mhz)
  16. @int 主频,根据设备的不同有不同的有效值,请查阅手册
  17. @return bool 成功返回true,否则返回false
  18. @usage
  19. -- 请注意,主频与外设主频有关联性, 例如主频2M时SPI的最高只能1M
  20. -- 设置到80MHZ
  21. mcu.setClk(80)
  22. sys.wait(1000)
  23. -- 设置到240MHZ
  24. mcu.setClk(240)
  25. sys.wait(1000)
  26. -- 设置到2MHZ
  27. mcu.setClk(2)
  28. sys.wait(1000)
  29. */
  30. static int l_mcu_set_clk(lua_State* L) {
  31. int ret = luat_mcu_set_clk((size_t)luaL_checkinteger(L, 1));
  32. lua_pushboolean(L, ret == 0 ? 1 : 0);
  33. return 1;
  34. }
  35. /*
  36. 获取主频,单位MHZ
  37. @api mcu.getClk()
  38. @return int 若失败返回-1,否则返回主频数值,若等于0,可能处于32k晶振的省电模式
  39. @usage
  40. local mhz = mcu.getClk()
  41. print("Boom", mhz)
  42. */
  43. static int l_mcu_get_clk(lua_State* L) {
  44. int mhz = luat_mcu_get_clk();
  45. lua_pushinteger(L, mhz);
  46. return 1;
  47. }
  48. /*
  49. 获取设备唯一id. 注意,可能包含不可见字符,如需查看建议toHex()后打印
  50. @api mcu.unique_id()
  51. @return string 设备唯一id.若不支持, 会返回空字符串.
  52. @usage
  53. local unique_id = mcu.unique_id()
  54. print("unique_id", unique_id)
  55. */
  56. static int l_mcu_unique_id(lua_State* L) {
  57. size_t len = 0;
  58. const char* id = luat_mcu_unique_id(&len);
  59. lua_pushlstring(L, id, len);
  60. return 1;
  61. }
  62. /*
  63. 获取启动后的tick数,注意会出现溢出会出现负数
  64. @api mcu.ticks()
  65. @return int 当前tick值
  66. @usage
  67. local tick = mcu.ticks()
  68. print("ticks", tick)
  69. */
  70. static int l_mcu_ticks(lua_State* L) {
  71. long tick = luat_mcu_ticks();
  72. lua_pushinteger(L, tick);
  73. return 1;
  74. }
  75. /*
  76. 获取每秒的tick数量
  77. @api mcu.hz()
  78. @return int 每秒的tick数量
  79. @usage
  80. local tick = mcu.hz()
  81. print("mcu.hz", hz)
  82. */
  83. static int l_mcu_hz(lua_State* L) {
  84. uint32_t hz = luat_mcu_hz();
  85. lua_pushinteger(L, hz);
  86. return 1;
  87. }
  88. /*
  89. 读写mcu的32bit寄存器或者ram,谨慎使用写功能,请熟悉mcu的寄存器使用方法后再使用
  90. @api mcu.reg32(address, value, mask)
  91. @int 寄存器或者ram地址
  92. @int 写入的值,如果没有,则直接返回当前值
  93. @int 位掩码,可以对特定几个位置的bit做修改, 默认0xffffffff,修改全部32bit
  94. @return int 返回当前寄存的值
  95. @usage
  96. local value = mcu.reg32(0x2009FFFC, 0x01, 0x01) --对0x2009FFFC地址上的值,修改bit0为1
  97. */
  98. static int l_mcu_reg32(lua_State* L) {
  99. volatile uint32_t *address = (uint32_t *)(luaL_checkinteger(L, 1) & 0xfffffffc);
  100. if (lua_isinteger(L, 2)) {
  101. volatile uint32_t value = lua_tointeger(L, 2);
  102. volatile uint32_t mask = luaL_optinteger(L, 3, 0xffffffff);
  103. volatile uint32_t org = *address;
  104. *address = (org & ~mask)| (value & mask);
  105. lua_pushinteger(L, *address);
  106. } else {
  107. lua_pushinteger(L, *address);
  108. }
  109. return 1;
  110. }
  111. /*
  112. 转换10进制数为16进制字符串输出
  113. @api mcu.x32(value)
  114. @int 需要转换的值
  115. @return string 16进制字符串
  116. @usage
  117. local value = mcu.x32(0x2009FFFC) --输出"0x2009fffc"
  118. */
  119. static int l_mcu_x32(lua_State* L) {
  120. uint32_t value = luaL_checkinteger(L, 1);
  121. char c[16];
  122. sprintf_(c, "0x%x", value);
  123. lua_pushstring(L, c);
  124. return 1;
  125. }
  126. // #ifdef __LUATOS_TICK_64BIT__
  127. /*
  128. 获取启动后的高精度tick,目前只有101/103/105能用
  129. @api mcu.tick64()
  130. @return string 当前tick值,8个字节的uint64
  131. @return int 1us有几个tick,0表示未知
  132. @usage
  133. local tick_str, tick_per = mcu.tick64()
  134. print("ticks", tick_str, tick_per)
  135. */
  136. static int l_mcu_hw_tick64(lua_State* L) {
  137. uint64_t tick = luat_mcu_tick64();
  138. uint32_t us_period = luat_mcu_us_period();
  139. lua_pushlstring(L, (const char*)&tick, 8);
  140. lua_pushinteger(L, us_period);
  141. return 2;
  142. }
  143. /*
  144. 计算2个64bit tick的差值,目前只有105能用
  145. @api mcu.dtick64(tick1, tick2, check_value)
  146. @string 64bit的string
  147. @string 64bit的string
  148. @int 参考值,可选项,如果为0,则返回结果中第一个项目为true
  149. @return boolean 与参考值比较,如果大于等于为true,反之为false
  150. @return int 差值tick1 - tick2,如果超过了0x7fffffff,结果可能是错的
  151. @usage
  152. local result, diff_tick = mcu.dtick64(tick1, tick2)
  153. print("ticks", result, diff_tick)
  154. */
  155. static int l_mcu_hw_diff_tick64(lua_State* L) {
  156. uint64_t tick1, tick2;
  157. int64_t diff;
  158. int check_value = 0;
  159. size_t len1;
  160. const char *data1 = luaL_checklstring(L, 1, &len1);
  161. size_t len2;
  162. const char *data2 = luaL_checklstring(L, 2, &len2);
  163. check_value = luaL_optinteger(L, 3, 0);
  164. memcpy(&tick1, data1, len1);
  165. memcpy(&tick2, data2, len2);
  166. diff = tick1 - tick2;
  167. lua_pushboolean(L, (diff >= (int64_t)check_value)?1:0);
  168. lua_pushinteger(L, diff);
  169. return 2;
  170. }
  171. /*
  172. 选择时钟源,当前仅air105支持
  173. @api mcu.setXTAL(source_main, source_32k, delay)
  174. @boolean 高速时钟是否使用外部时钟源,如果为空则不改变
  175. @boolean 低速32K是否使用外部时钟源,如果为空则不改变
  176. @int PLL稳定时间,在切换高速时钟的时候,根据硬件环境,需要delay一段时间等待PLL稳定,默认是1200,建议不小于1024
  177. @usage
  178. mcu.setXTAL(true, true, 1248) --高速时钟使用外部时钟,低速32K使用外部晶振, delay1248
  179. */
  180. static int l_mcu_set_xtal(lua_State* L) {
  181. int source_main = 255;
  182. int source_32k = 255;
  183. int delay = luaL_optinteger(L, 3, 1200);
  184. if (lua_isboolean(L, 1)) {
  185. source_main = lua_toboolean(L, 1);
  186. }
  187. if (lua_isboolean(L, 2)) {
  188. source_32k = lua_toboolean(L, 2);
  189. }
  190. luat_mcu_set_clk_source(source_main, source_32k, delay);
  191. return 0;
  192. }
  193. // #endif
  194. #include "rotable2.h"
  195. static const rotable_Reg_t reg_mcu[] =
  196. {
  197. { "setClk" , ROREG_FUNC(l_mcu_set_clk)},
  198. { "getClk", ROREG_FUNC(l_mcu_get_clk)},
  199. { "unique_id", ROREG_FUNC(l_mcu_unique_id)},
  200. { "ticks", ROREG_FUNC(l_mcu_ticks)},
  201. { "hz", ROREG_FUNC(l_mcu_hz)},
  202. { "reg32", ROREG_FUNC(l_mcu_reg32)},
  203. { "x32", ROREG_FUNC(l_mcu_x32)},
  204. // #ifdef __LUATOS_TICK_64BIT__
  205. { "tick64", ROREG_FUNC(l_mcu_hw_tick64)},
  206. { "dtick64", ROREG_FUNC(l_mcu_hw_diff_tick64)},
  207. { "setXTAL", ROREG_FUNC(l_mcu_set_xtal)},
  208. // #endif
  209. { NULL, ROREG_INT(0) }
  210. };
  211. LUAMOD_API int luaopen_mcu( lua_State *L ) {
  212. luat_newlib2(L, reg_mcu);
  213. return 1;
  214. }