s600_can.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. #include "s600_can.h"
  2. #include "s600_iap.h"
  3. #include "string.h"
  4. #include "stdlib.h"
  5. #ifndef CONFIG_CAN_ID
  6. #error CONFIG_CAN_ID not set
  7. #endif
  8. #define S600_CAN_LOOPBACK 0
  9. static s600_can_packet_t s600_can_tx_packets[5];
  10. static s600_can_packet_t *s600_can_tx_front;
  11. static s600_can_packet_t s600_can_rx_packets[10];
  12. static s600_can_packet_t *s600_can_rx_fronts[10];
  13. static u8 s600_can_rx_front_len;
  14. static u8 s600_can_tx_alloc_buff[NELEM(s600_can_tx_packets) + 1];
  15. static byte_queue_t s600_can_tx_allocator;
  16. static u8 s600_can_rx_alloc_buff[NELEM(s600_can_rx_packets) + 1];
  17. static byte_queue_t s600_can_rx_allocator;
  18. static u8 s600_can_tx_buff[NELEM(s600_can_tx_packets) + 1];
  19. static byte_queue_t s600_can_tx_queue = { s600_can_tx_buff, NELEM(s600_can_tx_buff), 0, 0 };
  20. static u8 s600_can_rx_buff[NELEM(s600_can_rx_packets) + 1];
  21. static byte_queue_t s600_can_rx_queue = { s600_can_rx_buff, NELEM(s600_can_rx_buff), 0, 0 };
  22. // ================================================================================
  23. static u32 s600_can_write_position;
  24. __STATIC_INLINE int s600_can_process_cmd_write_begin(const u8 *buff, u16 length)
  25. {
  26. s600_can_write_position = 0;
  27. s600_iap_write_begin();
  28. return 0;
  29. }
  30. __STATIC_INLINE int s600_can_process_cmd_write_end(const u8 *buff, u16 length)
  31. {
  32. u32 size, checksum;
  33. if (length < 7) {
  34. return -1;
  35. }
  36. size = s600_decode_u24(buff);
  37. checksum = s600_decode_u32(buff + 3);
  38. if (s600_iap_write_end(size, checksum)) {
  39. return 0;
  40. }
  41. return -1;
  42. }
  43. __STATIC_INLINE int s600_can_process_cmd_write_slow(u8 can, u8 *buff, u16 length)
  44. {
  45. u32 position;
  46. if (length < 3) {
  47. return -1;
  48. }
  49. position = s600_decode_u24(buff);
  50. if (s600_can_write_position == position) {
  51. length -= 3;
  52. s600_iap_write(buff + 3, length);
  53. s600_can_write_position += length;
  54. }
  55. s600_encode_u24(buff + 1, s600_can_write_position);
  56. return 3;
  57. }
  58. __STATIC_INLINE void s600_can_process_command(u8 can, u8 *command, u16 length)
  59. {
  60. int rsplen;
  61. u8 *args;
  62. u16 key;
  63. if (length < 2) {
  64. return;
  65. }
  66. key = *(u16 *) command;
  67. if ((key & 0xFFF0) != S600_CAN_BUILD_CMD(0xF0)) {
  68. return;
  69. }
  70. s600_iap_100ms = 0;
  71. args = command + 2;
  72. length -= 2;
  73. switch (key)
  74. {
  75. case S600_CAN_BUILD_CMD(0xF0):
  76. rsplen = 0;
  77. break;
  78. case S600_CAN_BUILD_CMD(0xF1):
  79. rsplen = s600_can_process_cmd_write_begin(args, length);
  80. break;
  81. case S600_CAN_BUILD_CMD(0xF2):
  82. rsplen = s600_can_process_cmd_write_end(args, length);
  83. break;
  84. case S600_CAN_BUILD_CMD(0xF3):
  85. s600_iap_write(args, length);
  86. return;
  87. case S600_CAN_BUILD_CMD(0xF4):
  88. rsplen = s600_can_process_cmd_write_slow(can, args, length);
  89. break;
  90. case S600_CAN_BUILD_CMD(0xF5):
  91. s600_iap_boot(false);
  92. rsplen = -1;
  93. break;
  94. default:
  95. rsplen = -1;
  96. break;
  97. }
  98. if (rsplen < 0) {
  99. rsplen = 0;
  100. args[0] = 0x01;
  101. } else {
  102. args[0] = 0x00;
  103. }
  104. s600_can_send_response(can, command, rsplen + 3);
  105. }
  106. // ================================================================================
  107. __STATIC_INLINE void s600_can_rcu_config(void)
  108. {
  109. byte_queue_alloc_init(&s600_can_tx_allocator, s600_can_tx_alloc_buff, sizeof(s600_can_tx_alloc_buff));
  110. byte_queue_alloc_init(&s600_can_rx_allocator, s600_can_rx_alloc_buff, sizeof(s600_can_rx_alloc_buff));
  111. #if CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PA11_PA12
  112. rcu_periph_clock_enable(RCU_GPIOA);
  113. #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PB8_PB9
  114. rcu_periph_clock_enable(RCU_GPIOB);
  115. #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PD0_PD1
  116. rcu_periph_clock_enable(RCU_GPIOD);
  117. #else
  118. #error "Invalid CONFIG_CAN_PIN_MAP"
  119. #endif
  120. rcu_periph_clock_enable(RCU_AF);
  121. rcu_periph_clock_enable(RCU_CAN0);
  122. }
  123. __STATIC_INLINE void s600_can_gpio_config(void)
  124. {
  125. #if CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PA11_PA12
  126. gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
  127. gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
  128. #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PB8_PB9
  129. gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
  130. gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
  131. #ifdef GPIO_CAN0_PARTIAL_REMAP
  132. gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP, ENABLE);
  133. #else
  134. gpio_pin_remap_config(GPIO_CAN_PARTIAL_REMAP, ENABLE);
  135. #endif
  136. #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PD0_PD1
  137. gpio_init(GPIOD, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
  138. gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
  139. gpio_pin_remap_config(GPIO_CAN_FULL_REMAP, ENABLE);
  140. #else
  141. #error "Invalid CONFIG_CAN_PIN_MAP"
  142. #endif
  143. }
  144. void s600_can_device_config(void)
  145. {
  146. can_parameter_struct can_parameter;
  147. can_filter_parameter_struct can_filter;
  148. s600_can_rcu_config();
  149. s600_can_gpio_config();
  150. // can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
  151. // can_struct_para_init(CAN_FILTER_STRUCT, &can_filter);
  152. can_deinit(CAN0);
  153. /* initialize CAN parameters */
  154. can_parameter.time_triggered = DISABLE;
  155. can_parameter.auto_bus_off_recovery = DISABLE;
  156. can_parameter.auto_wake_up = DISABLE;
  157. can_parameter.auto_retrans = DISABLE;
  158. can_parameter.rec_fifo_overwrite = DISABLE;
  159. can_parameter.trans_fifo_order = ENABLE;
  160. can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
  161. can_parameter.time_segment_1 = CAN_BT_BS1_5TQ;
  162. can_parameter.time_segment_2 = CAN_BT_BS2_3TQ;
  163. #if S600_CAN_LOOPBACK
  164. can_parameter.working_mode = CAN_LOOPBACK_MODE;
  165. #else
  166. can_parameter.working_mode = CAN_NORMAL_MODE;
  167. #endif
  168. #if S600_CAN_BAUDRATE == 1000
  169. can_parameter.prescaler = 6;
  170. #elif S600_CAN_BAUDRATE == 500
  171. can_parameter.prescaler = 12;
  172. #elif S600_CAN_BAUDRATE == 250
  173. can_parameter.prescaler = 24;
  174. #elif S600_CAN_BAUDRATE == 125
  175. can_parameter.prescaler = 48;
  176. #elif S600_CAN_BAUDRATE == 100
  177. can_parameter.prescaler = 60;
  178. #elif S600_CAN_BAUDRATE == 50
  179. can_parameter.prescaler = 120;
  180. #elif S600_CAN_BAUDRATE == 20
  181. can_parameter.prescaler = 300;
  182. #else
  183. #error "Invalid Baudrate"
  184. #endif
  185. /* initialize CAN */
  186. can_init(CAN0, &can_parameter);
  187. #ifdef CONFIG_GD32E10X
  188. can_frequency_set(CAN0, S600_CAN_BAUDRATE * 1000);
  189. #endif
  190. /* initialize filter */
  191. can_filter.filter_number = 0;
  192. can_filter.filter_mode = CAN_FILTERMODE_MASK;
  193. can_filter.filter_bits = CAN_FILTERBITS_32BIT;
  194. can_filter.filter_list_high = 0x0000;
  195. can_filter.filter_list_low = S600_CAN_DEST_ID(CONFIG_CAN_ID) << 3 | 1 << 2;
  196. can_filter.filter_mask_high = 0x0000;
  197. can_filter.filter_mask_low = S600_CAN_DEST_ID(S600_CAN_ALL_ID) << 3 | 1 << 2;
  198. can_filter.filter_fifo_number = CAN_FIFO1;
  199. can_filter.filter_enable = ENABLE;
  200. can_filter_init(&can_filter);
  201. nvic_irq_enable(CAN0_RX1_IRQn, 0, 0);
  202. can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE1);
  203. }
  204. void s600_can_device_deinit(void)
  205. {
  206. nvic_irq_disable(CAN0_RX1_IRQn);
  207. can_deinit(CAN0);
  208. }
  209. u8 s600_can_find_mailbox(void)
  210. {
  211. u32 value = CAN_TSTAT(CAN0);
  212. if ((value & CAN_TSTAT_TME0) != 0) {
  213. return CAN_MAILBOX0;
  214. }
  215. if ((value & CAN_TSTAT_TME1) != 0) {
  216. return CAN_MAILBOX1;
  217. }
  218. if ((value & CAN_TSTAT_TME2) != 0) {
  219. return CAN_MAILBOX2;
  220. }
  221. return CAN_NOMAILBOX;
  222. }
  223. u8 s600_can_wait_mailbox(void)
  224. {
  225. u32 count;
  226. for (count = 0; count < 1000000; count++) {
  227. u8 mailbox = s600_can_find_mailbox();
  228. if (mailbox != CAN_NOMAILBOX) {
  229. return mailbox;
  230. }
  231. }
  232. return CAN_NOMAILBOX;
  233. }
  234. void s600_can_send_frame(u8 mailbox, u32 efid, const u8 *buff, u8 length)
  235. {
  236. /* set the data length */
  237. CAN_TMP(CAN0, mailbox) &= ~CAN_TMP_DLENC;
  238. CAN_TMP(CAN0, mailbox) |= length;
  239. /* set the data */
  240. CAN_TMDATA0(CAN0, mailbox) = ((const u32 *) buff)[0];
  241. if (length > 4) {
  242. CAN_TMDATA1(CAN0, mailbox) = ((const u32 *) buff)[1];
  243. }
  244. /* enable transmission */
  245. CAN_TMI(CAN0, mailbox) = TMI_EFID(efid) | CAN_FF_EXTENDED | CAN_FT_DATA | CAN_TMI_TEN;
  246. }
  247. bool s600_can_tx_packet(s600_can_packet_t *packet)
  248. {
  249. u8 total, index;
  250. u8 mailbox;
  251. u16 length;
  252. u32 efid;
  253. mailbox = s600_can_find_mailbox();
  254. if (mailbox == CAN_NOMAILBOX) {
  255. return false;
  256. }
  257. total = (packet->length + 7) / 8;
  258. index = packet->offset / 8 + 1;
  259. efid = 6 << 26 | U32(packet->type) << 24
  260. | U32(total & 0x1F) << 19 | U32(index & 0x1F) << 14
  261. | S600_CAN_DEST_ID(packet->dest) | S600_CAN_SRC_ID(packet->src);
  262. length = packet->length - packet->offset;
  263. if (length > 8) {
  264. length = 8;
  265. }
  266. s600_can_send_frame(mailbox, efid, packet->data + packet->offset, length);
  267. packet->offset += length;
  268. return true;
  269. }
  270. __STATIC_INLINE s600_can_packet_t *s600_can_rx_front_get(u8 addr)
  271. {
  272. u8 index;
  273. for (index = 0; index < s600_can_rx_front_len; index++) {
  274. s600_can_packet_t *packet = s600_can_rx_fronts[index];
  275. if (packet->src == addr) {
  276. return packet;
  277. }
  278. }
  279. if (s600_can_rx_front_len < NELEM(s600_can_rx_fronts)) {
  280. u8 index = byte_queue_alloc(&s600_can_rx_allocator);
  281. s600_can_packet_t *packet;
  282. if (index == 0xFF) {
  283. return NULL;
  284. }
  285. packet = s600_can_rx_packets + index;
  286. packet->src = addr;
  287. #if S600_CAN_USE_MASK
  288. packet->mask = 0;
  289. #else
  290. packet->index = 0xFF;
  291. #endif
  292. s600_can_rx_fronts[s600_can_rx_front_len] = packet;
  293. s600_can_rx_front_len++;
  294. return packet;
  295. }
  296. return NULL;
  297. }
  298. __STATIC_INLINE bool s600_can_rx_front_put(s600_can_packet_t *packet)
  299. {
  300. u8 index;
  301. for (index = 0; index < s600_can_rx_front_len; index++) {
  302. if (s600_can_rx_fronts[index] == packet) {
  303. s600_can_rx_front_len--;
  304. while (index < s600_can_rx_front_len) {
  305. s600_can_rx_fronts[index] = s600_can_rx_fronts[index + 1];
  306. index++;
  307. }
  308. return true;
  309. }
  310. }
  311. return false;
  312. }
  313. bool s600_can_rx_packet(u8 fifo)
  314. {
  315. s600_can_packet_t *packet;
  316. u8 index, total;
  317. u32 *buff;
  318. u32 value;
  319. u32 efid;
  320. value = CAN_RFIFOMI(CAN0, fifo);
  321. if ((value & (CAN_RFIFOMI_FT | CAN_RFIFOMI_FF)) != (CAN_FT_DATA | CAN_FF_EXTENDED)) {
  322. return true;
  323. }
  324. efid = GET_RFIFOMI_EFID(value);
  325. value = CAN_RFIFOMP(CAN0, fifo);
  326. #ifdef CAN_RFIFOMP_FDF
  327. if ((value & CAN_RFIFOMP_FDF) != CAN_FDF_CLASSIC) {
  328. return true;
  329. }
  330. #endif
  331. packet = s600_can_rx_front_get((efid >> 7) & 0x7F);
  332. if (packet == NULL) {
  333. return false;
  334. }
  335. index = (efid >> 14) & 0x1F;
  336. total = (efid >> 19) & 0x1F;
  337. #if S600_CAN_USE_MASK
  338. if (index == total) {
  339. packet->dest = efid & 0x7F;
  340. packet->type = (efid >> 24) & 0x03;
  341. packet->length = ((total - 1) & 0x1F) << 3;
  342. packet->length += GET_RFIFOMP_DLENC(value);
  343. }
  344. index = (index - 1) & 0x1F;
  345. if (index == 0) {
  346. packet->mask = 1;
  347. } else {
  348. packet->mask |= 1 << index;
  349. }
  350. buff = (u32 *) packet->datas[index];
  351. buff[0] = CAN_RFIFOMDATA0(CAN0, fifo);
  352. buff[1] = CAN_RFIFOMDATA1(CAN0, fifo);
  353. if (total == 0) {
  354. value = 0xFFFFFFFF;
  355. } else {
  356. value = (1 << total) - 1;
  357. }
  358. if ((packet->mask & value) == value) {
  359. byte_queue_write_byte(&s600_can_rx_queue, packet - s600_can_rx_packets);
  360. s600_can_rx_front_put(packet);
  361. }
  362. #else
  363. if (index != packet->index) {
  364. if (index != 1) {
  365. return true;
  366. }
  367. packet->type = (efid >> 24) & 0x03;
  368. packet->dest = efid & 0x7F;
  369. packet->offset = 0;
  370. packet->index = 2;
  371. } else {
  372. packet->index = (index + 1) & 0x1F;
  373. }
  374. buff = (u32 *) (packet->data + packet->offset);
  375. packet->offset += GET_RFIFOMP_DLENC(value);
  376. buff[0] = CAN_RFIFOMDATA0(CAN0, fifo);
  377. buff[1] = CAN_RFIFOMDATA1(CAN0, fifo);
  378. if (total == index) {
  379. packet->length = packet->offset;
  380. byte_queue_write_byte(&s600_can_rx_queue, packet - s600_can_rx_packets);
  381. s600_can_rx_front_put(packet);
  382. }
  383. #endif
  384. return true;
  385. }
  386. void s600_can_transmit(void)
  387. {
  388. while (1) {
  389. u8 index;
  390. if (s600_can_tx_front) {
  391. if (s600_can_tx_front->offset < s600_can_tx_front->length) {
  392. s600_can_tx_packet(s600_can_tx_front);
  393. break;
  394. }
  395. byte_queue_free(&s600_can_tx_allocator, s600_can_tx_front - s600_can_tx_packets);
  396. }
  397. if (byte_queue_read(&s600_can_tx_queue, &index, 1) > 0) {
  398. s600_can_tx_front = s600_can_tx_packets + index;
  399. } else {
  400. s600_can_tx_front = NULL;
  401. break;
  402. }
  403. }
  404. }
  405. __STATIC_INLINE void s600_can_process_packet(s600_can_packet_t *packet)
  406. {
  407. s600_can_process_command(packet->src, packet->data, packet->length);
  408. }
  409. void s600_can_poll(void)
  410. {
  411. u8 index;
  412. s600_can_transmit();
  413. while (byte_queue_read(&s600_can_rx_queue, &index, 1) > 0) {
  414. s600_can_process_packet(s600_can_rx_packets + index);
  415. byte_queue_free(&s600_can_rx_allocator, index);
  416. }
  417. }
  418. bool s600_can_send_packet(u8 dest, u8 src, u8 type, const void *data, u16 length)
  419. {
  420. s600_can_packet_t *packet;
  421. u8 index;
  422. index = byte_queue_alloc(&s600_can_tx_allocator);
  423. if (index == 0xFF) {
  424. return false;
  425. }
  426. packet = s600_can_tx_packets + index;
  427. packet->offset = 0;
  428. packet->type = type;
  429. packet->dest = dest;
  430. packet->src = src;
  431. packet->length = length;
  432. memcpy(packet->data, data, length);
  433. byte_queue_write_byte(&s600_can_tx_queue, index);
  434. s600_can_transmit();
  435. return true;
  436. }
  437. void s600_can_send_packet_block(u8 dest, u8 src, u8 type, const void *data, u16 length)
  438. {
  439. while (!s600_can_send_packet(dest, src, type, data, length)) {
  440. s600_can_transmit();
  441. }
  442. }
  443. bool s600_can_send_command(u8 addr, const void *command, u16 length)
  444. {
  445. return s600_can_send_packet(addr, CONFIG_CAN_ID, 1, command, length);
  446. }
  447. bool s600_can_send_response(u8 addr, const void *response, u16 length)
  448. {
  449. return s600_can_send_packet(addr, CONFIG_CAN_ID, 2, response, length);
  450. }
  451. bool s600_can_send_event(u8 addr, const void *event, u16 length)
  452. {
  453. return s600_can_send_packet(addr, CONFIG_CAN_ID, 3, event, length);
  454. }
  455. // ================================================================================
  456. void CAN0_RX1_IRQHandler(void)
  457. {
  458. s600_can_rx_packet(CAN_FIFO1);
  459. CAN_RFIFO1(CAN0) |= CAN_RFIFO1_RFD1;
  460. }