aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2023-05-03 10:45:41 -0400
committerKevin O'Connor <kevin@koconnor.net>2023-05-03 10:45:41 -0400
commit3bd0be40d502f43bb9f941a60bf778b902ed4e6e (patch)
tree7d4fa8bcb3e0b92e04e3109314859851f2b61602 /lib
parent1a24e7c5b683355335b115e5659eb6fe8c8d11dc (diff)
downloadkutter-3bd0be40d502f43bb9f941a60bf778b902ed4e6e.tar.gz
kutter-3bd0be40d502f43bb9f941a60bf778b902ed4e6e.tar.xz
kutter-3bd0be40d502f43bb9f941a60bf778b902ed4e6e.zip
lib: Update to latest can2040 code
Disable tx state machine before resetting it Check for rx message with same id as tx but different payload Do not use canrx line to alter bit timing of cantx line Improve bit time synchronization with slow transmitters Implement tx synchronization to faster transmitters Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/can2040/can2040.c65
1 files changed, 39 insertions, 26 deletions
diff --git a/lib/can2040/can2040.c b/lib/can2040/can2040.c
index 9eef0d43..926893d9 100644
--- a/lib/can2040/can2040.c
+++ b/lib/can2040/can2040.c
@@ -76,21 +76,21 @@ rp2040_gpio_peripheral(uint32_t gpio, int func, int pull_up)
#define can2040_offset_shared_rx_read 13u
#define can2040_offset_shared_rx_end 15u
#define can2040_offset_match_load_next 18u
+#define can2040_offset_tx_conflict 24u
#define can2040_offset_match_end 25u
#define can2040_offset_tx_got_recessive 25u
-#define can2040_offset_tx_start 26u
-#define can2040_offset_tx_conflict 31u
+#define can2040_offset_tx_write_pin 27u
static const uint16_t can2040_program_instructions[] = {
0x0085, // 0: jmp y--, 5
0x0048, // 1: jmp x--, 8
- 0xe12a, // 2: set x, 10 [1]
+ 0xe029, // 2: set x, 9
0x00cc, // 3: jmp pin, 12
0xc000, // 4: irq nowait 0
0x00c0, // 5: jmp pin, 0
0xc040, // 6: irq clear 0
- 0xe229, // 7: set x, 9 [2]
- 0xf242, // 8: set y, 2 [18]
+ 0xe429, // 7: set x, 9 [4]
+ 0xf043, // 8: set y, 3 [16]
0xc104, // 9: irq nowait 4 [1]
0x03c5, // 10: jmp pin, 5 [3]
0x0307, // 11: jmp 7 [3]
@@ -98,7 +98,7 @@ static const uint16_t can2040_program_instructions[] = {
0x20c4, // 13: wait 1 irq, 4
0x4001, // 14: in pins, 1
0xa046, // 15: mov y, isr
- 0x00b2, // 16: jmp x != y, 18
+ 0x01b2, // 16: jmp x != y, 18 [1]
0xc002, // 17: irq nowait 2
0x40eb, // 18: in osr, 11
0x4054, // 19: in y, 20
@@ -107,13 +107,13 @@ static const uint16_t can2040_program_instructions[] = {
0xa027, // 22: mov x, osr
0x0098, // 23: jmp y--, 24
0xa0e2, // 24: mov osr, y
- 0xa242, // 25: nop [2]
- 0x6021, // 26: out x, 1
- 0xa001, // 27: mov pins, x
- 0x20c4, // 28: wait 1 irq, 4
- 0x00d9, // 29: jmp pin, 25
- 0x023a, // 30: jmp !x, 26 [2]
- 0x001f, // 31: jmp 31
+ 0x6021, // 25: out x, 1
+ 0x00df, // 26: jmp pin, 31
+ 0xb801, // 27: mov pins, x [24]
+ 0x02d9, // 28: jmp pin, 25 [2]
+ 0x0058, // 29: jmp x--, 24
+ 0x6021, // 30: out x, 1
+ 0x011b, // 31: jmp 27 [1]
};
// Local names for PIO state machine IRQs
@@ -138,7 +138,7 @@ pio_sync_setup(struct can2040 *cd)
| cd->gpio_rx << PIO_SM0_PINCTRL_SET_BASE_LSB);
sm->instr = 0xe080; // set pindirs, 0
sm->pinctrl = 0;
- pio_hw->txf[0] = PIO_CLOCK_PER_BIT / 2 * 7 - 5 - 1;
+ pio_hw->txf[0] = 9 + 6 * PIO_CLOCK_PER_BIT / 2;
sm->instr = 0x80a0; // pull block
sm->instr = can2040_offset_sync_entry; // jmp sync_entry
}
@@ -183,7 +183,10 @@ pio_tx_setup(struct can2040 *cd)
{
pio_hw_t *pio_hw = cd->pio_hw;
struct pio_sm_hw *sm = &pio_hw->sm[3];
- sm->execctrl = cd->gpio_rx << PIO_SM0_EXECCTRL_JMP_PIN_LSB;
+ sm->execctrl = (
+ cd->gpio_rx << PIO_SM0_EXECCTRL_JMP_PIN_LSB
+ | can2040_offset_tx_conflict << PIO_SM0_EXECCTRL_WRAP_TOP_LSB
+ | can2040_offset_tx_conflict << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB);
sm->shiftctrl = (PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS
| PIO_SM0_SHIFTCTRL_AUTOPULL_BITS);
sm->pinctrl = (1 << PIO_SM0_PINCTRL_SET_COUNT_LSB
@@ -247,6 +250,7 @@ static void
pio_tx_reset(struct can2040 *cd)
{
pio_hw_t *pio_hw = cd->pio_hw;
+ pio_hw->ctrl = 0x07 << PIO_CTRL_SM_ENABLE_LSB;
pio_hw->ctrl = ((0x07 << PIO_CTRL_SM_ENABLE_LSB)
| (0x08 << PIO_CTRL_SM_RESTART_LSB));
pio_hw->irq = (SI_MATCHED | SI_ACKDONE) >> 8; // clear PIO irq flags
@@ -255,9 +259,6 @@ pio_tx_reset(struct can2040 *cd)
sm->shiftctrl = 0;
sm->shiftctrl = (PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS
| PIO_SM0_SHIFTCTRL_AUTOPULL_BITS);
- // Must reset again after clearing fifo
- pio_hw->ctrl = ((0x07 << PIO_CTRL_SM_ENABLE_LSB)
- | (0x08 << PIO_CTRL_SM_RESTART_LSB));
}
// Queue a message for transmission on PIO "tx" state machine
@@ -266,13 +267,14 @@ 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]
+ pio_hw->instr_mem[can2040_offset_tx_got_recessive] = 0x6021; // out x, 1
uint32_t i;
for (i=0; i<count; i++)
pio_hw->txf[3] = data[i];
struct pio_sm_hw *sm = &pio_hw->sm[3];
sm->instr = 0xe001; // set pins, 1
- sm->instr = can2040_offset_tx_start; // jmp tx_start
+ sm->instr = 0x6021; // out x, 1
+ sm->instr = can2040_offset_tx_write_pin; // jmp tx_write_pin
sm->instr = 0x20c0; // wait 1 irq, 0
pio_hw->ctrl = 0x0f << PIO_CTRL_SM_ENABLE_LSB;
}
@@ -287,7 +289,8 @@ pio_tx_inject_ack(struct can2040 *cd, uint32_t match_key)
pio_hw->txf[3] = 0x7fffffff;
struct pio_sm_hw *sm = &pio_hw->sm[3];
sm->instr = 0xe001; // set pins, 1
- sm->instr = can2040_offset_tx_start; // jmp tx_start
+ sm->instr = 0x6021; // out x, 1
+ sm->instr = can2040_offset_tx_write_pin; // jmp tx_write_pin
sm->instr = 0x20c2; // wait 1 irq, 2
pio_hw->ctrl = 0x0f << PIO_CTRL_SM_ENABLE_LSB;
@@ -680,8 +683,11 @@ tx_check_local_message(struct can2040 *cd)
return 0;
struct can2040_transmit *qt = &cd->tx_queue[tx_qpos(cd, cd->tx_pull_pos)];
struct can2040_msg *pm = &cd->parse_msg, *tm = &qt->msg;
- if (qt->crc == cd->parse_crc && tm->id == pm->id && tm->dlc == pm->dlc
- && tm->data32[0] == pm->data32[0] && tm->data32[1] == pm->data32[1]) {
+ if (tm->id == pm->id) {
+ if (qt->crc != cd->parse_crc || tm->dlc != pm->dlc
+ || tm->data32[0] != pm->data32[0] || tm->data32[1] != pm->data32[1])
+ // Message with same id that differs in content - an error
+ return -1;
// This is a self transmit
cd->tx_state = TS_CONFIRM_TX;
return 1;
@@ -757,22 +763,25 @@ report_note_message_start(struct can2040 *cd)
}
// Setup for ack injection (if receiving) or ack confirmation (if transmit)
-static void
+static int
report_note_crc_start(struct can2040 *cd)
{
int ret = tx_check_local_message(cd);
if (ret) {
+ if (ret < 0)
+ return -1;
// This is a self transmit - setup tx eof "matched" signal
cd->report_state = RS_NEED_TX_ACK;
uint32_t bits = (cd->parse_crc_bits << 9) | 0x0ff;
pio_match_check(cd, pio_match_calc_key(bits, cd->parse_crc_pos + 9));
- return;
+ return 0;
}
// Setup for ack inject (after rx fifos fully drained)
cd->report_state = RS_NEED_RX_ACK;
pio_signal_set_txpending(cd);
pio_irq_set(cd, SI_MAYTX | SI_TXPENDING);
+ return 0;
}
// Parser successfully found matching crc
@@ -961,7 +970,11 @@ data_state_go_crc(struct can2040 *cd)
cd->parse_crc_bits = (crc_bits << 1) | 0x01; // Add crc delimiter
cd->parse_crc_pos = crcstart_bitpos + crc_bitcount + 1;
- report_note_crc_start(cd);
+ int ret = report_note_crc_start(cd);
+ if (ret) {
+ data_state_go_discard(cd);
+ return;
+ }
data_state_go_next(cd, MS_CRC, 16);
}