Guest User

c

a guest
Dec 6th, 2021
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.75 KB | None | 0 0
  1. #include <freertos/FreeRTOS.h>
  2. #include <freertos/queue.h>
  3. #include <freertos/event_groups.h>
  4. #include <driver/can.h>
  5. #include <nvs_flash.h>
  6. #include <esp_task_wdt.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <sys/time.h>
  10. #include "can.h"
  11. #include "hci.h"
  12.  
  13. const int can_tx_pin = GPIO_NUM_0;
  14. const int can_rx_pin = GPIO_NUM_2;
  15.  
  16. struct
  17. {
  18. can_timing_config_t timing;
  19. can_filter_config_t filter;
  20. can_message_t periodic_messages[8];
  21. uint8_t flags; /* initialized, rx */
  22. } can_config;
  23.  
  24. can_general_config_t config =
  25. {
  26. .mode = CAN_MODE_NORMAL,
  27. .tx_io = can_tx_pin,
  28. .rx_io = can_rx_pin,
  29. .clkout_io = -1,
  30. .bus_off_io = -1,
  31. .tx_queue_len = 10,
  32. .rx_queue_len = 10,
  33. .alerts_enabled = CAN_ALERT_NONE,
  34. .clkout_divider = 0
  35. };
  36.  
  37. const uint8_t CAN_FLAG_INIT = 1 << 0;
  38. const uint8_t CAN_FLAG_RX_ON = 1 << 1;
  39. static QueueHandle_t can_rx_queue;
  40. static EventBits_t can_reinstall_done = 1 << 0;
  41. static EventGroupHandle_t can_event_group;
  42. struct can_rx_event
  43. {
  44. uint8_t event;
  45. };
  46.  
  47. enum
  48. {
  49. EVENT_CAN_RX_OFF = 0,
  50. EVENT_CAN_RX_ON = 1,
  51. EVENT_CAN_REINSTALL = 2
  52. };
  53.  
  54.  
  55. int can_init()
  56. {
  57. esp_err_t err;
  58. /* Setup default timing */
  59. can_config.timing.brp = 8;
  60. can_config.timing.tseg_1 = 5;
  61. can_config.timing.tseg_2 = 4;
  62. can_config.timing.sjw = 1;
  63. /* Setup default filter */
  64. can_config.filter.acceptance_code = 0;
  65. can_config.filter.acceptance_mask = 0xffffffff;
  66. can_config.filter.single_filter = 1;
  67. err = can_driver_install(&config, &can_config.timing, &can_config.filter);
  68.  
  69. if(err != ESP_OK)
  70. {
  71. printf("ERR CAN init failed!\n");
  72. return -1;
  73. }
  74.  
  75. err = can_start();
  76. if(err != ESP_OK)
  77. {
  78. printf("ERR CAN init failed!\n");
  79. return -1;
  80. }
  81.  
  82. can_event_group = xEventGroupCreate();
  83. can_config.flags |= CAN_FLAG_INIT;
  84. return 0;
  85. }
  86.  
  87. int can_reinstall()
  88. {
  89. esp_err_t err;
  90. can_stop();
  91. can_driver_uninstall();
  92. /* Setup default timing */
  93. err = can_driver_install(&config, &can_config.timing, &can_config.filter);
  94. if(err != ESP_OK)
  95. return -1;
  96. err = can_start();
  97. if(err != ESP_OK)
  98. return -1;
  99. return 0;
  100. }
  101.  
  102. int parse_message_format(can_message_t *msg, const char *fmt)
  103. {
  104. uint32_t id;
  105. char remote;
  106. memset(msg, 0, sizeof(*msg));
  107. sscanf(fmt, "%x#%c", &id, &remote);
  108. msg->flags |= CAN_MSG_FLAG_SS;
  109. if(remote == 'R')
  110. {
  111. msg->flags |= CAN_MSG_FLAG_RTR;
  112. msg->identifier = id;
  113. msg->data_length_code = 0;
  114. }
  115. else
  116. {
  117. int data[8];
  118. int ret = sscanf(fmt, "%x#%2x%2x%2x%2x%2x%2x%2x%2x",
  119. &id, &data[0], &data[1], &data[2], &data[3],
  120. &data[4], &data[5], &data[6], &data[7]);
  121. if(ret < 1)
  122. return -1;
  123. int len = ret - 1;
  124. msg->identifier = id;
  125. msg->data_length_code = len;
  126. for(int i = 0; i < len; i++)
  127. msg->data[i] = data[i];
  128. }
  129.  
  130. return 0;
  131. }
  132.  
  133. void can_command()
  134. {
  135. char *cmd = strtok(NULL, " ");
  136. esp_err_t err;
  137. /* Make sure we have a command */
  138. if(!cmd)
  139. goto einval;
  140. /*
  141. * Compare commande against known commands and handle them, otherwise tell
  142. * the user it was invalid.
  143. */
  144. if(strcmp(cmd, "help") == 0)
  145. {
  146. printf("OK\n");
  147. printf(
  148. "Available commands:\n"
  149. "Source clock: 80 MHz\n"
  150. "CAN bitrate = 80 000 000 / brp / (1 + tseg_1 + tseg_2)\n"
  151. "\n"
  152. "can help - write this text\n"
  153. "can rx on/off - enable or disable RX\n"
  154. "can send <id>#<data in hex> - e.g. send 13f#02e8\n"
  155. "can config brp [value] - get or set current can brp (2-128, even)\n"
  156. "can config tseg_1 [value] - get or set current can tseg_1 (1-16)\n"
  157. "can config tseg_2 [value] - get or set current can tseg_2 (1-8)\n"
  158. "can config sjw [value] - get or set current can sjw (1-4)\n"
  159. "\n");
  160. }
  161. else if(strcmp(cmd, "rx") == 0)
  162. {
  163. const char *arg = strtok(NULL, " ");
  164.  
  165. if(strcmp(arg, "on") == 0)
  166. can_rx_on();
  167. else if(strcmp(arg, "off") == 0)
  168. can_rx_off();
  169. else
  170. goto einval;
  171. }
  172. else if(strcmp(cmd, "send") == 0)
  173. {
  174. can_message_t msg;
  175. const char *msg_str = strtok(NULL, " ");
  176.  
  177. memset(&msg, 0, sizeof(msg));
  178. if(parse_message_format(&msg, msg_str) < 0)
  179. goto einval;
  180. struct timeval current_time;
  181. gettimeofday(&current_time, NULL);
  182. /* printf("seconds : %ld\nmicro seconds : %ld", current_time.tv_sec, current_time.tv_usec); */
  183. /* unsigned long currentMillis = xTaskGetTickCount(); */
  184. unsigned long time_in_micros = 1000000 * current_time.tv_sec + current_time.tv_usec;
  185. printf("T: %ld SENT %x#", time_in_micros, msg.identifier);
  186. for(int i = 0; i < msg.data_length_code; i++)
  187. printf("%02x", msg.data[i]);
  188. printf("\n");
  189. err = can_transmit(&msg, 0);
  190. if(err != ESP_OK)
  191. {
  192. printf("ERR Transmit failed!\n");
  193. /*
  194. * If we get to many transmission errors due to non-acked frames
  195. * then the bus will go into an error state, restart it by
  196. * reinstalling it.
  197. */
  198. can_send_reinstall();
  199. return;
  200. }
  201.  
  202. }
  203. else if(strcmp(cmd, "sendex") == 0)
  204. {
  205. can_message_t msg;
  206. const char *msg_str = strtok(NULL, " ");
  207.  
  208. memset(&msg, 0, sizeof(msg));
  209. if(parse_message_format(&msg, msg_str) < 0)
  210. goto einval;
  211. msg.extd = 1;
  212. struct timeval current_time;
  213. gettimeofday(&current_time, NULL);
  214. /* printf("seconds : %ld\nmicro seconds : %ld", current_time.tv_sec, current_time.tv_usec); */
  215. /* unsigned long currentMillis = xTaskGetTickCount(); */
  216. unsigned long time_in_micros = 1000000 * current_time.tv_sec + current_time.tv_usec;
  217. printf("T: %ld SENT %x#", time_in_micros, msg.identifier);
  218. for(int i = 0; i < msg.data_length_code; i++)
  219. printf("%02x", msg.data[i]);
  220. printf("\n");
  221. err = can_transmit(&msg, 0);
  222. if(err != ESP_OK)
  223. {
  224. printf("ERR Transmit failed!\n");
  225.  
  226. /*
  227. * If we get to many transmission errors due to non-acked frames
  228. * then the bus will go into an error state, restart it by
  229. * reinstalling it.
  230. */
  231. can_send_reinstall();
  232.  
  233. return;
  234. }
  235.  
  236. }
  237. else if(strcmp(cmd, "config") == 0)
  238. {
  239. /* Read value argument */
  240. const char *arg = strtok(NULL, " ");
  241. if(!arg)
  242. goto einval;
  243. if(strcmp(arg, "brp") == 0)
  244. {
  245. const char *value_str = strtok(NULL, " ");
  246. if(!value_str)
  247. printf("OK %d\n", can_config.timing.brp);
  248.  
  249. else
  250. {
  251. int value = atoi(value_str);
  252.  
  253. if(value < 2 || value > 127 || value % 2)
  254. goto einval;
  255. can_config.timing.brp = value;
  256. can_send_reinstall();
  257. }
  258. }
  259. else if(strcmp(arg, "tseg_1") == 0)
  260. {
  261. const char *value_str = strtok(NULL, " ");
  262. if(!value_str)
  263. printf("OK %d\n", can_config.timing.tseg_1);
  264. else
  265. {
  266. int value = atoi(value_str);
  267. if(value < 1 || value > 16 )
  268. goto einval;
  269. can_config.timing.tseg_1 = value;
  270. can_send_reinstall();
  271. }
  272. }
  273. else if(strcmp(arg, "tseg_2") == 0)
  274. {
  275. const char *value_str = strtok(NULL, " ");
  276. if(!value_str)
  277. printf("OK %d\n", can_config.timing.tseg_2);
  278. else
  279. {
  280. int value = atoi(value_str);
  281. if(value < 1 || value > 8 )
  282. goto einval;
  283. can_config.timing.tseg_2 = value;
  284. can_send_reinstall();
  285. }
  286. }
  287. else if(strcmp(arg, "sjw") == 0)
  288. {
  289. const char *value_str = strtok(NULL, " ");
  290. if(!value_str)
  291. printf("OK %d\n", can_config.timing.sjw);
  292. else
  293. {
  294. int value = atoi(value_str);
  295. if(value < 1 || value > 4 )
  296. goto einval;
  297. can_config.timing.sjw = value;
  298. can_send_reinstall();
  299. }
  300. }
  301. else
  302. goto einval;
  303. }
  304. else if(strcmp(cmd, "status") == 0)
  305. {
  306. }
  307. else
  308. goto einval;
  309. return;
  310.  
  311. einval:
  312. printf("INVALID COMMAND");
  313. return;
  314. }
  315.  
  316. void can_rx_off()
  317. {
  318. struct can_rx_event event =
  319. {
  320. .event = EVENT_CAN_RX_OFF
  321. };
  322. xQueueSendToBack(can_rx_queue, &event, 0);
  323. }
  324.  
  325. void can_rx_on()
  326. {
  327. struct can_rx_event event =
  328. {
  329. .event = EVENT_CAN_RX_ON
  330. };
  331. xQueueSendToBack(can_rx_queue, &event, 0);
  332. }
  333.  
  334. void can_send_reinstall()
  335. {
  336. struct can_rx_event event =
  337. {
  338. .event = EVENT_CAN_REINSTALL
  339. };
  340. xQueueSendToBack(can_rx_queue, &event, 0);
  341. /* Wait for reinstallation done */
  342. xEventGroupWaitBits(can_event_group, can_reinstall_done, 1, 1, 1000 * portTICK_PERIOD_MS);
  343. }
  344.  
  345. void can_rx_thread(void *parameters)
  346. {
  347. /* Check that CAN initialized correctly */
  348. while(!(can_config.flags & CAN_FLAG_INIT))
  349. vTaskDelay(100 * portTICK_PERIOD_MS);
  350. esp_task_wdt_delete(xTaskGetCurrentTaskHandle());
  351. can_rx_queue = xQueueCreate(10, sizeof(struct can_rx_event));
  352. int rx_running = 0;
  353.  
  354. while(1)
  355. {
  356. can_message_t msg;
  357. while(can_receive(&msg, 10) == ESP_OK)
  358. {
  359. /* AUTOPING */
  360. /* can_transmit(&msg, 0); */
  361. /* AUTOPING */
  362. if(rx_running)
  363. {
  364.  
  365. struct timeval tvr;
  366. gettimeofday(&tvr, NULL);
  367. /* unsigned long currentMillis = xTaskGetTickCount(); */
  368. unsigned long time_in_micros = 1000000 * tvr.tv_sec + tvr.tv_usec;
  369. printf("T: %ld CAN RX: %x#", time_in_micros, msg.identifier);
  370. if(msg.flags & CAN_MSG_FLAG_RTR)
  371. printf("R");
  372. else
  373. for(int i = 0; i < msg.data_length_code; i++)
  374. printf("%02x", msg.data[i]);
  375. /*
  376. if (msg.extd)
  377. printf("Message is in Extended Format\n");
  378. else
  379. printf("Message is in Standard Format\n");
  380. */
  381.  
  382. printf("\n");
  383. }
  384. }
  385.  
  386. struct can_rx_event event;
  387. if(xQueueReceive(can_rx_queue, &event, 0))
  388. {
  389. if(event.event == EVENT_CAN_RX_OFF)
  390. {
  391. rx_running = 0;
  392. printf("OK\n");
  393. }
  394.  
  395. else if(event.event == EVENT_CAN_RX_ON)
  396. {
  397. rx_running = 1;
  398. printf("OK\n");
  399. }
  400.  
  401. else if(event.event == EVENT_CAN_REINSTALL)
  402. {
  403. if(can_reinstall() < 0)
  404. printf("ERR Unknown error\n");
  405. else
  406. printf("OK\n");
  407. /* Also perform a full recovery which helps on bus-off recovery */
  408. can_initiate_recovery();
  409.  
  410. while(1)
  411. {
  412. twai_status_info_t info;
  413. twai_get_status_info(&info);
  414. if(info.state != CAN_STATE_RECOVERING)
  415. break;
  416. }
  417.  
  418. xEventGroupSetBits(can_event_group, can_reinstall_done);
  419. }
  420. }
  421. }
  422. }
Advertisement
Add Comment
Please, Sign In to add comment