ethercat_domain.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /**
  2. * RT-Thread RuiChing
  3. *
  4. * COPYRIGHT (C) 2024-2025 Shanghai Real-Thread Electronic Technology Co., Ltd.
  5. * All rights reserved.
  6. *
  7. * The license and distribution terms for this file may be
  8. * found in the file LICENSE in this distribution.
  9. */
  10. #include "rtthread.h"
  11. #include <stdint.h>
  12. #include <stdlib.h>
  13. #ifdef COMP_USING_ETHERCAT
  14. #include "ecat_master.h"
  15. #define EC_TIMEOUTRXM 700000
  16. #define THREAD_PRIORITY 18
  17. #define THREAD_STACK_SIZE 5120
  18. #define THREAD_TIMESLICE 5
  19. #define BUFF_SIZE 256
  20. #define MOTOR_START_STEP_NUM 10
  21. struct rt_rpmsg_ep_addr
  22. {
  23. const char *name;
  24. rt_uint32_t src;
  25. rt_uint32_t dst;
  26. };
  27. #pragma pack(1)
  28. struct rpdo_csp
  29. {
  30. uint8_t mode_byte;
  31. uint16_t control_word;
  32. int32_t dest_pos;
  33. int32_t dest_speed;
  34. int16_t dest_torque;
  35. };
  36. struct tpdo_csp
  37. {
  38. uint16_t error_word;
  39. uint16_t status_word;
  40. int32_t cur_pos;
  41. int32_t cur_speed;
  42. int16_t curr_torque;
  43. };
  44. typedef struct
  45. {
  46. int slave;
  47. uint8_t run;
  48. uint8_t dir;
  49. uint8_t mode;
  50. uint8_t rev;
  51. uint32_t ctrl_value;
  52. int32_t dest_pos;
  53. int32_t cur_pos;
  54. int32_t rpm;
  55. } motorctrl_data_t;
  56. #pragma pack()
  57. motorctrl_data_t ctrl_data;
  58. static rt_sem_t dynamic_sem = RT_NULL;
  59. static struct rt_device *rpmsg = RT_NULL;
  60. static rt_thread_t thread = RT_NULL;
  61. static rt_bool_t is_inited = RT_FALSE;
  62. static rt_int32_t motor_ctrl_value = 0;
  63. static struct rt_rpmsg_ep_addr rpmsg_remote_echo = {
  64. "rpmsg_chrdev", 0x3001U, 0x1001
  65. };
  66. static uint8_t process_data[4096];
  67. static ec_master_t csp_master = {
  68. .name = "master1",
  69. .nic0 = "e1",
  70. .main_cycletime_us = 1000, // 1ms
  71. .sub_cycletime_us = 5000, // 5ms
  72. .recovery_timeout_ms = 3000, // 3s
  73. .process_data = process_data,
  74. .process_data_size = 4096,
  75. .dc_active = 1,
  76. .dc_cycltime0 = 5000000,
  77. .dc_cyclshift = 1000,
  78. .dc_index = 1,
  79. .net_mode = EC_NET_MODE_EXCLUSIVE,
  80. .priority = 1,
  81. };
  82. static ec_pdo_entry_info_t slave1_output_pdo_entries[] = {
  83. { 0x6060, 0x00, 8 }, // 6060h(mode)
  84. { 0x6040, 0x00, 16 }, // 6040h(control)
  85. { 0x607A, 0x00, 32 }, // 607Ah(dest position)
  86. { 0x60FF, 0x00, 32 }, // 60FFh(dest speed)
  87. { 0x6071, 0x00, 16 }, // 6071h(dest torque)
  88. };
  89. static ec_pdo_entry_info_t slave1_input_pdo_entries[] = {
  90. { 0x603F, 0x00, 16 }, // 603Fh(error)
  91. { 0x6041, 0x00, 16 }, // 6041h(status)
  92. { 0x6064, 0x00, 32 }, // 6064h(current postion)
  93. { 0x606C, 0x00, 32 }, // 606Ch(current speed)
  94. { 0x6077, 0x00, 16 }, // 6077h(current torque)
  95. };
  96. ec_pdo_info_t slave_pdos[] = {
  97. { 0x1600, 5, slave1_output_pdo_entries },
  98. { 0x1a00, 5, slave1_input_pdo_entries },
  99. };
  100. ec_sync_info_t slave_syncs[] = {
  101. { 2, EC_DIR_OUTPUT, 1, &slave_pdos[0], EC_WD_DISABLE },
  102. { 3, EC_DIR_INPUT, 1, &slave_pdos[1], EC_WD_DISABLE },
  103. };
  104. static void servo_switch_op(struct rpdo_csp *output, struct tpdo_csp *input)
  105. {
  106. int sta;
  107. struct rpdo_csp *data = (struct rpdo_csp *)(output);
  108. struct tpdo_csp *status = (struct tpdo_csp *)(input);
  109. sta = status->status_word & 0x3ff;
  110. if (status->status_word & 0x8)
  111. {
  112. data->control_word = 0x80;
  113. }
  114. else
  115. {
  116. // swtich servo stattus, ref cia402
  117. switch (sta)
  118. {
  119. case 0x250:
  120. case 0x270:
  121. data->control_word = 0x6;
  122. ;
  123. break;
  124. case 0x231: data->control_word = 0x7; break;
  125. case 0x233: data->control_word = 0xf; break;
  126. default:
  127. // data->control_word = 0x6;
  128. break;
  129. }
  130. }
  131. }
  132. static void rpmsg_ethercat_read(void *parameter)
  133. {
  134. rt_uint32_t len = 0;
  135. rt_uint8_t buff[BUFF_SIZE];
  136. while ((len = rt_device_read(rpmsg, rpmsg_remote_echo.src, buff, BUFF_SIZE - 1)) >= 0)
  137. {
  138. motorctrl_data_t *data = (motorctrl_data_t*)&buff;
  139. ctrl_data.ctrl_value = data->ctrl_value;
  140. ctrl_data.run = data->run;
  141. ctrl_data.dir = data->dir;
  142. }
  143. }
  144. static void rpmsg_ethercat_write(void *parameter)
  145. {
  146. while (rt_sem_take(dynamic_sem, RT_WAITING_FOREVER) == RT_EOK)
  147. {
  148. rt_device_write(rpmsg, rpmsg_remote_echo.dst, &ctrl_data, sizeof(motorctrl_data_t));
  149. }
  150. }
  151. extern void ecat_config_service_init(ec_master_t *m);
  152. int ethercat_domain_init(void)
  153. {
  154. rt_err_t ret = RT_EOK, err;
  155. static uint8_t inited = 0;
  156. int slave_counts;
  157. uint16_t state;
  158. rt_thread_mdelay(5000);
  159. if (inited)
  160. {
  161. rt_kprintf("ethercat always running!\n");
  162. return ret;
  163. }
  164. if(is_inited == RT_TRUE)
  165. return RT_EOK;
  166. rpmsg = rt_device_find("rpmsg");
  167. if (rpmsg == RT_NULL)
  168. {
  169. rt_kprintf("Unable to find rpmsg device.\r\n");
  170. return RT_ERROR;
  171. }
  172. rt_device_open(rpmsg, RT_DEVICE_OFLAG_OPEN);
  173. rt_device_control(rpmsg, RT_DEVICE_CTRL_CONFIG, &rpmsg_remote_echo);
  174. dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_PRIO);
  175. if (dynamic_sem == RT_NULL)
  176. {
  177. return -1;
  178. }
  179. thread = rt_thread_create("rpmsg_ethercat_read",
  180. rpmsg_ethercat_read, RT_NULL,
  181. THREAD_STACK_SIZE,
  182. THREAD_PRIORITY, THREAD_TIMESLICE);
  183. if (thread != RT_NULL)
  184. rt_thread_startup(thread);
  185. thread = rt_thread_create("rpmsg_ethercat_write",
  186. rpmsg_ethercat_write, RT_NULL,
  187. THREAD_STACK_SIZE,
  188. THREAD_PRIORITY, THREAD_TIMESLICE);
  189. if (thread != RT_NULL)
  190. rt_thread_startup(thread);
  191. if(ret != RT_EOK)
  192. {
  193. return RT_ERROR;
  194. }
  195. is_inited = RT_TRUE;
  196. rt_kprintf("rpmsg ethercat init end.\r\n");
  197. ctrl_data.ctrl_value = 300;
  198. ctrl_data.mode = 1;
  199. /* ethercat service init */
  200. ecat_service_init();
  201. err = ecat_master_init(&csp_master);
  202. if (err)
  203. {
  204. rt_kprintf("ethercat master init failed, err:%d\n", err);
  205. return err;
  206. }
  207. slave_counts = ecat_slavecount(&csp_master);
  208. rt_kprintf("Found slaves count:%d\n", slave_counts);
  209. static ec_slave_config_t slave_cia402_config;
  210. slave_cia402_config.dc_assign_activate = 0x300;
  211. slave_cia402_config.dc_sync[0].cycle_time = csp_master.main_cycletime_us * 1000;
  212. slave_cia402_config.dc_sync[0].shift_time = 500000;
  213. slave_cia402_config.dc_sync[1].cycle_time = 0;
  214. slave_cia402_config.dc_sync[1].shift_time = 0;
  215. slave_cia402_config.sync = slave_syncs;
  216. slave_cia402_config.sync_count = sizeof(slave_syncs) / sizeof(ec_sync_info_t);
  217. ecat_slave_config(&csp_master, 0, &slave_cia402_config);
  218. ecat_master_start(&csp_master);
  219. state = EC_STATE_OPERATIONAL;
  220. err = ecat_check_state(&csp_master, 0, &state, 20000000 * 3);
  221. if (err != RT_EOK)
  222. {
  223. rt_kprintf("Not all slaves reached operational mode.\n");
  224. return err;
  225. }
  226. struct rpdo_csp *rmap = (struct rpdo_csp *)(csp_master.process_data);
  227. struct tpdo_csp *tmap =
  228. (struct tpdo_csp *)(csp_master.process_data + sizeof(struct rpdo_csp));
  229. rmap->mode_byte = 0x8;
  230. while (1)
  231. {
  232. servo_switch_op(rmap, tmap);
  233. struct rpdo_csp *data = (struct rpdo_csp *)(rmap);
  234. struct tpdo_csp *status = (struct tpdo_csp *)(tmap);
  235. if (ctrl_data.run)
  236. {
  237. if (data->control_word == 7)
  238. {
  239. data->dest_pos = status->cur_pos;
  240. }
  241. else if (data->control_word == 0xf)
  242. {
  243. motor_ctrl_value += MOTOR_START_STEP_NUM;
  244. if (motor_ctrl_value >= ctrl_data.ctrl_value)
  245. {
  246. motor_ctrl_value = ctrl_data.ctrl_value;
  247. }
  248. if (ctrl_data.dir)
  249. {
  250. data->dest_pos -= motor_ctrl_value;
  251. }
  252. else
  253. {
  254. data->dest_pos += motor_ctrl_value;
  255. }
  256. ctrl_data.dest_pos = data->dest_pos;
  257. }
  258. }
  259. else
  260. {
  261. if (motor_ctrl_value != 0)
  262. {
  263. if (data->control_word == 7)
  264. {
  265. rmap->mode_byte = 0x8;
  266. data->dest_pos = status->cur_pos;
  267. }
  268. else if (data->control_word == 0xf)
  269. {
  270. motor_ctrl_value -= MOTOR_START_STEP_NUM;
  271. if (motor_ctrl_value <= 0)
  272. {
  273. motor_ctrl_value = 0;
  274. }
  275. if (ctrl_data.dir)
  276. {
  277. data->dest_pos -= motor_ctrl_value;
  278. }
  279. else
  280. {
  281. data->dest_pos += motor_ctrl_value;
  282. }
  283. ctrl_data.dest_pos = data->dest_pos;
  284. }
  285. }
  286. else
  287. {
  288. data->dest_pos = status->cur_pos;
  289. data->control_word = 0x0;
  290. if(abs(ctrl_data.dest_pos - data->dest_pos) > 3)
  291. {
  292. ctrl_data.dest_pos = data->dest_pos;
  293. }
  294. }
  295. }
  296. ctrl_data.cur_pos = status->cur_pos;
  297. ctrl_data.rpm = ctrl_data.ctrl_value * 60000 / 3600;
  298. rt_sem_release(dynamic_sem);
  299. rt_thread_delay(5);
  300. }
  301. return 0;
  302. }
  303. MSH_CMD_EXPORT(ethercat_domain_init, ethercat domain init);
  304. void rpmsg_send_data_sync(void)
  305. {
  306. if(is_inited != RT_TRUE)
  307. return ;
  308. rt_sem_release(dynamic_sem);
  309. }
  310. int motor_run(void)
  311. {
  312. ctrl_data.run = 1;
  313. rpmsg_send_data_sync();
  314. return 0;
  315. }
  316. MSH_CMD_EXPORT(motor_run, motor run);
  317. int motor_stop(void)
  318. {
  319. ctrl_data.run = 0;
  320. rpmsg_send_data_sync();
  321. return 0;
  322. }
  323. MSH_CMD_EXPORT(motor_stop, motor stop);
  324. void motor_dir(int argc, char *argv[])
  325. {
  326. if (argc == 2)
  327. {
  328. if (atoi(argv[1]) == 0)
  329. {
  330. ctrl_data.dir = 0;
  331. }
  332. else
  333. {
  334. ctrl_data.dir = 1;
  335. }
  336. }
  337. rpmsg_send_data_sync();
  338. }
  339. MSH_CMD_EXPORT(motor_dir, motor dir);
  340. #endif /* COMP_USING_ETHERCAT */