luat_lib_gpio.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*
  2. @module gpio
  3. @summary GPIO操作
  4. @catalog 外设API
  5. @version 1.0
  6. @date 2020.03.30
  7. @demo gpio
  8. @video https://www.bilibili.com/video/BV1hr4y1p7dt
  9. @tag LUAT_USE_GPIO
  10. */
  11. #include "luat_base.h"
  12. #include "luat_gpio.h"
  13. #include "luat_malloc.h"
  14. #include "luat_mcu.h"
  15. #include "luat_msgbus.h"
  16. #include "luat_timer.h"
  17. #include "luat_rtos.h"
  18. #include <math.h>
  19. #define LUAT_LOG_TAG "gpio"
  20. #include "luat_log.h"
  21. // 若bsp没有定义最大PIN编号, 那么默认给个128吧
  22. #ifndef LUAT_GPIO_PIN_MAX
  23. #define LUAT_GPIO_PIN_MAX (128)
  24. #endif
  25. static int l_gpio_set(lua_State *L);
  26. static int l_gpio_get(lua_State *L);
  27. static int l_gpio_close(lua_State *L);
  28. int l_gpio_handler(lua_State *L, void* ptr) ;
  29. typedef struct gpio_ctx
  30. {
  31. int lua_ref; // irq下的回调函数
  32. luat_rtos_timer_t timer;
  33. uint32_t latest_tick; // 防抖功能的最后tick数
  34. uint16_t conf_tick; // 防抖设置的超时tick数
  35. uint8_t debounce_mode;
  36. uint8_t latest_state;
  37. uint8_t irq_type;
  38. }gpio_ctx_t;
  39. // 保存中断回调的数组
  40. static gpio_ctx_t gpios[LUAT_GPIO_PIN_MAX] __attribute__((aligned (16)));
  41. static uint32_t default_gpio_pull = Luat_GPIO_DEFAULT;
  42. // 记录GPIO电平,仅OUTPUT时可用
  43. static uint8_t gpio_out_levels[(LUAT_GPIO_PIN_MAX + 7) / 8] __attribute__((aligned (16)));
  44. static uint8_t gpio_bit_get(int pin) {
  45. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
  46. return 0;
  47. return (gpio_out_levels[pin/8] >> (pin%8)) & 0x01;
  48. }
  49. static void gpio_bit_set(int pin, uint8_t value) {
  50. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
  51. return;
  52. uint8_t val = (gpio_out_levels[pin/8] >> (pin%8)) & 0x01;
  53. if (val == value)
  54. return; // 不变呀
  55. if (value == 0) {
  56. gpio_out_levels[pin/8] -= (1 << (pin%8));
  57. }
  58. else {
  59. gpio_out_levels[pin/8] += (1 << (pin%8));
  60. }
  61. }
  62. int l_gpio_debounce_timer_handler(lua_State *L, void* ptr) {
  63. (void)L;
  64. (void)ptr;
  65. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  66. int pin = msg->arg1;
  67. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
  68. return 0; // 超范围, 内存异常
  69. if (gpios[pin].lua_ref == 0)
  70. return 0; // 早关掉了
  71. if (gpios[pin].latest_state != luat_gpio_get(pin))
  72. return 0; // 电平变了
  73. if (gpios[pin].debounce_mode)
  74. {
  75. switch(gpios[pin].irq_type)
  76. {
  77. case Luat_GPIO_RISING:
  78. case Luat_GPIO_HIGH_IRQ:
  79. if (!gpios[pin].latest_state) return 0;
  80. break;
  81. case Luat_GPIO_FALLING:
  82. case Luat_GPIO_LOW_IRQ:
  83. if (gpios[pin].latest_state) return 0;
  84. break;
  85. }
  86. }
  87. lua_geti(L, LUA_REGISTRYINDEX, gpios[pin].lua_ref);
  88. if (!lua_isnil(L, -1)) {
  89. lua_pushinteger(L, gpios[pin].latest_state);
  90. lua_call(L, 1, 0);
  91. }
  92. return 0;
  93. }
  94. #ifndef LUAT_RTOS_API_NOTOK
  95. static LUAT_RT_RET_TYPE l_gpio_debounce_mode1_cb(LUAT_RT_CB_PARAM) {
  96. int pin = (int)param;
  97. rtos_msg_t msg = {0};
  98. msg.handler = l_gpio_debounce_timer_handler;
  99. msg.arg1 = pin;
  100. luat_msgbus_put(&msg, 0);
  101. }
  102. #endif
  103. int luat_gpio_irq_default(int pin, void* args) {
  104. rtos_msg_t msg = {0};
  105. #ifdef LUAT_GPIO_PIN_MAX
  106. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX) {
  107. #else
  108. if (pin < 0 || pin >= Luat_GPIO_MAX_ID) {
  109. #endif
  110. return 0;
  111. }
  112. if (pin < LUAT_GPIO_PIN_MAX && gpios[pin].conf_tick > 0) {
  113. // 防抖模式0, 触发后冷却N个ms
  114. if (gpios[pin].debounce_mode == 0) {
  115. uint32_t ticks = (uint32_t)luat_mcu_ticks();
  116. uint32_t diff = (ticks > gpios[pin].latest_tick) ? (ticks - gpios[pin].latest_tick) : (gpios[pin].latest_tick - ticks);
  117. if (diff >= gpios[pin].conf_tick) {
  118. gpios[pin].latest_tick = ticks;
  119. }
  120. else {
  121. // 防抖生效, 直接返回
  122. return 0;
  123. }
  124. }
  125. #ifndef LUAT_RTOS_API_NOTOK
  126. // 防抖模式1, 触发后延时N个ms, 电平依然不变才触发
  127. else if (gpios[pin].debounce_mode == 1) {
  128. if (gpios[pin].timer == NULL || gpios[pin].conf_tick == 0) {
  129. return 0; // timer被释放了?
  130. }
  131. gpios[pin].latest_state = luat_gpio_get(pin);
  132. luat_rtos_timer_stop(gpios[pin].timer);
  133. luat_rtos_timer_start(gpios[pin].timer, gpios[pin].conf_tick, 0, l_gpio_debounce_mode1_cb, (void*)pin);
  134. return 0;
  135. }
  136. #endif
  137. }
  138. msg.handler = l_gpio_handler;
  139. msg.ptr = NULL;
  140. msg.arg1 = pin;
  141. msg.arg2 = (int)args;
  142. return luat_msgbus_put(&msg, 0);
  143. }
  144. int l_gpio_handler(lua_State *L, void* ptr) {
  145. (void)ptr; // unused
  146. // 给 sys.publish方法发送数据
  147. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  148. int pin = msg->arg1;
  149. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
  150. return 0;
  151. if (gpios[pin].lua_ref == 0)
  152. return 0;
  153. lua_geti(L, LUA_REGISTRYINDEX, gpios[pin].lua_ref);
  154. if (!lua_isnil(L, -1)) {
  155. lua_pushinteger(L, msg->arg2);
  156. lua_call(L, 1, 0);
  157. }
  158. return 0;
  159. }
  160. /*
  161. 设置管脚功能
  162. @api gpio.setup(pin, mode, pull, irq, alt)
  163. @int pin gpio编号,必须是数值
  164. @any mode 输入输出模式:<br>数字0/1代表输出模式<br>nil代表输入模式<br>function代表中断模式
  165. @int pull 上拉下列模式, 可以是gpio.PULLUP 或 gpio.PULLDOWN, 需要根据实际硬件选用
  166. @int irq 中断触发模式,默认gpio.BOTH。中断触发模式<br>上升沿gpio.RISING<br>下降沿gpio.FALLING<br>上升和下降都触发gpio.BOTH
  167. @int alt 复用选项,目前只有EC618平台需要这个参数,有些GPIO可以复用到不同引脚上,可以选择复用选项(0或者4)从而复用到对应的引脚上
  168. @return any 输出模式返回设置电平的闭包, 输入模式和中断模式返回获取电平的闭包
  169. @usage
  170. -- 设置gpio17为输入
  171. gpio.setup(17, nil)
  172. -- 设置gpio17为输出,且初始化电平为低,使用硬件默认上下拉配置
  173. gpio.setup(17, 0)
  174. -- 设置gpio17为输出,且初始化电平为高,且启用内部上拉
  175. gpio.setup(17, 1, gpio.PULLUP)
  176. -- 设置gpio27为中断
  177. gpio.setup(27, function(val) print("IRQ_27",val) end, gpio.PULLUP)
  178. -- 设置gpio27为中断
  179. gpio.setup(27, function(val) print("IRQ_27",val) end, gpio.PULLUP)
  180. -- alt_func 于2023.7.2新增
  181. -- 设置AIR780E的PIN33复用成gpio18,方向输出,且初始化电平为低,使用硬件默认上下拉配置
  182. gpio.setup(18, 0, nil, nil, 4)
  183. */
  184. static int l_gpio_setup(lua_State *L) {
  185. luat_gpio_t conf = {0};
  186. conf.pin = luaL_checkinteger(L, 1);
  187. //conf->mode = luaL_checkinteger(L, 2);
  188. conf.lua_ref = 0;
  189. conf.irq = 0;
  190. gpios[conf.pin].irq_type = 0xff;
  191. if (lua_isfunction(L, 2)) {
  192. conf.mode = Luat_GPIO_IRQ;
  193. lua_pushvalue(L, 2);
  194. conf.lua_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  195. conf.irq = luaL_optinteger(L, 4, Luat_GPIO_BOTH);
  196. gpios[conf.pin].irq_type = conf.irq;
  197. }
  198. else if (lua_isinteger(L, 2)) {
  199. conf.mode = Luat_GPIO_OUTPUT;
  200. conf.irq = luaL_checkinteger(L, 2) == 0 ? 0 : 1; // 重用irq当初始值用
  201. }
  202. else {
  203. conf.mode = Luat_GPIO_INPUT;
  204. }
  205. conf.pull = luaL_optinteger(L, 3, default_gpio_pull);
  206. conf.irq_cb = 0;
  207. if (lua_isinteger(L, 5)) {
  208. conf.alt_func = luaL_checkinteger(L, 5);
  209. }
  210. else
  211. {
  212. conf.alt_func = -1;
  213. }
  214. int re = luat_gpio_setup(&conf);
  215. if (re != 0) {
  216. LLOGW("gpio setup fail pin=%d", conf.pin);
  217. return 0;
  218. }
  219. if (conf.mode == Luat_GPIO_IRQ) {
  220. if (gpios[conf.pin].lua_ref && gpios[conf.pin].lua_ref != conf.lua_ref) {
  221. luaL_unref(L, LUA_REGISTRYINDEX, gpios[conf.pin].lua_ref);
  222. gpios[conf.pin].lua_ref = conf.lua_ref;
  223. }
  224. gpios[conf.pin].lua_ref = conf.lua_ref;
  225. }
  226. else if (conf.mode == Luat_GPIO_OUTPUT) {
  227. luat_gpio_set(conf.pin, conf.irq); // irq被重用为OUTPUT的初始值
  228. }
  229. // 生成闭包
  230. lua_settop(L, 1);
  231. if (conf.mode == Luat_GPIO_OUTPUT) {
  232. lua_pushcclosure(L, l_gpio_set, 1);
  233. }
  234. else {
  235. lua_pushcclosure(L, l_gpio_get, 1);
  236. }
  237. return 1;
  238. }
  239. /*
  240. 设置管脚电平
  241. @api gpio.set(pin, value)
  242. @int pin GPIO编号,必须是数值
  243. @int value 电平, 可以是 高电平gpio.HIGH, 低电平gpio.LOW, 或者直接写数值1或0
  244. @return nil 无返回值
  245. @usage
  246. -- 设置gpio17为低电平
  247. gpio.set(17, 0)
  248. */
  249. static int l_gpio_set(lua_State *L) {
  250. int pin = 0;
  251. int value = 0;
  252. if (lua_isinteger(L, lua_upvalueindex(1))) {
  253. pin = lua_tointeger(L, lua_upvalueindex(1));
  254. value = luaL_checkinteger(L, 1);
  255. }
  256. else {
  257. pin = luaL_checkinteger(L, 1);
  258. value = luaL_checkinteger(L, 2);
  259. }
  260. luat_gpio_set(pin, value);
  261. gpio_bit_set(pin, (uint8_t)value);
  262. return 0;
  263. }
  264. /*
  265. 获取管脚电平
  266. @api gpio.get(pin)
  267. @int pin GPIO编号,必须是数值
  268. @return value 电平, 高电平gpio.HIGH, 低电平gpio.LOW, 对应数值1和0
  269. @usage
  270. -- 获取gpio17的当前电平
  271. gpio.get(17)
  272. */
  273. static int l_gpio_get(lua_State *L) {
  274. if (lua_isinteger(L, lua_upvalueindex(1)))
  275. lua_pushinteger(L, luat_gpio_get(luaL_checkinteger(L, lua_upvalueindex(1))) & 0x01 ? 1 : 0);
  276. else
  277. lua_pushinteger(L, luat_gpio_get(luaL_checkinteger(L, 1)) & 0x01 ? 1 : 0);
  278. return 1;
  279. }
  280. /*
  281. 关闭管脚功能(高阻输入态),关掉中断
  282. @api gpio.close(pin)
  283. @int pin GPIO编号,必须是数值
  284. @return nil 无返回值,总是执行成功
  285. @usage
  286. -- 关闭gpio17
  287. gpio.close(17)
  288. */
  289. static int l_gpio_close(lua_State *L) {
  290. int pin = luaL_checkinteger(L, 1);
  291. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
  292. return 0;
  293. luat_gpio_close(pin);
  294. if (gpios[pin].lua_ref) {
  295. luaL_unref(L, LUA_REGISTRYINDEX, gpios[pin].lua_ref);
  296. gpios[pin].lua_ref = 0;
  297. }
  298. #ifndef LUAT_RTOS_API_NOTOK
  299. if (gpios[pin].timer != NULL) {
  300. gpios[pin].conf_tick = 0;
  301. luat_rtos_timer_stop(gpios[pin].timer);
  302. luat_rtos_timer_delete(gpios[pin].timer);
  303. gpios[pin].timer = NULL;
  304. }
  305. #endif
  306. return 0;
  307. }
  308. /*
  309. 设置GPIO脚的默认上拉/下拉设置, 默认是平台自定义(一般为开漏).
  310. @api gpio.setDefaultPull(val)
  311. @int val 0平台自定义,1上拉, 2下拉
  312. @return boolean 传值正确返回true,否则返回false
  313. @usage
  314. -- 设置gpio.setup的pull默认值为上拉
  315. gpio.setDefaultPull(1)
  316. */
  317. static int l_gpio_set_default_pull(lua_State *L) {
  318. int value = luaL_checkinteger(L, 1);
  319. if (value >= 0 && value <= 2) {
  320. default_gpio_pull = value;
  321. lua_pushboolean(L, 1);
  322. }
  323. else {
  324. lua_pushboolean(L, 0);
  325. }
  326. return 1;
  327. }
  328. /*
  329. 变换GPIO脚输出电平,仅输出模式可用
  330. @api gpio.toggle(pin)
  331. @int 管脚的GPIO号
  332. @return nil 无返回值
  333. @usage
  334. -- 本API于 2022.05.17 添加
  335. -- 假设GPIO16上有LED, 每500ms切换一次开关
  336. gpio.setup(16, 0)
  337. sys.timerLoopStart(function()
  338. gpio.toggle(16)
  339. end, 500)
  340. */
  341. static int l_gpio_toggle(lua_State *L) {
  342. int pin = 0;
  343. if (lua_isinteger(L, lua_upvalueindex(1)))
  344. pin = lua_tointeger(L, lua_upvalueindex(1));
  345. else
  346. pin = luaL_checkinteger(L, 1);
  347. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX) {
  348. LLOGW("pin id out of range (0-127)");
  349. return 0;
  350. }
  351. uint8_t value = gpio_bit_get(pin);
  352. luat_gpio_set(pin, value == 0 ? Luat_GPIO_HIGH : Luat_GPIO_LOW);
  353. gpio_bit_set(pin, value == 0 ? 1 : 0);
  354. return 0;
  355. }
  356. /*
  357. 在同一个GPIO输出一组脉冲, 注意, len的单位是bit, 高位在前.
  358. @api gpio.pulse(pin,level,len,delay)
  359. @int gpio号
  360. @int/string 数值或者字符串.
  361. @int len 长度 单位是bit, 高位在前.
  362. @int delay 延迟,当前无固定时间单位
  363. @return nil 无返回值
  364. @usage
  365. -- 通过PB06脚输出输出8个电平变化.
  366. gpio.pulse(pin.PB06,0xA9, 8, 0)
  367. */
  368. static int l_gpio_pulse(lua_State *L) {
  369. int pin,delay = 0;
  370. char tmp = 0;
  371. size_t len = 0;
  372. char* level = NULL;
  373. if (lua_isinteger(L, lua_upvalueindex(1))){
  374. pin = lua_tointeger(L, lua_upvalueindex(1));
  375. if (lua_isinteger(L, 1)){
  376. tmp = (char)luaL_checkinteger(L, 1);
  377. level = &tmp;
  378. }else if (lua_isstring(L, 1)){
  379. level = (char*)luaL_checklstring(L, 1, &len);
  380. }
  381. len = luaL_checkinteger(L, 2);
  382. delay = luaL_checkinteger(L, 3);
  383. } else {
  384. pin = luaL_checkinteger(L, 1);
  385. if (lua_isinteger(L, 2)){
  386. tmp = (char)luaL_checkinteger(L, 2);
  387. level = &tmp;
  388. }else if (lua_isstring(L, 2)){
  389. level = (char*)luaL_checklstring(L, 2, &len);
  390. }
  391. len = luaL_checkinteger(L, 3);
  392. delay = luaL_checkinteger(L, 4);
  393. }
  394. if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX) {
  395. LLOGD("pin id out of range (0-127)");
  396. return 0;
  397. }
  398. luat_gpio_pulse(pin,(uint8_t*)level,len,delay);
  399. return 0;
  400. }
  401. /*
  402. 防抖设置, 根据硬件ticks进行防抖
  403. @api gpio.debounce(pin, ms, mode)
  404. @int gpio号, 0~127, 与硬件相关
  405. @int 防抖时长,单位毫秒, 最大 65555 ms, 设置为0则关闭
  406. @int 模式, 0冷却模式, 1延时模式. 默认是0
  407. @return nil 无返回值
  408. @usage
  409. -- 消抖模式, 当前支持2种, 2022.12.16开始支持mode=1
  410. -- 0 触发中断后,马上上报一次, 然后冷却N个毫秒后,重新接受中断
  411. -- 1 触发中断后,延迟N个毫秒,期间没有新中断且电平没有变化,上报一次
  412. -- 开启防抖, 模式0-冷却, 中断后马上上报, 但100ms内只上报一次
  413. gpio.debounce(7, 100) -- 若芯片支持pin库, 可用pin.PA7代替数字7
  414. -- 开启防抖, 模式1-延时, 中断后等待100ms,期间若保持该电平了,时间到之后上报一次
  415. -- 对应的,如果输入的是一个 50hz的方波,那么不会触发任何上报
  416. gpio.debounce(7, 100, 1)
  417. -- 关闭防抖,时间设置为0就关闭
  418. gpio.debounce(7, 0)
  419. */
  420. static int l_gpio_debounce(lua_State *L) {
  421. uint8_t pin = luaL_checkinteger(L, 1);
  422. uint16_t timeout = luaL_checkinteger(L, 2);
  423. uint8_t mode = luaL_optinteger(L, 3, 0);
  424. if (pin >= LUAT_GPIO_PIN_MAX) {
  425. LLOGW("MUST pin < 128");
  426. return 0;
  427. }
  428. //LLOGD("debounce %d %d %d", pin, timeout, mode);
  429. gpios[pin].conf_tick = timeout;
  430. gpios[pin].latest_tick = 0;
  431. gpios[pin].debounce_mode = mode;
  432. #ifndef LUAT_RTOS_API_NOTOK
  433. if ((mode == 0 && gpios[pin].timer != NULL) || timeout == 0) {
  434. luat_rtos_timer_stop(gpios[pin].timer);
  435. luat_rtos_timer_delete(gpios[pin].timer);
  436. gpios[pin].timer = NULL;
  437. }
  438. else if (mode == 1 && gpios[pin].timer == NULL && timeout > 0) {
  439. //LLOGD("GPIO debounce mode 1 %d %d", pin, timeout);
  440. if (gpios[pin].timer == NULL)
  441. luat_rtos_timer_create(&gpios[pin].timer);
  442. if (gpios[pin].timer == NULL) {
  443. LLOGE("out of memory when malloc debounce timer");
  444. return 0;
  445. }
  446. }
  447. #endif
  448. return 0;
  449. }
  450. #include "rotable2.h"
  451. static const rotable_Reg_t reg_gpio[] =
  452. {
  453. { "setup" , ROREG_FUNC(l_gpio_setup )},
  454. { "set" , ROREG_FUNC(l_gpio_set)},
  455. { "get" , ROREG_FUNC(l_gpio_get)},
  456. { "close" , ROREG_FUNC(l_gpio_close)},
  457. { "toggle", ROREG_FUNC(l_gpio_toggle)},
  458. { "debounce", ROREG_FUNC(l_gpio_debounce)},
  459. { "pulse", ROREG_FUNC(l_gpio_pulse)},
  460. { "setDefaultPull", ROREG_FUNC(l_gpio_set_default_pull)},
  461. //@const LOW number 低电平
  462. { "LOW", ROREG_INT(Luat_GPIO_LOW)},
  463. //@const HIGH number 高电平
  464. { "HIGH", ROREG_INT(Luat_GPIO_HIGH)},
  465. { "OUTPUT", ROREG_INT(Luat_GPIO_OUTPUT)}, // 留着做兼容
  466. //@const PULLUP number 上拉
  467. { "PULLUP", ROREG_INT(Luat_GPIO_PULLUP)},
  468. //@const PULLDOWN number 下拉
  469. { "PULLDOWN", ROREG_INT(Luat_GPIO_PULLDOWN)},
  470. //@const RISING number 上升沿触发
  471. { "RISING", ROREG_INT(Luat_GPIO_RISING)},
  472. //@const FALLING number 下降沿触发
  473. { "FALLING", ROREG_INT(Luat_GPIO_FALLING)},
  474. //@const BOTH number 双向触发,部分设备支持
  475. { "BOTH", ROREG_INT(Luat_GPIO_BOTH)},
  476. //@const HIGH_IRQ number 高电平触发,部分设备支持
  477. { "HIGH_IRQ", ROREG_INT(Luat_GPIO_HIGH_IRQ)},
  478. //@const LOW_IRQ number 低电平触发,部分设备支持
  479. { "LOW_IRQ", ROREG_INT(Luat_GPIO_LOW_IRQ)},
  480. { NULL, ROREG_INT(0) }
  481. };
  482. LUAMOD_API int luaopen_gpio( lua_State *L ) {
  483. memset(gpios, 0, sizeof(gpio_ctx_t) * LUAT_GPIO_PIN_MAX);
  484. luat_newlib2(L, reg_gpio);
  485. return 1;
  486. }
  487. // -------------------- 一些辅助函数
  488. void luat_gpio_mode(int pin, int mode, int pull, int initOutput) {
  489. if (pin == 255) return;
  490. luat_gpio_t conf = {0};
  491. conf.pin = pin;
  492. conf.mode = mode == Luat_GPIO_INPUT ? Luat_GPIO_INPUT : Luat_GPIO_OUTPUT; // 只能是输入/输出, 不能是中断.
  493. conf.pull = pull;
  494. conf.irq = initOutput;
  495. conf.lua_ref = 0;
  496. conf.irq_cb = 0;
  497. conf.alt_func = -1;
  498. luat_gpio_setup(&conf);
  499. if (conf.mode == Luat_GPIO_OUTPUT)
  500. luat_gpio_set(pin, initOutput);
  501. }
  502. #ifndef LUAT_COMPILER_NOWEAK
  503. void LUAT_WEAK luat_gpio_pulse(int pin, uint8_t *level, uint16_t len, uint16_t delay_ns) {
  504. }
  505. #endif