luat_lib_pins.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. @module pins
  3. @summary 管脚外设复用
  4. @version 1.0
  5. @date 2025.4.10
  6. @tag
  7. @usage
  8. */
  9. #include "luat_base.h"
  10. #include "luat_pin.h"
  11. #include "luat_mcu.h"
  12. #include <stdlib.h>
  13. #define LUAT_LOG_TAG "pins"
  14. #include "luat_log.h"
  15. static int search(char *string, size_t string_len, const char **table, uint8_t len)
  16. {
  17. for(int i = 0; i < len; i++)
  18. {
  19. if (strnstr(string, table[i], string_len))
  20. {
  21. return i;
  22. }
  23. }
  24. return -1;
  25. }
  26. static luat_pin_peripheral_function_description_u luat_pin_function_analyze(char *string, size_t len)
  27. {
  28. luat_pin_peripheral_function_description_u description;
  29. size_t offset = 0;
  30. const char *peripheral_names[LUAT_MCU_PERIPHERAL_QTY] = {
  31. "UART","I2C","SPI","PWM","CAN","GPIO","I2S","SDIO","LCD","CAMERA","ONEWIRE","KEYBORAD"
  32. };
  33. const char *function0_names[3] = {
  34. "RX","SCL","MOSI"
  35. };
  36. const char *function1_names[3] = {
  37. "TX","SDA","MISO"
  38. };
  39. const char *function2_names[4] = {
  40. "RTS","SCLK","STB","BCLK"
  41. };
  42. const char *function3_names[3] = {
  43. "CTS","CS","LRCLK"
  44. };
  45. const char *function4_names[2] = {
  46. "MCLK","CMD"
  47. };
  48. const char *function5_names[1] = {
  49. "SCLK"
  50. };
  51. description.code = 0;
  52. for(description.peripheral_type = 0; description.peripheral_type < LUAT_MCU_PERIPHERAL_QTY; description.peripheral_type++)
  53. {
  54. offset = strlen(peripheral_names[description.peripheral_type]);
  55. if (!memcmp(string, peripheral_names[description.peripheral_type], offset))
  56. {
  57. int function_id;
  58. description.peripheral_id = 0;
  59. string += offset;
  60. len -= offset;
  61. while(isdigit(string[0]))
  62. {
  63. description.peripheral_id = description.peripheral_id * 10 + (string[0] - '0');
  64. string++;
  65. len--;
  66. }
  67. switch(description.peripheral_type)
  68. {
  69. case LUAT_MCU_PERIPHERAL_UART:
  70. function_id = search(string, len, function0_names, sizeof(function0_names)/4);
  71. if (function_id >= 0)
  72. {
  73. description.function_id = 0;
  74. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  75. }
  76. function_id = search(string, len, function1_names, sizeof(function1_names)/4);
  77. if (function_id >= 0)
  78. {
  79. description.function_id = 1;
  80. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  81. }
  82. function_id = search(string, len, function2_names, sizeof(function2_names)/4);
  83. if (function_id >= 0)
  84. {
  85. description.function_id = 2;
  86. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  87. }
  88. function_id = search(string, len, function3_names, sizeof(function3_names)/4);
  89. if (function_id >= 0)
  90. {
  91. description.function_id = 3;
  92. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  93. }
  94. break;
  95. case LUAT_MCU_PERIPHERAL_I2C:
  96. function_id = search(string, len, function0_names, sizeof(function0_names)/4);
  97. if (function_id >= 0)
  98. {
  99. description.function_id = 0;
  100. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  101. }
  102. function_id = search(string, len, function1_names, sizeof(function1_names)/4);
  103. if (function_id >= 0)
  104. {
  105. description.function_id = 1;
  106. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  107. }
  108. break;
  109. case LUAT_MCU_PERIPHERAL_SPI:
  110. function_id = search(string, len, function0_names, sizeof(function0_names)/4);
  111. if (function_id >= 0)
  112. {
  113. description.function_id = 0;
  114. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  115. }
  116. function_id = search(string, len, function1_names, sizeof(function1_names)/4);
  117. if (function_id >= 0)
  118. {
  119. description.function_id = 1;
  120. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  121. }
  122. function_id = search(string, len, function2_names, sizeof(function2_names)/4);
  123. if (function_id >= 0)
  124. {
  125. description.function_id = 2;
  126. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  127. }
  128. function_id = search(string, len, function3_names, sizeof(function3_names)/4);
  129. if (function_id >= 0)
  130. {
  131. description.function_id = 3;
  132. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  133. }
  134. break;
  135. case LUAT_MCU_PERIPHERAL_PWM:
  136. if (!string[0])
  137. {
  138. description.function_id = 0;
  139. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  140. }
  141. if (string[0] == 'n')
  142. {
  143. description.function_id = 1;
  144. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  145. }
  146. break;
  147. case LUAT_MCU_PERIPHERAL_CAN:
  148. function_id = search(string, len, function0_names, sizeof(function0_names)/4);
  149. if (function_id >= 0)
  150. {
  151. description.function_id = 0;
  152. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  153. }
  154. function_id = search(string, len, function1_names, sizeof(function1_names)/4);
  155. if (function_id >= 0)
  156. {
  157. description.function_id = 1;
  158. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  159. }
  160. function_id = search(string, len, function2_names, sizeof(function2_names)/4);
  161. if (function_id >= 0)
  162. {
  163. description.function_id = 2;
  164. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  165. }
  166. break;
  167. case LUAT_MCU_PERIPHERAL_GPIO:
  168. if (!string[0])
  169. {
  170. description.function_id = 0;
  171. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  172. }
  173. break;
  174. case LUAT_MCU_PERIPHERAL_I2S:
  175. function_id = search(string, len, function0_names, sizeof(function0_names)/4);
  176. if (function_id >= 0)
  177. {
  178. description.function_id = 0;
  179. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  180. }
  181. function_id = search(string, len, function1_names, sizeof(function1_names)/4);
  182. if (function_id >= 0)
  183. {
  184. description.function_id = 1;
  185. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  186. }
  187. function_id = search(string, len, function2_names, sizeof(function2_names)/4);
  188. if (function_id >= 0)
  189. {
  190. description.function_id = 2;
  191. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  192. }
  193. function_id = search(string, len, function3_names, sizeof(function3_names)/4);
  194. if (function_id >= 0)
  195. {
  196. description.function_id = 3;
  197. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  198. }
  199. function_id = search(string, len, function4_names, sizeof(function4_names)/4);
  200. if (function_id >= 0)
  201. {
  202. description.function_id = 4;
  203. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  204. }
  205. break;
  206. case LUAT_MCU_PERIPHERAL_SDIO:
  207. if (strnstr(string, "_DATA", len))
  208. {
  209. if (string[5] >= '0' && string[5] <= '3')
  210. {
  211. function_id = string[5] - '0';
  212. }
  213. break;
  214. }
  215. function_id = search(string, len, function4_names, sizeof(function4_names)/4);
  216. if (function_id >= 0)
  217. {
  218. description.function_id = 4;
  219. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  220. }
  221. function_id = search(string, len, function5_names, sizeof(function5_names)/4);
  222. if (function_id >= 0)
  223. {
  224. description.function_id = 5;
  225. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  226. }
  227. break;
  228. case LUAT_MCU_PERIPHERAL_ONEWIRE:
  229. if (!string[0])
  230. {
  231. description.function_id = 0;
  232. goto LUAT_PIN_FUNCTION_ANALYZE_DONE;
  233. }
  234. break;
  235. default:
  236. break;
  237. }
  238. }
  239. }
  240. LLOGE("%.*s不是可配置的外设功能", len, string);
  241. description.code = 0xffff;
  242. LUAT_PIN_FUNCTION_ANALYZE_DONE:
  243. if (!description.is_no_use)
  244. {
  245. LLOGD("%.*s find %d,%d,%d", len, string, description.peripheral_type, description.peripheral_id, description.function_id);
  246. }
  247. return description;
  248. }
  249. /**
  250. 当某种外设允许复用在不同引脚上时,指定某个管脚允许复用成某种外设功能,需要在外设启用前配置好,外设启用时起作用。
  251. @api pins.setup(pin, func)
  252. @int 管脚物理编号, 对应模组俯视图下的顺序编号, 例如 67, 68
  253. @string/int 功能说明, 可以直接填写复用功能的altfunction号码, 比如altfunction1写1, 如果不清楚就写具体功能, 例如 "GPIO18", "UART1_TX", "UART1_RX", "SPI1_CLK", "I2C1_CLK", 目前支持的外设有"UART","I2C","SPI","PWM","CAN","GPIO","ONEWIRE"
  254. @return boolean 配置成功,返回true, 其他情况均返回false, 并在日志中提示失败原因
  255. @usage
  256. --把air780epm的PIN67脚,做GPIO 18用, 下面2个等价
  257. --pins.setup(67, "GPIO18")
  258. --pins.setup(67, 4)
  259. --把air780epm的PIN55脚,做uart2 rx用, 下面2个等价
  260. --pins.setup(55, "UART2_RXD")
  261. --pins.setup(55, 2)
  262. --把air780epm的PIN56脚,做uart2 tx用, 下面2个等价
  263. --pins.setup(56, "UART2_TXD")
  264. --pins.setup(56, 2)
  265. */
  266. static int luat_pin_setup(lua_State *L){
  267. size_t len;
  268. int pin = 0;
  269. int result;
  270. int altfun_id;
  271. const char* func_name = NULL;
  272. luat_pin_peripheral_function_description_u func_description;
  273. pin = luaL_optinteger(L, 1, -1);
  274. if (pin < 0)
  275. {
  276. LLOGE("pin序号参数错误");
  277. goto LUAT_PIN_SETUP_DONE;
  278. }
  279. else
  280. {
  281. luat_pin_function_description_t pin_description;
  282. if (luat_pin_get_description_from_num(pin, &pin_description))
  283. {
  284. LLOGE("pin%d不支持修改", pin);
  285. goto LUAT_PIN_SETUP_DONE;
  286. }
  287. altfun_id = luaL_optinteger(L, 2, -1);
  288. if (altfun_id < 0)
  289. {
  290. func_name = luaL_checklstring(L, 2, &len);
  291. if (len < 2)
  292. {
  293. LLOGE("%.*s外设功能描述不正确", len, func_name);
  294. goto LUAT_PIN_SETUP_DONE;
  295. }
  296. func_description = luat_pin_function_analyze(func_name, len);
  297. if (func_description.code == 0xffff)
  298. {
  299. goto LUAT_PIN_SETUP_DONE;
  300. }
  301. altfun_id = luat_pin_get_altfun_id_from_description(func_description.code, &pin_description);
  302. if (altfun_id == 0xff)
  303. {
  304. LLOGE("%.*s不是pin%d的可配置功能", len, func_name, pin);
  305. goto LUAT_PIN_SETUP_DONE;
  306. }
  307. }
  308. else
  309. {
  310. if (altfun_id < LUAT_PIN_ALT_FUNCTION_MAX)
  311. {
  312. func_description.code = pin_description.function_code[altfun_id];
  313. if (func_description.code == 0xffff)
  314. {
  315. LLOGE("没有altfunction%d", altfun_id);
  316. goto LUAT_PIN_SETUP_DONE;
  317. }
  318. }
  319. else
  320. {
  321. LLOGE("没有altfunction%d", altfun_id);
  322. goto LUAT_PIN_SETUP_DONE;
  323. }
  324. }
  325. luat_pin_iomux_info pin_list[LUAT_PIN_FUNCTION_MAX] = {0};
  326. if (!luat_pin_get_iomux_info(func_description.peripheral_type, func_description.peripheral_id, pin_list))
  327. {
  328. pin_list[func_description.function_id].altfun_id = altfun_id;
  329. pin_list[func_description.function_id].uid = pin_description.uid;
  330. if (!luat_pin_set_iomux_info(func_description.peripheral_type, func_description.peripheral_id, pin_list))
  331. {
  332. result = 1;
  333. goto LUAT_PIN_SETUP_DONE;
  334. }
  335. }
  336. if (func_name)
  337. {
  338. LLOGE("%.*s不可配置,请确认硬件手册上该功能可以复用在2个及以上的pin", len, func_name);
  339. }
  340. else
  341. {
  342. LLOGE("altfunction%d不可配置,请确认硬件手册上该功能可以复用在2个及以上的pin", altfun_id);
  343. }
  344. }
  345. LUAT_PIN_SETUP_DONE:
  346. lua_pushboolean(L, result);
  347. return 1;
  348. }
  349. /**
  350. 加载硬件配置,如果存在/luadb/pins.json,开机后自动加载/luadb/pins.json,无需调用
  351. @api pins.load(path)
  352. @string path, 配置文件路径, 可选, 默认值是 /luadb/pins.json
  353. @return boolean 成功返回true, 失败返回false
  354. @usage
  355. pins.load()
  356. pins.load("/my.json")
  357. */
  358. static int luat_pin_load(lua_State *L){
  359. return 1;
  360. }
  361. #include "rotable2.h"
  362. static const rotable_Reg_t reg_pins[] =
  363. {
  364. {"setup", ROREG_FUNC(luat_pin_setup)},
  365. {"load", ROREG_FUNC(luat_pin_load)},
  366. { NULL, ROREG_INT(0) }
  367. };
  368. LUAMOD_API int luaopen_pins( lua_State *L ) {
  369. luat_newlib2(L, reg_pins);
  370. return 1;
  371. }