Munashedov

Untitled

Dec 6th, 2021
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
Add Comment
Please, Sign In to add comment