From aa8a6f4cf1a50724a61fd0ee6a80590677856b21 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 11 Apr 2023 11:20:57 -0400 Subject: [PATCH] lib: Update to latest can2040 code Avoid some gcc warnings by using uint32_t for iterators Better document the fallthough case statement in crc_bytes() Fix txpending race from report_line_ackdone() Make can2040_transmit() multi-cpu atomic Signed-off-by: Kevin O'Connor --- lib/README | 2 +- lib/can2040/can2040.c | 32 ++++++++++++++++++++------------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/README b/lib/README index 84bfcb56..ce24bce6 100644 --- a/lib/README +++ b/lib/README @@ -155,7 +155,7 @@ used to upload firmware to devices flashed with the CanBoot bootloader. The can2040 directory contains code from: https://github.com/KevinOConnor/can2040 -revision 177b0073fe6f19281ee7f7fdbe9599e32d1b4b8b. +revision d1190afcaa6245c20da28199d06e453d2e743099. The Huada HC32F460 directory contains code from: https://www.hdsc.com.cn/Category83-1490 diff --git a/lib/can2040/can2040.c b/lib/can2040/can2040.c index fb9e3fb6..759f0974 100644 --- a/lib/can2040/can2040.c +++ b/lib/can2040/can2040.c @@ -267,7 +267,7 @@ pio_tx_send(struct can2040 *cd, uint32_t *data, uint32_t count) pio_hw_t *pio_hw = cd->pio_hw; pio_tx_reset(cd); pio_hw->instr_mem[can2040_offset_tx_got_recessive] = 0xa242; // nop [2] - int i; + uint32_t i; for (i=0; itxf[3] = data[i]; struct pio_sm_hw *sm = &pio_hw->sm[3]; @@ -351,7 +351,7 @@ pio_sm_setup(struct can2040 *cd) pio_signal_set_txpending(cd); // Load pio program - int i; + uint32_t i; for (i=0; iinstr_mem[i] = can2040_program_instructions[i]; @@ -436,9 +436,9 @@ static inline uint32_t crc_bytes(uint32_t crc, uint32_t data, uint32_t num) { switch (num) { - default: crc = crc_byte(crc, data >> 24); - case 3: crc = crc_byte(crc, data >> 16); - case 2: crc = crc_byte(crc, data >> 8); + default: crc = crc_byte(crc, data >> 24); /* FALLTHRU */ + case 3: crc = crc_byte(crc, data >> 16); /* FALLTHRU */ + case 2: crc = crc_byte(crc, data >> 8); /* FALLTHRU */ case 1: crc = crc_byte(crc, data); } return crc; @@ -647,14 +647,19 @@ tx_schedule_transmit(struct can2040 *cd) if (cd->tx_state == TS_QUEUED && !pio_tx_did_fail(cd)) // Already queued or actively transmitting return 0; - if (cd->tx_push_pos == cd->tx_pull_pos) { + uint32_t tx_pull_pos = cd->tx_pull_pos; + if (readl(&cd->tx_push_pos) == tx_pull_pos) { // No new messages to transmit cd->tx_state = TS_IDLE; pio_signal_clear_txpending(cd); - return SI_TXPENDING; + __DMB(); + if (likely(readl(&cd->tx_push_pos) == tx_pull_pos)) + return SI_TXPENDING; + // Raced with can2040_transmit() - msg is now available for transmit + pio_signal_set_txpending(cd); } cd->tx_state = TS_QUEUED; - struct can2040_transmit *qt = &cd->tx_queue[tx_qpos(cd, cd->tx_pull_pos)]; + struct can2040_transmit *qt = &cd->tx_queue[tx_qpos(cd, tx_pull_pos)]; pio_tx_send(cd, qt->stuffed_data, qt->stuffed_words); return 0; } @@ -717,7 +722,7 @@ report_callback_rx_msg(struct can2040 *cd) static void report_callback_tx_msg(struct can2040 *cd) { - cd->tx_pull_pos++; + writel(&cd->tx_pull_pos, cd->tx_pull_pos + 1); cd->rx_cb(cd, CAN2040_NOTIFY_TX, &cd->parse_msg); } @@ -856,7 +861,9 @@ report_line_maytx(struct can2040 *cd) static void report_line_txpending(struct can2040 *cd) { - if (cd->report_state == RS_NEED_RX_ACK) { + uint32_t pio_irqs = pio_irq_get(cd); + if (pio_irqs == (SI_MAYTX | SI_TXPENDING | SI_RX_DATA) + && cd->report_state == RS_NEED_RX_ACK) { // Ack inject request from report_note_crc_start() uint32_t mk = pio_match_calc_key(cd->parse_crc_bits, cd->parse_crc_pos); tx_inject_ack(cd, mk); @@ -866,7 +873,7 @@ report_line_txpending(struct can2040 *cd) // Tx request from can2040_transmit(), report_note_eof_success(), // or report_note_parse_error(). uint32_t check_txpending = tx_schedule_transmit(cd); - pio_irq_set(cd, (pio_irq_get(cd) & ~SI_TXPENDING) | check_txpending); + pio_irq_set(cd, (pio_irqs & ~SI_TXPENDING) | check_txpending); } @@ -1241,7 +1248,7 @@ can2040_transmit(struct can2040 *cd, struct can2040_msg *msg) crc = crc_bytes(crc, hdr, 3); bs_push(&bs, hdr, 19); } - int i; + uint32_t i; for (i=0; imsg.data[i]; crc = crc_byte(crc, v); @@ -1256,6 +1263,7 @@ can2040_transmit(struct can2040 *cd, struct can2040_msg *msg) writel(&cd->tx_push_pos, tx_push_pos + 1); // Wakeup if in TS_IDLE state + __DMB(); pio_signal_set_txpending(cd); return 0;