lib: Update to latest can2040 code
Fix gpio function selection for PIO1 usage. Minor variable name changes. Allow scheduling tx "matched" event after a crc match. Allow for up to 5 passive bits after unstuf_clear_state(). Pause PIO "rx" bit reception after 10 passive bits. Signal the CPU to process data every 10 read bits. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
eb9cda91b5
commit
6cc104677e
|
@ -146,4 +146,4 @@ used to upload firmware to devices flashed with the CanBoot bootloader.
|
||||||
|
|
||||||
The can2040 directory contains code from:
|
The can2040 directory contains code from:
|
||||||
https://github.com/KevinOConnor/can2040
|
https://github.com/KevinOConnor/can2040
|
||||||
revision 9ca095c939a48391de60dd353f0cd91999bb9257.
|
revision aff2940f1fa5b0c9822a7694403ec9d70710193d.
|
||||||
|
|
|
@ -67,6 +67,7 @@ rp2040_gpio_peripheral(uint32_t gpio, int func, int pull_up)
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
#define PIO_CLOCK_PER_BIT 32
|
#define PIO_CLOCK_PER_BIT 32
|
||||||
|
#define PIO_RX_WAKE_BITS 10
|
||||||
|
|
||||||
#define can2040_offset_sync_found_end_of_message 2u
|
#define can2040_offset_sync_found_end_of_message 2u
|
||||||
#define can2040_offset_sync_signal_start 4u
|
#define can2040_offset_sync_signal_start 4u
|
||||||
|
@ -83,12 +84,12 @@ rp2040_gpio_peripheral(uint32_t gpio, int func, int pull_up)
|
||||||
static const uint16_t can2040_program_instructions[] = {
|
static const uint16_t can2040_program_instructions[] = {
|
||||||
0x0085, // 0: jmp y--, 5
|
0x0085, // 0: jmp y--, 5
|
||||||
0x0048, // 1: jmp x--, 8
|
0x0048, // 1: jmp x--, 8
|
||||||
0xe13a, // 2: set x, 26 [1]
|
0xe12a, // 2: set x, 10 [1]
|
||||||
0x00cc, // 3: jmp pin, 12
|
0x00cc, // 3: jmp pin, 12
|
||||||
0xc000, // 4: irq nowait 0
|
0xc000, // 4: irq nowait 0
|
||||||
0x00c0, // 5: jmp pin, 0
|
0x00c0, // 5: jmp pin, 0
|
||||||
0xc040, // 6: irq clear 0
|
0xc040, // 6: irq clear 0
|
||||||
0xe228, // 7: set x, 8 [2]
|
0xe229, // 7: set x, 9 [2]
|
||||||
0xf242, // 8: set y, 2 [18]
|
0xf242, // 8: set y, 2 [18]
|
||||||
0xc104, // 9: irq nowait 4 [1]
|
0xc104, // 9: irq nowait 4 [1]
|
||||||
0x03c5, // 10: jmp pin, 5 [3]
|
0x03c5, // 10: jmp pin, 5 [3]
|
||||||
|
@ -130,7 +131,7 @@ pio_sync_setup(struct can2040 *cd)
|
||||||
| cd->gpio_rx << PIO_SM0_PINCTRL_SET_BASE_LSB);
|
| cd->gpio_rx << PIO_SM0_PINCTRL_SET_BASE_LSB);
|
||||||
sm->instr = 0xe080; // set pindirs, 0
|
sm->instr = 0xe080; // set pindirs, 0
|
||||||
sm->pinctrl = 0;
|
sm->pinctrl = 0;
|
||||||
pio_hw->txf[0] = PIO_CLOCK_PER_BIT / 2 * 8 - 5 - 1;
|
pio_hw->txf[0] = PIO_CLOCK_PER_BIT / 2 * 7 - 5 - 1;
|
||||||
sm->instr = 0x80a0; // pull block
|
sm->instr = 0x80a0; // pull block
|
||||||
sm->instr = can2040_offset_sync_entry; // jmp sync_entry
|
sm->instr = can2040_offset_sync_entry; // jmp sync_entry
|
||||||
}
|
}
|
||||||
|
@ -147,7 +148,7 @@ pio_rx_setup(struct can2040 *cd)
|
||||||
sm->pinctrl = cd->gpio_rx << PIO_SM0_PINCTRL_IN_BASE_LSB;
|
sm->pinctrl = cd->gpio_rx << PIO_SM0_PINCTRL_IN_BASE_LSB;
|
||||||
sm->shiftctrl = 0; // flush fifo on a restart
|
sm->shiftctrl = 0; // flush fifo on a restart
|
||||||
sm->shiftctrl = (PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS
|
sm->shiftctrl = (PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS
|
||||||
| 8 << PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB
|
| PIO_RX_WAKE_BITS << PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB
|
||||||
| PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS);
|
| PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS);
|
||||||
sm->instr = can2040_offset_shared_rx_read; // jmp shared_rx_read
|
sm->instr = can2040_offset_shared_rx_read; // jmp shared_rx_read
|
||||||
}
|
}
|
||||||
|
@ -192,7 +193,7 @@ pio_sync_normal_start_signal(struct can2040 *cd)
|
||||||
{
|
{
|
||||||
pio_hw_t *pio_hw = cd->pio_hw;
|
pio_hw_t *pio_hw = cd->pio_hw;
|
||||||
uint32_t eom_idx = can2040_offset_sync_found_end_of_message;
|
uint32_t eom_idx = can2040_offset_sync_found_end_of_message;
|
||||||
pio_hw->instr_mem[eom_idx] = 0xe13a; // set x, 26 [1]
|
pio_hw->instr_mem[eom_idx] = 0xe12a; // set x, 10 [1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set PIO "sync" machine to signal "may transmit" (sm irq 0) on 17 idle bits
|
// Set PIO "sync" machine to signal "may transmit" (sm irq 0) on 17 idle bits
|
||||||
|
@ -368,8 +369,6 @@ pio_sm_setup(struct can2040 *cd)
|
||||||
pio_hw->ctrl = 0x07 << PIO_CTRL_SM_ENABLE_LSB;
|
pio_hw->ctrl = 0x07 << PIO_CTRL_SM_ENABLE_LSB;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PIO_FUNC 6
|
|
||||||
|
|
||||||
// Initial setup of gpio pins and PIO state machines
|
// Initial setup of gpio pins and PIO state machines
|
||||||
static void
|
static void
|
||||||
pio_setup(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate)
|
pio_setup(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate)
|
||||||
|
@ -389,8 +388,9 @@ pio_setup(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate)
|
||||||
pio_sm_setup(cd);
|
pio_sm_setup(cd);
|
||||||
|
|
||||||
// Map Rx/Tx gpios
|
// Map Rx/Tx gpios
|
||||||
rp2040_gpio_peripheral(cd->gpio_rx, PIO_FUNC, 1);
|
uint32_t pio_func = cd->pio_num ? 7 : 6;
|
||||||
rp2040_gpio_peripheral(cd->gpio_tx, PIO_FUNC, 0);
|
rp2040_gpio_peripheral(cd->gpio_rx, pio_func, 1);
|
||||||
|
rp2040_gpio_peripheral(cd->gpio_tx, pio_func, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -462,12 +462,12 @@ unstuf_add_bits(struct can2040_bitunstuffer *bu, uint32_t data, uint32_t count)
|
||||||
bu->count_stuff = count;
|
bu->count_stuff = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset state and set the next desired 'count' unstuffed bits to extract
|
// Reset state and set the next desired 'num_bits' unstuffed bits to extract
|
||||||
static void
|
static void
|
||||||
unstuf_set_count(struct can2040_bitunstuffer *bu, uint32_t count)
|
unstuf_set_count(struct can2040_bitunstuffer *bu, uint32_t num_bits)
|
||||||
{
|
{
|
||||||
bu->unstuffed_bits = 0;
|
bu->unstuffed_bits = 0;
|
||||||
bu->count_unstuff = count;
|
bu->count_unstuff = num_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear bitstuffing state (used after crc field to avoid bitstuffing ack field)
|
// Clear bitstuffing state (used after crc field to avoid bitstuffing ack field)
|
||||||
|
@ -475,7 +475,7 @@ static void
|
||||||
unstuf_clear_state(struct can2040_bitunstuffer *bu)
|
unstuf_clear_state(struct can2040_bitunstuffer *bu)
|
||||||
{
|
{
|
||||||
uint32_t lb = 1 << bu->count_stuff;
|
uint32_t lb = 1 << bu->count_stuff;
|
||||||
bu->stuffed_bits = (bu->stuffed_bits & (lb - 1)) | lb;
|
bu->stuffed_bits = (bu->stuffed_bits & (lb - 1)) | (lb << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull bits from unstuffer (as specified in unstuf_set_count() )
|
// Pull bits from unstuffer (as specified in unstuf_set_count() )
|
||||||
|
@ -774,6 +774,15 @@ report_note_crc_start(struct can2040 *cd)
|
||||||
cd->report_eof_key = pio_match_calc_key(last, crcend_bitpos + 9);
|
cd->report_eof_key = pio_match_calc_key(last, crcend_bitpos + 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parser successfully found matching crc
|
||||||
|
static void
|
||||||
|
report_note_crc_success(struct can2040 *cd)
|
||||||
|
{
|
||||||
|
if (cd->report_state == (RS_IN_MSG | RS_IS_TX))
|
||||||
|
// Enable "matched" irq for fast back-to-back transmit scheduling
|
||||||
|
pio_irq_set_maytx_matched(cd);
|
||||||
|
}
|
||||||
|
|
||||||
// Parser found successful ack
|
// Parser found successful ack
|
||||||
static void
|
static void
|
||||||
report_note_ack_success(struct can2040 *cd)
|
report_note_ack_success(struct can2040 *cd)
|
||||||
|
@ -782,9 +791,6 @@ report_note_ack_success(struct can2040 *cd)
|
||||||
// Got rx "ackdone" and "matched" signals already
|
// Got rx "ackdone" and "matched" signals already
|
||||||
return;
|
return;
|
||||||
cd->report_state |= RS_AWAIT_EOF;
|
cd->report_state |= RS_AWAIT_EOF;
|
||||||
if (cd->report_state & RS_IS_TX)
|
|
||||||
// Enable "matched" irq for fast back-to-back transmit scheduling
|
|
||||||
pio_irq_set_maytx_matched(cd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parser found successful EOF
|
// Parser found successful EOF
|
||||||
|
@ -816,7 +822,6 @@ report_line_ackdone(struct can2040 *cd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Setup "matched" irq for fast rx callbacks
|
// Setup "matched" irq for fast rx callbacks
|
||||||
cd->report_state = RS_IN_MSG | RS_AWAIT_EOF;
|
|
||||||
pio_match_check(cd, cd->report_eof_key);
|
pio_match_check(cd, cd->report_eof_key);
|
||||||
pio_irq_set_maytx_matched(cd);
|
pio_irq_set_maytx_matched(cd);
|
||||||
// Schedule next transmit (so it is ready for next frame line arbitration)
|
// Schedule next transmit (so it is ready for next frame line arbitration)
|
||||||
|
@ -828,6 +833,8 @@ static void
|
||||||
report_line_matched(struct can2040 *cd)
|
report_line_matched(struct can2040 *cd)
|
||||||
{
|
{
|
||||||
// Implement fast rx callback and/or fast back-to-back tx scheduling
|
// Implement fast rx callback and/or fast back-to-back tx scheduling
|
||||||
|
if (cd->report_state & RS_IN_MSG)
|
||||||
|
cd->report_state |= RS_AWAIT_EOF;
|
||||||
report_handle_eof(cd);
|
report_handle_eof(cd);
|
||||||
pio_irq_set_none(cd);
|
pio_irq_set_none(cd);
|
||||||
tx_schedule_transmit(cd);
|
tx_schedule_transmit(cd);
|
||||||
|
@ -857,10 +864,10 @@ enum {
|
||||||
|
|
||||||
// Transition to the next parsing state
|
// Transition to the next parsing state
|
||||||
static void
|
static void
|
||||||
data_state_go_next(struct can2040 *cd, uint32_t state, uint32_t bits)
|
data_state_go_next(struct can2040 *cd, uint32_t state, uint32_t num_bits)
|
||||||
{
|
{
|
||||||
cd->parse_state = state;
|
cd->parse_state = state;
|
||||||
unstuf_set_count(&cd->unstuf, bits);
|
unstuf_set_count(&cd->unstuf, num_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transition to the MS_DISCARD state - drop all bits until 6 passive bits
|
// Transition to the MS_DISCARD state - drop all bits until 6 passive bits
|
||||||
|
@ -886,7 +893,7 @@ data_state_line_error(struct can2040 *cd)
|
||||||
data_state_go_discard(cd);
|
data_state_go_discard(cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Received six passive bits on the line
|
// Received six unexpected passive bits on the line
|
||||||
static void
|
static void
|
||||||
data_state_line_passive(struct can2040 *cd)
|
data_state_line_passive(struct can2040 *cd)
|
||||||
{
|
{
|
||||||
|
@ -897,7 +904,8 @@ data_state_line_passive(struct can2040 *cd)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t stuffed_bits = cd->unstuf.stuffed_bits >> cd->unstuf.count_stuff;
|
uint32_t stuffed_bits = cd->unstuf.stuffed_bits >> cd->unstuf.count_stuff;
|
||||||
if (stuffed_bits == 0xffffffff) {
|
uint32_t dom_bits = ~stuffed_bits;
|
||||||
|
if (!dom_bits) {
|
||||||
// Counter overflow in "sync" state machine - reset it
|
// Counter overflow in "sync" state machine - reset it
|
||||||
pio_sync_setup(cd);
|
pio_sync_setup(cd);
|
||||||
cd->unstuf.stuffed_bits = 0;
|
cd->unstuf.stuffed_bits = 0;
|
||||||
|
@ -905,8 +913,8 @@ data_state_line_passive(struct can2040 *cd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for sof after 9 passive bits (most "PIO sync" will produce)
|
// Look for sof after 10 passive bits (most "PIO sync" will produce)
|
||||||
if (((stuffed_bits + 1) & 0x1ff) == 0) {
|
if (!(dom_bits & 0x3ff)) {
|
||||||
data_state_go_next(cd, MS_START, 1);
|
data_state_go_next(cd, MS_START, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1014,6 +1022,7 @@ data_state_update_crc(struct can2040 *cd, uint32_t data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
report_note_crc_success(cd);
|
||||||
unstuf_clear_state(&cd->unstuf);
|
unstuf_clear_state(&cd->unstuf);
|
||||||
data_state_go_next(cd, MS_ACK, 2);
|
data_state_go_next(cd, MS_ACK, 2);
|
||||||
}
|
}
|
||||||
|
@ -1039,18 +1048,18 @@ data_state_update_eof0(struct can2040 *cd, uint32_t data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unstuf_clear_state(&cd->unstuf);
|
unstuf_clear_state(&cd->unstuf);
|
||||||
data_state_go_next(cd, MS_EOF1, 4);
|
data_state_go_next(cd, MS_EOF1, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle reception of end-of-frame (EOF) bits 5-7 and first IFS bit
|
// Handle reception of end-of-frame (EOF) bits 5-7 and first two IFS bits
|
||||||
static void
|
static void
|
||||||
data_state_update_eof1(struct can2040 *cd, uint32_t data)
|
data_state_update_eof1(struct can2040 *cd, uint32_t data)
|
||||||
{
|
{
|
||||||
if (data >= 0x0e || (data >= 0x0c && report_is_acking_rx(cd)))
|
if (data >= 0x1c || (data >= 0x18 && report_is_acking_rx(cd)))
|
||||||
// Message is considered fully transmitted
|
// Message is considered fully transmitted
|
||||||
report_note_eof_success(cd);
|
report_note_eof_success(cd);
|
||||||
|
|
||||||
if (data == 0x0f)
|
if (data == 0x1f)
|
||||||
data_state_go_next(cd, MS_START, 1);
|
data_state_go_next(cd, MS_START, 1);
|
||||||
else
|
else
|
||||||
data_state_go_discard(cd);
|
data_state_go_discard(cd);
|
||||||
|
@ -1088,10 +1097,10 @@ data_state_update(struct can2040 *cd, uint32_t data)
|
||||||
|
|
||||||
// Process an incoming byte of data from PIO "rx" state machine
|
// Process an incoming byte of data from PIO "rx" state machine
|
||||||
static void
|
static void
|
||||||
process_rx(struct can2040 *cd, uint32_t rx_byte)
|
process_rx(struct can2040 *cd, uint32_t rx_data)
|
||||||
{
|
{
|
||||||
unstuf_add_bits(&cd->unstuf, rx_byte, 8);
|
unstuf_add_bits(&cd->unstuf, rx_data, PIO_RX_WAKE_BITS);
|
||||||
cd->raw_bit_count += 8;
|
cd->raw_bit_count += PIO_RX_WAKE_BITS;
|
||||||
|
|
||||||
// undo bit stuffing
|
// undo bit stuffing
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1120,8 +1129,8 @@ can2040_pio_irq_handler(struct can2040 *cd)
|
||||||
pio_hw_t *pio_hw = cd->pio_hw;
|
pio_hw_t *pio_hw = cd->pio_hw;
|
||||||
uint32_t ints = pio_hw->ints0;
|
uint32_t ints = pio_hw->ints0;
|
||||||
while (likely(ints & PIO_IRQ0_INTE_SM1_RXNEMPTY_BITS)) {
|
while (likely(ints & PIO_IRQ0_INTE_SM1_RXNEMPTY_BITS)) {
|
||||||
uint8_t rx_byte = pio_hw->rxf[1];
|
uint32_t rx_data = pio_hw->rxf[1];
|
||||||
process_rx(cd, rx_byte);
|
process_rx(cd, rx_data);
|
||||||
ints = pio_hw->ints0;
|
ints = pio_hw->ints0;
|
||||||
if (likely(!ints))
|
if (likely(!ints))
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue