| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584 |
- #include "s600_can.h"
- #include "s600_iap.h"
- #include "string.h"
- #include "stdlib.h"
- #ifndef CONFIG_CAN_ID
- #error CONFIG_CAN_ID not set
- #endif
- #define S600_CAN_LOOPBACK 0
- static s600_can_packet_t s600_can_tx_packets[5];
- static s600_can_packet_t *s600_can_tx_front;
- static s600_can_packet_t s600_can_rx_packets[10];
- static s600_can_packet_t *s600_can_rx_fronts[10];
- static u8 s600_can_rx_front_len;
- static u8 s600_can_tx_alloc_buff[NELEM(s600_can_tx_packets) + 1];
- static byte_queue_t s600_can_tx_allocator;
- static u8 s600_can_rx_alloc_buff[NELEM(s600_can_rx_packets) + 1];
- static byte_queue_t s600_can_rx_allocator;
- static u8 s600_can_tx_buff[NELEM(s600_can_tx_packets) + 1];
- static byte_queue_t s600_can_tx_queue = { s600_can_tx_buff, NELEM(s600_can_tx_buff), 0, 0 };
- static u8 s600_can_rx_buff[NELEM(s600_can_rx_packets) + 1];
- static byte_queue_t s600_can_rx_queue = { s600_can_rx_buff, NELEM(s600_can_rx_buff), 0, 0 };
- // ================================================================================
- static u32 s600_can_write_position;
- __STATIC_INLINE int s600_can_process_cmd_write_begin(const u8 *buff, u16 length)
- {
- s600_can_write_position = 0;
- s600_iap_write_begin();
- return 0;
- }
- __STATIC_INLINE int s600_can_process_cmd_write_end(const u8 *buff, u16 length)
- {
- u32 size, checksum;
- if (length < 7) {
- return -1;
- }
- size = s600_decode_u24(buff);
- checksum = s600_decode_u32(buff + 3);
- if (s600_iap_write_end(size, checksum)) {
- return 0;
- }
- return -1;
- }
- __STATIC_INLINE int s600_can_process_cmd_write_slow(u8 can, u8 *buff, u16 length)
- {
- u32 position;
- if (length < 3) {
- return -1;
- }
- position = s600_decode_u24(buff);
- if (s600_can_write_position == position) {
- length -= 3;
- s600_iap_write(buff + 3, length);
- s600_can_write_position += length;
- }
- s600_encode_u24(buff + 1, s600_can_write_position);
- return 3;
- }
- __STATIC_INLINE void s600_can_process_command(u8 can, u8 *command, u16 length)
- {
- int rsplen;
- u8 *args;
- u16 key;
- if (length < 2) {
- return;
- }
- key = *(u16 *) command;
- if ((key & 0xFFF0) != S600_CAN_BUILD_CMD(0xF0)) {
- return;
- }
- s600_iap_100ms = 0;
- args = command + 2;
- length -= 2;
- switch (key)
- {
- case S600_CAN_BUILD_CMD(0xF0):
- rsplen = 0;
- break;
- case S600_CAN_BUILD_CMD(0xF1):
- rsplen = s600_can_process_cmd_write_begin(args, length);
- break;
- case S600_CAN_BUILD_CMD(0xF2):
- rsplen = s600_can_process_cmd_write_end(args, length);
- break;
- case S600_CAN_BUILD_CMD(0xF3):
- s600_iap_write(args, length);
- return;
- case S600_CAN_BUILD_CMD(0xF4):
- rsplen = s600_can_process_cmd_write_slow(can, args, length);
- break;
- case S600_CAN_BUILD_CMD(0xF5):
- s600_iap_boot(false);
- rsplen = -1;
- break;
- default:
- rsplen = -1;
- break;
- }
- if (rsplen < 0) {
- rsplen = 0;
- args[0] = 0x01;
- } else {
- args[0] = 0x00;
- }
- s600_can_send_response(can, command, rsplen + 3);
- }
- // ================================================================================
- __STATIC_INLINE void s600_can_rcu_config(void)
- {
- byte_queue_alloc_init(&s600_can_tx_allocator, s600_can_tx_alloc_buff, sizeof(s600_can_tx_alloc_buff));
- byte_queue_alloc_init(&s600_can_rx_allocator, s600_can_rx_alloc_buff, sizeof(s600_can_rx_alloc_buff));
- #if CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PA11_PA12
- rcu_periph_clock_enable(RCU_GPIOA);
- #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PB8_PB9
- rcu_periph_clock_enable(RCU_GPIOB);
- #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PD0_PD1
- rcu_periph_clock_enable(RCU_GPIOD);
- #else
- #error "Invalid CONFIG_CAN_PIN_MAP"
- #endif
- rcu_periph_clock_enable(RCU_AF);
- rcu_periph_clock_enable(RCU_CAN0);
- }
- __STATIC_INLINE void s600_can_gpio_config(void)
- {
- #if CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PA11_PA12
- gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
- gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
- #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PB8_PB9
- gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
- gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
- #ifdef GPIO_CAN0_PARTIAL_REMAP
- gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP, ENABLE);
- #else
- gpio_pin_remap_config(GPIO_CAN_PARTIAL_REMAP, ENABLE);
- #endif
- #elif CONFIG_CAN_PIN_MAP == CAN_PIN_MAP_PD0_PD1
- gpio_init(GPIOD, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
- gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
- gpio_pin_remap_config(GPIO_CAN_FULL_REMAP, ENABLE);
- #else
- #error "Invalid CONFIG_CAN_PIN_MAP"
- #endif
- }
- void s600_can_device_config(void)
- {
- can_parameter_struct can_parameter;
- can_filter_parameter_struct can_filter;
- s600_can_rcu_config();
- s600_can_gpio_config();
- // can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
- // can_struct_para_init(CAN_FILTER_STRUCT, &can_filter);
- can_deinit(CAN0);
- /* initialize CAN parameters */
- can_parameter.time_triggered = DISABLE;
- can_parameter.auto_bus_off_recovery = DISABLE;
- can_parameter.auto_wake_up = DISABLE;
- can_parameter.auto_retrans = DISABLE;
- can_parameter.rec_fifo_overwrite = DISABLE;
- can_parameter.trans_fifo_order = ENABLE;
- can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
- can_parameter.time_segment_1 = CAN_BT_BS1_5TQ;
- can_parameter.time_segment_2 = CAN_BT_BS2_3TQ;
- #if S600_CAN_LOOPBACK
- can_parameter.working_mode = CAN_LOOPBACK_MODE;
- #else
- can_parameter.working_mode = CAN_NORMAL_MODE;
- #endif
- #if S600_CAN_BAUDRATE == 1000
- can_parameter.prescaler = 6;
- #elif S600_CAN_BAUDRATE == 500
- can_parameter.prescaler = 12;
- #elif S600_CAN_BAUDRATE == 250
- can_parameter.prescaler = 24;
- #elif S600_CAN_BAUDRATE == 125
- can_parameter.prescaler = 48;
- #elif S600_CAN_BAUDRATE == 100
- can_parameter.prescaler = 60;
- #elif S600_CAN_BAUDRATE == 50
- can_parameter.prescaler = 120;
- #elif S600_CAN_BAUDRATE == 20
- can_parameter.prescaler = 300;
- #else
- #error "Invalid Baudrate"
- #endif
- /* initialize CAN */
- can_init(CAN0, &can_parameter);
- #ifdef CONFIG_GD32E10X
- can_frequency_set(CAN0, S600_CAN_BAUDRATE * 1000);
- #endif
- /* initialize filter */
- can_filter.filter_number = 0;
- can_filter.filter_mode = CAN_FILTERMODE_MASK;
- can_filter.filter_bits = CAN_FILTERBITS_32BIT;
- can_filter.filter_list_high = 0x0000;
- can_filter.filter_list_low = S600_CAN_DEST_ID(CONFIG_CAN_ID) << 3 | 1 << 2;
- can_filter.filter_mask_high = 0x0000;
- can_filter.filter_mask_low = S600_CAN_DEST_ID(S600_CAN_ALL_ID) << 3 | 1 << 2;
- can_filter.filter_fifo_number = CAN_FIFO1;
- can_filter.filter_enable = ENABLE;
- can_filter_init(&can_filter);
- nvic_irq_enable(CAN0_RX1_IRQn, 0, 0);
- can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE1);
- }
- void s600_can_device_deinit(void)
- {
- nvic_irq_disable(CAN0_RX1_IRQn);
- can_deinit(CAN0);
- }
- u8 s600_can_find_mailbox(void)
- {
- u32 value = CAN_TSTAT(CAN0);
- if ((value & CAN_TSTAT_TME0) != 0) {
- return CAN_MAILBOX0;
- }
- if ((value & CAN_TSTAT_TME1) != 0) {
- return CAN_MAILBOX1;
- }
- if ((value & CAN_TSTAT_TME2) != 0) {
- return CAN_MAILBOX2;
- }
- return CAN_NOMAILBOX;
- }
- u8 s600_can_wait_mailbox(void)
- {
- u32 count;
- for (count = 0; count < 1000000; count++) {
- u8 mailbox = s600_can_find_mailbox();
- if (mailbox != CAN_NOMAILBOX) {
- return mailbox;
- }
- }
- return CAN_NOMAILBOX;
- }
- void s600_can_send_frame(u8 mailbox, u32 efid, const u8 *buff, u8 length)
- {
- /* set the data length */
- CAN_TMP(CAN0, mailbox) &= ~CAN_TMP_DLENC;
- CAN_TMP(CAN0, mailbox) |= length;
- /* set the data */
- CAN_TMDATA0(CAN0, mailbox) = ((const u32 *) buff)[0];
- if (length > 4) {
- CAN_TMDATA1(CAN0, mailbox) = ((const u32 *) buff)[1];
- }
- /* enable transmission */
- CAN_TMI(CAN0, mailbox) = TMI_EFID(efid) | CAN_FF_EXTENDED | CAN_FT_DATA | CAN_TMI_TEN;
- }
- bool s600_can_tx_packet(s600_can_packet_t *packet)
- {
- u8 total, index;
- u8 mailbox;
- u16 length;
- u32 efid;
- mailbox = s600_can_find_mailbox();
- if (mailbox == CAN_NOMAILBOX) {
- return false;
- }
- total = (packet->length + 7) / 8;
- index = packet->offset / 8 + 1;
- efid = 6 << 26 | U32(packet->type) << 24
- | U32(total & 0x1F) << 19 | U32(index & 0x1F) << 14
- | S600_CAN_DEST_ID(packet->dest) | S600_CAN_SRC_ID(packet->src);
- length = packet->length - packet->offset;
- if (length > 8) {
- length = 8;
- }
- s600_can_send_frame(mailbox, efid, packet->data + packet->offset, length);
- packet->offset += length;
- return true;
- }
- __STATIC_INLINE s600_can_packet_t *s600_can_rx_front_get(u8 addr)
- {
- u8 index;
- for (index = 0; index < s600_can_rx_front_len; index++) {
- s600_can_packet_t *packet = s600_can_rx_fronts[index];
- if (packet->src == addr) {
- return packet;
- }
- }
- if (s600_can_rx_front_len < NELEM(s600_can_rx_fronts)) {
- u8 index = byte_queue_alloc(&s600_can_rx_allocator);
- s600_can_packet_t *packet;
- if (index == 0xFF) {
- return NULL;
- }
- packet = s600_can_rx_packets + index;
- packet->src = addr;
- #if S600_CAN_USE_MASK
- packet->mask = 0;
- #else
- packet->index = 0xFF;
- #endif
- s600_can_rx_fronts[s600_can_rx_front_len] = packet;
- s600_can_rx_front_len++;
- return packet;
- }
- return NULL;
- }
- __STATIC_INLINE bool s600_can_rx_front_put(s600_can_packet_t *packet)
- {
- u8 index;
- for (index = 0; index < s600_can_rx_front_len; index++) {
- if (s600_can_rx_fronts[index] == packet) {
- s600_can_rx_front_len--;
- while (index < s600_can_rx_front_len) {
- s600_can_rx_fronts[index] = s600_can_rx_fronts[index + 1];
- index++;
- }
- return true;
- }
- }
- return false;
- }
- bool s600_can_rx_packet(u8 fifo)
- {
- s600_can_packet_t *packet;
- u8 index, total;
- u32 *buff;
- u32 value;
- u32 efid;
- value = CAN_RFIFOMI(CAN0, fifo);
- if ((value & (CAN_RFIFOMI_FT | CAN_RFIFOMI_FF)) != (CAN_FT_DATA | CAN_FF_EXTENDED)) {
- return true;
- }
- efid = GET_RFIFOMI_EFID(value);
- value = CAN_RFIFOMP(CAN0, fifo);
- #ifdef CAN_RFIFOMP_FDF
- if ((value & CAN_RFIFOMP_FDF) != CAN_FDF_CLASSIC) {
- return true;
- }
- #endif
- packet = s600_can_rx_front_get((efid >> 7) & 0x7F);
- if (packet == NULL) {
- return false;
- }
- index = (efid >> 14) & 0x1F;
- total = (efid >> 19) & 0x1F;
- #if S600_CAN_USE_MASK
- if (index == total) {
- packet->dest = efid & 0x7F;
- packet->type = (efid >> 24) & 0x03;
- packet->length = ((total - 1) & 0x1F) << 3;
- packet->length += GET_RFIFOMP_DLENC(value);
- }
- index = (index - 1) & 0x1F;
- if (index == 0) {
- packet->mask = 1;
- } else {
- packet->mask |= 1 << index;
- }
- buff = (u32 *) packet->datas[index];
- buff[0] = CAN_RFIFOMDATA0(CAN0, fifo);
- buff[1] = CAN_RFIFOMDATA1(CAN0, fifo);
- if (total == 0) {
- value = 0xFFFFFFFF;
- } else {
- value = (1 << total) - 1;
- }
- if ((packet->mask & value) == value) {
- byte_queue_write_byte(&s600_can_rx_queue, packet - s600_can_rx_packets);
- s600_can_rx_front_put(packet);
- }
- #else
- if (index != packet->index) {
- if (index != 1) {
- return true;
- }
- packet->type = (efid >> 24) & 0x03;
- packet->dest = efid & 0x7F;
- packet->offset = 0;
- packet->index = 2;
- } else {
- packet->index = (index + 1) & 0x1F;
- }
- buff = (u32 *) (packet->data + packet->offset);
- packet->offset += GET_RFIFOMP_DLENC(value);
- buff[0] = CAN_RFIFOMDATA0(CAN0, fifo);
- buff[1] = CAN_RFIFOMDATA1(CAN0, fifo);
- if (total == index) {
- packet->length = packet->offset;
- byte_queue_write_byte(&s600_can_rx_queue, packet - s600_can_rx_packets);
- s600_can_rx_front_put(packet);
- }
- #endif
- return true;
- }
- void s600_can_transmit(void)
- {
- while (1) {
- u8 index;
- if (s600_can_tx_front) {
- if (s600_can_tx_front->offset < s600_can_tx_front->length) {
- s600_can_tx_packet(s600_can_tx_front);
- break;
- }
- byte_queue_free(&s600_can_tx_allocator, s600_can_tx_front - s600_can_tx_packets);
- }
- if (byte_queue_read(&s600_can_tx_queue, &index, 1) > 0) {
- s600_can_tx_front = s600_can_tx_packets + index;
- } else {
- s600_can_tx_front = NULL;
- break;
- }
- }
- }
- __STATIC_INLINE void s600_can_process_packet(s600_can_packet_t *packet)
- {
- s600_can_process_command(packet->src, packet->data, packet->length);
- }
- void s600_can_poll(void)
- {
- u8 index;
- s600_can_transmit();
- while (byte_queue_read(&s600_can_rx_queue, &index, 1) > 0) {
- s600_can_process_packet(s600_can_rx_packets + index);
- byte_queue_free(&s600_can_rx_allocator, index);
- }
- }
- bool s600_can_send_packet(u8 dest, u8 src, u8 type, const void *data, u16 length)
- {
- s600_can_packet_t *packet;
- u8 index;
- index = byte_queue_alloc(&s600_can_tx_allocator);
- if (index == 0xFF) {
- return false;
- }
- packet = s600_can_tx_packets + index;
- packet->offset = 0;
- packet->type = type;
- packet->dest = dest;
- packet->src = src;
- packet->length = length;
- memcpy(packet->data, data, length);
- byte_queue_write_byte(&s600_can_tx_queue, index);
- s600_can_transmit();
- return true;
- }
- void s600_can_send_packet_block(u8 dest, u8 src, u8 type, const void *data, u16 length)
- {
- while (!s600_can_send_packet(dest, src, type, data, length)) {
- s600_can_transmit();
- }
- }
- bool s600_can_send_command(u8 addr, const void *command, u16 length)
- {
- return s600_can_send_packet(addr, CONFIG_CAN_ID, 1, command, length);
- }
- bool s600_can_send_response(u8 addr, const void *response, u16 length)
- {
- return s600_can_send_packet(addr, CONFIG_CAN_ID, 2, response, length);
- }
- bool s600_can_send_event(u8 addr, const void *event, u16 length)
- {
- return s600_can_send_packet(addr, CONFIG_CAN_ID, 3, event, length);
- }
- // ================================================================================
- void CAN0_RX1_IRQHandler(void)
- {
- s600_can_rx_packet(CAN_FIFO1);
- CAN_RFIFO1(CAN0) |= CAN_RFIFO1_RFD1;
- }
|