luat_lib_can.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. @module can
  3. @summary can操作库
  4. @version 1.0
  5. @date 2025.2.24
  6. @demo can
  7. @tag LUAT_USE_CAN
  8. */
  9. #include "luat_base.h"
  10. #include "luat_sys.h"
  11. #include "luat_msgbus.h"
  12. #include "luat_mem.h"
  13. #include "luat_can.h"
  14. #include "luat_zbuff.h"
  15. #include "c_common.h"
  16. #define LUAT_LOG_TAG "can"
  17. #include "luat_log.h"
  18. #include "rotable2.h"
  19. #define MAX_DEVICE_COUNT 2
  20. static int l_can_cb[MAX_DEVICE_COUNT];
  21. static uint8_t l_can_debug_flag;
  22. static int l_can_handler(lua_State *L, void* ptr)
  23. {
  24. (void)ptr;
  25. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  26. lua_pop(L, 1);
  27. int can_id = msg->arg1;
  28. if (l_can_debug_flag) LLOGD("callback %d,%d,%x", can_id, msg->arg2, msg->ptr);
  29. if (l_can_cb[can_id])
  30. {
  31. lua_geti(L, LUA_REGISTRYINDEX, l_can_cb[can_id]);
  32. if (lua_isfunction(L, -1))
  33. {
  34. lua_pushinteger(L, can_id);
  35. switch(msg->arg2)
  36. {
  37. case LUAT_CAN_CB_NEW_MSG:
  38. lua_pushinteger(L, msg->arg2);
  39. lua_pushnil(L);
  40. break;
  41. case LUAT_CAN_CB_TX_OK:
  42. lua_pushinteger(L, msg->arg2);
  43. lua_pushboolean(L, 1);
  44. break;
  45. case LUAT_CAN_CB_TX_FAILED:
  46. lua_pushinteger(L, LUAT_CAN_CB_TX_OK);
  47. lua_pushboolean(L, 0);
  48. break;
  49. case LUAT_CAN_CB_ERROR_REPORT:
  50. lua_pushinteger(L, msg->arg2);
  51. lua_pushinteger(L, (uint32_t)msg->ptr);
  52. break;
  53. case LUAT_CAN_CB_STATE_CHANGE:
  54. lua_pushinteger(L, msg->arg2);
  55. lua_pushinteger(L, (uint32_t)msg->ptr);
  56. break;
  57. }
  58. lua_call(L, 3, 0);
  59. }
  60. }
  61. // 给rtos.recv方法返回个空数据
  62. lua_pushinteger(L, 0);
  63. return 1;
  64. }
  65. static void l_can_callback(int can_id, LUAT_CAN_CB_E cb_type, void *cb_param)
  66. {
  67. rtos_msg_t msg;
  68. msg.handler = l_can_handler;
  69. msg.ptr = cb_param;
  70. msg.arg1 = can_id;
  71. msg.arg2 = cb_type;
  72. luat_msgbus_put(&msg, 0);
  73. }
  74. /*
  75. CAN总线初始化
  76. @api can.init(id, rx_message_cache_max)
  77. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  78. @int rx_message_cache_max,接收缓存消息数的最大值,写0或者留空则使用平台默认值
  79. @return boolean 成功返回true,失败返回false
  80. @usage
  81. can.init()
  82. */
  83. static int l_can_init(lua_State *L)
  84. {
  85. int ret = luat_can_base_init(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, 0));
  86. if (ret)
  87. {
  88. LLOGE("init failed %d", ret);
  89. lua_pushboolean(L, 0);
  90. }
  91. else
  92. {
  93. lua_pushboolean(L, 1);
  94. }
  95. return 1;
  96. }
  97. /*
  98. 注册CAN事件回调
  99. @api can.on(id, func)
  100. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  101. @function 回调方法
  102. @return nil 无返回值
  103. @usage
  104. can.on(1, function(id, type, param)
  105. log.info("can", id, type, param)
  106. end)
  107. */
  108. static int l_can_on(lua_State *L) {
  109. int id = luaL_optinteger(L, 1, 0);
  110. if (id >= MAX_DEVICE_COUNT)
  111. {
  112. id = 0;
  113. }
  114. if (l_can_cb[id] != 0)
  115. {
  116. luaL_unref(L, LUA_REGISTRYINDEX, l_can_cb[id]);
  117. }
  118. if (lua_isfunction(L, 2))
  119. {
  120. lua_pushvalue(L, 2);
  121. luat_can_set_callback(id, l_can_callback);
  122. l_can_cb[id] = luaL_ref(L, LUA_REGISTRYINDEX);
  123. }
  124. else
  125. {
  126. luat_can_set_callback(id, NULL);
  127. }
  128. return 0;
  129. }
  130. /*
  131. CAN总线配置时序
  132. @api can.timing(id, br, PTS, PBS1, PBS2, SJW)
  133. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  134. @int br, 波特率, 默认1Mbps
  135. @int PTS, 传播时间段, 范围1~8,默认5
  136. @int PBS1, 相位缓冲段1,范围1~8,默认4
  137. @int PBS2, 相位缓冲段2,范围2~8,默认3
  138. @int SJW, 同步补偿宽度值,范围1~4,默认2
  139. @return boolean 成功返回true,失败返回false
  140. @usage
  141. can.timing(0, 1000000, 5, 4, 3, 2)
  142. can.timing(0, 650000, 9, 6, 4, 2)
  143. can.timing(0, 500000, 5, 4, 3, 2)
  144. can.timing(0, 250000, 5, 4, 3, 2)
  145. can.timing(0, 125000, 5, 4, 3, 2)
  146. can.timing(0, 100000, 5, 4, 3, 2)
  147. can.timing(0, 50000, 9, 6, 4, 2)
  148. can.timing(0, 25000, 9, 6, 4, 2)
  149. */
  150. static int l_can_timing(lua_State *L)
  151. {
  152. int ret = luat_can_set_timing(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, 1000000),
  153. luaL_optinteger(L, 3, 5), luaL_optinteger(L, 4, 4), luaL_optinteger(L, 5, 3),
  154. luaL_optinteger(L, 6, 2));
  155. if (ret)
  156. {
  157. LLOGE("set timing failed %d", ret);
  158. lua_pushboolean(L, 0);
  159. }
  160. else
  161. {
  162. lua_pushboolean(L, 1);
  163. }
  164. return 1;
  165. }
  166. /*
  167. CAN总线设置工作模式
  168. @api can.mode(id, mode)
  169. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  170. @int mode, 见MODE_XXX,默认是MODE_NORMAL
  171. @return boolean 成功返回true,失败返回false
  172. @usage
  173. can.mode(0, CAN.MODE_NORMAL)
  174. */
  175. static int l_can_mode(lua_State *L)
  176. {
  177. int ret = luat_can_set_work_mode(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, LUAT_CAN_WORK_MODE_NORMAL));
  178. if (ret)
  179. {
  180. LLOGE("set mode failed %d", ret);
  181. lua_pushboolean(L, 0);
  182. }
  183. else
  184. {
  185. lua_pushboolean(L, 1);
  186. }
  187. return 1;
  188. }
  189. /*
  190. CAN总线设置节点ID,这是一种简易的过滤规则,只接收和ID完全匹配的消息,和can.filter选择一个使用
  191. @api can.node(id, node_id, id_type)
  192. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  193. @int node_id, 节点ID, 标准格式11位或者扩展格式29位,根据id_type决定,默认值是0x1fffffff,id值越小,优先级越高
  194. @int id_type,ID类型,填1或者CAN.EXT为扩展格式,填0或者CAN.STD为标准格式
  195. @return boolean 成功返回true,失败返回false
  196. @usage
  197. can.node(0, 0x12345678, CAN.EXT)
  198. can.node(0, 0x123, CAN.STD)
  199. */
  200. static int l_can_node(lua_State *L)
  201. {
  202. int ret = luat_can_set_node(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, 0x1fffffff), luaL_optinteger(L, 3, 1));
  203. if (ret)
  204. {
  205. LLOGE("set node failed %d", ret);
  206. lua_pushboolean(L, 0);
  207. }
  208. else
  209. {
  210. lua_pushboolean(L, 1);
  211. }
  212. return 1;
  213. }
  214. /*
  215. CAN总线设置接收过滤模式,当can.node不满足需求时才使用这个,和can.node选择一个使用,过滤模式比较复杂,请参考SJA1000的Pelican模式下滤波
  216. @api can.filter(id, dual_mode, ACR, AMR)
  217. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  218. @boolean dual_mode, 是否是双过滤模式,true是,false不是,默认是false
  219. @int ACR, 接收代码寄存器值,必须写0xnnnnnnnn这样的格式,大端格式赋值到4个ACR寄存器上,默认值是0
  220. @int AMR, 接收屏蔽寄存器值,必须写0xnnnnnnnn这样的格式,大端格式赋值到4个AMR寄存器上,对应bit写0表示需要检测,写1表示不检测,默认是0xffffffff,不过滤全接收
  221. @return boolean 成功返回true,失败返回false
  222. @usage
  223. can.filter(0, false, 0x12345678 << 3, 0x07) --效果等同于can.node(0, 0x12345678, CAN.EXT)
  224. can.filter(0, false, 0x123 << 21, 0x0001fffff) --效果等同于can.node(0, 0x123, CAN.STD)
  225. */
  226. static int l_can_filter(lua_State *L)
  227. {
  228. uint32_t mask = luaL_optinteger(L, 4, 0xffffffff);
  229. uint32_t node_id = luaL_optinteger(L, 3, 0);
  230. uint8_t ACR[4];
  231. uint8_t AMR[4];
  232. uint8_t dual_mode = lua_toboolean(L,2);
  233. BytesPutBe32(ACR, node_id);
  234. BytesPutBe32(AMR, mask);
  235. int ret = luat_can_set_filter(luaL_optinteger(L, 1, 0), dual_mode, ACR, AMR);
  236. if (ret)
  237. {
  238. LLOGE("set filter failed %d", ret);
  239. lua_pushboolean(L, 0);
  240. }
  241. else
  242. {
  243. lua_pushboolean(L, 1);
  244. }
  245. return 1;
  246. }
  247. /*
  248. CAN工作状态
  249. @api can.state(id)
  250. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  251. @return int 返回值见STATE_XXX
  252. @usage
  253. can.state(0)
  254. */
  255. static int l_can_state(lua_State *L)
  256. {
  257. lua_pushinteger(L, luat_can_get_state(luaL_optinteger(L, 1, 0)));
  258. return 1;
  259. }
  260. /*
  261. CAN发送一条消息
  262. @api can.tx(id, msg_id, id_type, RTR, need_ack, data)
  263. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  264. @int msg_id, 节点ID, 标准格式11位或者扩展格式29位,根据id_type决定,默认值是0x1fffffff,id值越小,优先级越高
  265. @int id_type, ID类型,填1或者CAN.EXT为扩展格式,填0或者CAN.STD为标准格式
  266. @boolean RTR, 是否是遥控帧,true是,false不是,默认是false
  267. @boolean need_ack,是否需要应答,true是,false不需要,默认是true
  268. @string/zbuff data, 需要发送的数据, 如果是zbuff会从指针起始位置开始发送,最多发送8字节
  269. @return boolean 成功返回true,失败返回false
  270. @usage
  271. can.tx(id, 0x12345678, CAN.EXT, false, true, "\x00\x01\x02\x03\0x04\x05\0x6\x07")
  272. */
  273. static int l_can_tx(lua_State *L)
  274. {
  275. size_t len;
  276. const char *buf;
  277. uint32_t id = luaL_optinteger(L, 2, 0x1fffffff);
  278. if(lua_isuserdata(L, 6))
  279. {
  280. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 6, LUAT_ZBUFF_TYPE));
  281. len = buff->used;
  282. buf = (const char *)(buff->addr);
  283. }
  284. else
  285. {
  286. buf = lua_tolstring(L, 6, &len);//取出字符串数据
  287. }
  288. if (len > 8) len = 8;
  289. lua_pushinteger(L, luat_can_tx_message(luaL_optinteger(L, 1, 0), id, luaL_optinteger(L, 3, 0), lua_toboolean(L, 4), lua_toboolean(L, 5), len, buf));
  290. return 1;
  291. }
  292. /*
  293. 从缓存里读出一条消息
  294. @api can.rx(id)
  295. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  296. @return boolean 是否读出数据,true读出,false没有读出,缓存已经空了,或者id不对
  297. @return int 消息ID
  298. @return int ID类型,1或者CAN.EXT为扩展格式,0或者CAN.STD为标准格式
  299. @return boolean 是否是遥控帧,true是,false不是
  300. @return string 数据
  301. @usage
  302. local succ, id, type, rtr, data = can.rx(0)
  303. */
  304. static int l_can_rx(lua_State *L)
  305. {
  306. luat_can_message_t msg = {0};
  307. int id = luaL_optinteger(L, 1, 0);
  308. if (luat_can_rx_message_from_cache(id, &msg) > 0)
  309. {
  310. lua_pushboolean(L, 1);
  311. lua_pushinteger(L, msg.id);
  312. lua_pushinteger(L, msg.is_extend);
  313. lua_pushboolean(L, msg.RTR);
  314. lua_pushlstring(L, (const char*)msg.data, msg.len);
  315. }
  316. else
  317. {
  318. lua_pushboolean(L, 0);
  319. lua_pushnil(L);
  320. lua_pushnil(L);
  321. lua_pushnil(L);
  322. lua_pushnil(L);
  323. }
  324. return 5;
  325. }
  326. /*
  327. 立刻停止当前的发送
  328. @api can.stop(id)
  329. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  330. @return boolean 成功返回true,失败返回false
  331. @usage
  332. can.stop(0)
  333. */
  334. static int l_can_stop(lua_State *L)
  335. {
  336. int id = luaL_optinteger(L, 1, 0);
  337. if (luat_can_tx_stop(id))
  338. {
  339. lua_pushboolean(L, 0);
  340. }
  341. else
  342. {
  343. lua_pushboolean(L, 1);
  344. }
  345. return 1;
  346. }
  347. /*
  348. CAN总线复位,一般用于从总线关闭状态恢复成主动错误
  349. @api can.reset(id)
  350. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  351. @return boolean 成功返回true,失败返回false
  352. @usage
  353. can.reset(0)
  354. */
  355. static int l_can_reset(lua_State *L)
  356. {
  357. if (luat_can_reset(luaL_optinteger(L, 1, 0)))
  358. {
  359. lua_pushboolean(L, 0);
  360. }
  361. else
  362. {
  363. lua_pushboolean(L, 1);
  364. }
  365. return 1;
  366. }
  367. /*
  368. CAN完全关闭
  369. @api can.deinit(id)
  370. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  371. @return boolean 成功返回true,失败返回false
  372. @usage
  373. can.state(0)
  374. */
  375. static int l_can_deinit(lua_State *L)
  376. {
  377. if (luat_can_close(luaL_optinteger(L, 1, 0)))
  378. {
  379. lua_pushboolean(L, 0);
  380. }
  381. else
  382. {
  383. lua_pushboolean(L, 1);
  384. }
  385. return 1;
  386. }
  387. /*
  388. CAN debug开关,打开后有更详细的打印
  389. @api can.debug(on_off)
  390. @boolean true打开,false关闭
  391. @return nil
  392. @usage
  393. can.debug(true)
  394. */
  395. static int l_can_debug(lua_State *L)
  396. {
  397. l_can_debug_flag = lua_toboolean(L, 1);
  398. luat_can_set_debug(l_can_debug_flag);
  399. return 0;
  400. }
  401. static const rotable_Reg_t reg_can[] =
  402. {
  403. { "init", ROREG_FUNC(l_can_init)},
  404. { "on", ROREG_FUNC(l_can_on)},
  405. { "timing", ROREG_FUNC(l_can_timing)},
  406. { "mode", ROREG_FUNC(l_can_mode)},
  407. { "node", ROREG_FUNC(l_can_node)},
  408. { "filter", ROREG_FUNC(l_can_filter)},
  409. { "state", ROREG_FUNC(l_can_state)},
  410. { "tx", ROREG_FUNC(l_can_tx)},
  411. { "rx", ROREG_FUNC(l_can_rx)},
  412. { "stop", ROREG_FUNC(l_can_stop)},
  413. { "reset", ROREG_FUNC(l_can_reset)},
  414. { "deinit", ROREG_FUNC(l_can_deinit)},
  415. { "debug", ROREG_FUNC(l_can_debug)},
  416. //@const MODE_NORMAL number 正常工作模式
  417. { "MODE_NORMAL", ROREG_INT(LUAT_CAN_WORK_MODE_NORMAL)},
  418. //@const MODE_LISTEN number 监听模式
  419. { "MODE_LISTEN", ROREG_INT(LUAT_CAN_WORK_MODE_ONLY_LISTEN)},
  420. //@const MODE_TEST number 自测模式
  421. { "MODE_TEST", ROREG_INT(LUAT_CAN_WORK_MODE_SELF_TEST)},
  422. //@const MODE_SLEEP number 休眠模式
  423. { "MODE_SLEEP", ROREG_INT(LUAT_CAN_WORK_MODE_SLEEP)},
  424. //@const STATE_STOP number 停止工作状态
  425. { "STATE_STOP", ROREG_INT(LUAT_CAN_STOP)},
  426. //@const STATE_ACTIVE number 主动错误状态,一般都是这个状态
  427. { "STATE_ACTIVE", ROREG_INT(LUAT_CAN_ACTIVE_ERROR)},
  428. //@const STATE_PASSIVE number 被动错误状态,总线上错误多会进入这个状态,但是还能正常收发
  429. { "STATE_PASSIVE", ROREG_INT(LUAT_CAN_PASSIVE_ERROR)},
  430. //@const STATE_BUSOFF number 离线状态,总线上错误非常多会进入这个状态,不能收发,需要手动退出
  431. { "STATE_BUSOFF", ROREG_INT(LUAT_CAN_BUS_OFF)},
  432. //@const STATE_LISTEN number 监听状态,选择监听模式时进入这个状态
  433. { "STATE_LISTEN", ROREG_INT(LUAT_CAN_ONLY_LISTEN)},
  434. //@const STATE_TEST number 自收自发状态,选择自测模式时进入这个状态
  435. { "STATE_TEST", ROREG_INT(LUAT_CAN_SELF_TEST)},
  436. //@const STATE_SLEEP number 休眠状态,选择休眠模式时进入这个状态
  437. { "STATE_SLEEP", ROREG_INT(LUAT_CAN_SLEEP)},
  438. //@const CB_MSG number 回调消息类型,有新数据写入缓存
  439. { "CB_MSG", ROREG_INT(LUAT_CAN_CB_NEW_MSG)},
  440. //@const CB_TX number 回调消息类型,数据发送结束,需要根据后续param确定发送成功还是失败
  441. { "CB_TX", ROREG_INT(LUAT_CAN_CB_TX_OK)},
  442. //@const CB_ERR number 回调消息类型,有错误报告,后续param是错误码
  443. { "CB_ERR", ROREG_INT(LUAT_CAN_CB_ERROR_REPORT)},
  444. //@const CB_STATE number 回调消息类型,总线状态变更,后续param是新的状态,也可以用can.state读出
  445. { "CB_STATE", ROREG_INT(LUAT_CAN_CB_STATE_CHANGE)},
  446. //@const STATE_TEST number 自收自发状态,选择自测模式时进入这个状态
  447. { "EXT", ROREG_INT(1)},
  448. //@const STATE_SLEEP number 休眠状态,选择休眠模式时进入这个状态
  449. { "STD", ROREG_INT(0)},
  450. { NULL, ROREG_INT(0) }
  451. };
  452. LUAMOD_API int luaopen_can( lua_State *L )
  453. {
  454. luat_newlib2(L, reg_can);
  455. return 1;
  456. }