Skip to content

Commit aa726cb

Browse files
committed
lib: Update to latest can2040 code
Add support for can2040_stop() Add data_state_go_error() helper Add new can2040_get_statistics() API function Call report_note_discarding() after setting MS_DISCARD state Convert report_is_rx_eof_pending() to report_is_not_in_tx() Signed-off-by: Kevin O'Connor <[email protected]>
1 parent 7bd3299 commit aa726cb

File tree

3 files changed

+82
-27
lines changed

3 files changed

+82
-27
lines changed

lib/README

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ used to upload firmware to devices flashed with the CanBoot bootloader.
167167

168168
The can2040 directory contains code from:
169169
https://github.com/KevinOConnor/can2040
170-
revision d1190afcaa6245c20da28199d06e453d2e743099.
170+
version v1.6.0 (af3d21e5d61b8408c63fbdfb0aceb21d69d91693)
171171

172172
The Huada HC32F460 directory contains code from:
173173
https://www.hdsc.com.cn/Category83-1490

lib/can2040/can2040.c

+72-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Software CANbus implementation for rp2040
22
//
3-
// Copyright (C) 2022 Kevin O'Connor <[email protected]>
3+
// Copyright (C) 2022,2023 Kevin O'Connor <[email protected]>
44
//
55
// This file may be distributed under the terms of the GNU GPLv3 license.
66

@@ -318,6 +318,14 @@ pio_irq_set(struct can2040 *cd, uint32_t sm_irqs)
318318
pio_hw->inte0 = sm_irqs | SI_RX_DATA;
319319
}
320320

321+
// Completely disable host irqs
322+
static void
323+
pio_irq_disable(struct can2040 *cd)
324+
{
325+
pio_hw_t *pio_hw = cd->pio_hw;
326+
pio_hw->inte0 = 0;
327+
}
328+
321329
// Return current host irq mask
322330
static uint32_t
323331
pio_irq_get(struct can2040 *cd)
@@ -662,6 +670,7 @@ tx_schedule_transmit(struct can2040 *cd)
662670
pio_signal_set_txpending(cd);
663671
}
664672
cd->tx_state = TS_QUEUED;
673+
cd->stats.tx_attempt++;
665674
struct can2040_transmit *qt = &cd->tx_queue[tx_qpos(cd, tx_pull_pos)];
666675
pio_tx_send(cd, qt->stuffed_data, qt->stuffed_words);
667676
return 0;
@@ -721,6 +730,7 @@ report_callback_error(struct can2040 *cd, uint32_t error_code)
721730
static void
722731
report_callback_rx_msg(struct can2040 *cd)
723732
{
733+
cd->stats.rx_total++;
724734
cd->rx_cb(cd, CAN2040_NOTIFY_RX, &cd->parse_msg);
725735
}
726736

@@ -729,6 +739,7 @@ static void
729739
report_callback_tx_msg(struct can2040 *cd)
730740
{
731741
writel(&cd->tx_pull_pos, cd->tx_pull_pos + 1);
742+
cd->stats.tx_total++;
732743
cd->rx_cb(cd, CAN2040_NOTIFY_TX, &cd->parse_msg);
733744
}
734745

@@ -748,11 +759,11 @@ report_handle_eof(struct can2040 *cd)
748759
pio_match_clear(cd);
749760
}
750761

751-
// Check if in an rx message is being processed
762+
// Check if message being processed is an rx message (not self feedback from tx)
752763
static int
753-
report_is_rx_eof_pending(struct can2040 *cd)
764+
report_is_not_in_tx(struct can2040 *cd)
754765
{
755-
return cd->report_state == RS_NEED_RX_EOF;
766+
return !(cd->report_state & RS_NEED_TX_ACK);
756767
}
757768

758769
// Parser found a new message start
@@ -817,7 +828,7 @@ report_note_eof_success(struct can2040 *cd)
817828

818829
// Parser found unexpected data on input
819830
static void
820-
report_note_parse_error(struct can2040 *cd)
831+
report_note_discarding(struct can2040 *cd)
821832
{
822833
if (cd->report_state != RS_IDLE) {
823834
cd->report_state = RS_IDLE;
@@ -880,7 +891,7 @@ report_line_txpending(struct can2040 *cd)
880891
return;
881892
}
882893
// Tx request from can2040_transmit(), report_note_eof_success(),
883-
// or report_note_parse_error().
894+
// or report_note_discarding().
884895
uint32_t check_txpending = tx_schedule_transmit(cd);
885896
pio_irq_set(cd, (pio_irqs & ~SI_TXPENDING) | check_txpending);
886897
}
@@ -896,6 +907,13 @@ enum {
896907
MS_CRC, MS_ACK, MS_EOF0, MS_EOF1, MS_DISCARD
897908
};
898909

910+
// Reset any bits in the incoming parsing state
911+
static void
912+
data_state_clear_bits(struct can2040 *cd)
913+
{
914+
cd->raw_bit_count = cd->unstuf.stuffed_bits = cd->unstuf.count_stuff = 0;
915+
}
916+
899917
// Transition to the next parsing state
900918
static void
901919
data_state_go_next(struct can2040 *cd, uint32_t state, uint32_t num_bits)
@@ -908,23 +926,35 @@ data_state_go_next(struct can2040 *cd, uint32_t state, uint32_t num_bits)
908926
static void
909927
data_state_go_discard(struct can2040 *cd)
910928
{
911-
report_note_parse_error(cd);
912-
913929
if (pio_rx_check_stall(cd)) {
914930
// CPU couldn't keep up for some read data - must reset pio state
915-
cd->raw_bit_count = cd->unstuf.count_stuff = 0;
931+
data_state_clear_bits(cd);
916932
pio_sm_setup(cd);
917933
report_callback_error(cd, 0);
918934
}
919935

920936
data_state_go_next(cd, MS_DISCARD, 32);
937+
938+
// Clear report state and update hw irqs after transition to MS_DISCARD
939+
report_note_discarding(cd);
940+
}
941+
942+
// Note a data parse error and transition to discard state
943+
static void
944+
data_state_go_error(struct can2040 *cd)
945+
{
946+
cd->stats.parse_error++;
947+
data_state_go_discard(cd);
921948
}
922949

923950
// Received six dominant bits on the line
924951
static void
925952
data_state_line_error(struct can2040 *cd)
926953
{
927-
data_state_go_discard(cd);
954+
if (cd->parse_state == MS_DISCARD)
955+
data_state_go_discard(cd);
956+
else
957+
data_state_go_error(cd);
928958
}
929959

930960
// Received six unexpected passive bits on the line
@@ -933,16 +963,15 @@ data_state_line_passive(struct can2040 *cd)
933963
{
934964
if (cd->parse_state != MS_DISCARD && cd->parse_state != MS_START) {
935965
// Bitstuff error
936-
data_state_go_discard(cd);
966+
data_state_go_error(cd);
937967
return;
938968
}
939969

940970
uint32_t stuffed_bits = unstuf_get_raw(&cd->unstuf);
941971
uint32_t dom_bits = ~stuffed_bits;
942972
if (!dom_bits) {
943973
// Counter overflow in "sync" state machine - reset it
944-
cd->unstuf.stuffed_bits = 0;
945-
cd->raw_bit_count = cd->unstuf.count_stuff = 0;
974+
data_state_clear_bits(cd);
946975
pio_sm_setup(cd);
947976
data_state_go_discard(cd);
948977
return;
@@ -972,7 +1001,7 @@ data_state_go_crc(struct can2040 *cd)
9721001

9731002
int ret = report_note_crc_start(cd);
9741003
if (ret) {
975-
data_state_go_discard(cd);
1004+
data_state_go_error(cd);
9761005
return;
9771006
}
9781007
data_state_go_next(cd, MS_CRC, 16);
@@ -1065,7 +1094,7 @@ static void
10651094
data_state_update_crc(struct can2040 *cd, uint32_t data)
10661095
{
10671096
if (((cd->parse_crc << 1) | 1) != data) {
1068-
data_state_go_discard(cd);
1097+
data_state_go_error(cd);
10691098
return;
10701099
}
10711100

@@ -1083,7 +1112,7 @@ data_state_update_ack(struct can2040 *cd, uint32_t data)
10831112
// data_state_line_passive()
10841113
unstuf_restore_state(&cd->unstuf, (cd->parse_crc_bits << 2) | data);
10851114

1086-
data_state_go_discard(cd);
1115+
data_state_go_error(cd);
10871116
return;
10881117
}
10891118
report_note_ack_success(cd);
@@ -1095,7 +1124,7 @@ static void
10951124
data_state_update_eof0(struct can2040 *cd, uint32_t data)
10961125
{
10971126
if (data != 0x0f || pio_rx_check_stall(cd)) {
1098-
data_state_go_discard(cd);
1127+
data_state_go_error(cd);
10991128
return;
11001129
}
11011130
unstuf_clear_state(&cd->unstuf);
@@ -1106,14 +1135,17 @@ data_state_update_eof0(struct can2040 *cd, uint32_t data)
11061135
static void
11071136
data_state_update_eof1(struct can2040 *cd, uint32_t data)
11081137
{
1109-
if (data >= 0x1c || (data >= 0x18 && report_is_rx_eof_pending(cd)))
1110-
// Message is considered fully transmitted
1138+
if (data == 0x1f) {
1139+
// Success
11111140
report_note_eof_success(cd);
1112-
1113-
if (data == 0x1f)
11141141
data_state_go_next(cd, MS_START, 1);
1115-
else
1142+
} else if (data >= 0x1c || (data >= 0x18 && report_is_not_in_tx(cd))) {
1143+
// Message fully transmitted - followed by "overload frame"
1144+
report_note_eof_success(cd);
11161145
data_state_go_discard(cd);
1146+
} else {
1147+
data_state_go_error(cd);
1148+
}
11171149
}
11181150

11191151
// Handle data received while in MS_DISCARD state
@@ -1310,13 +1342,28 @@ can2040_start(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate
13101342
{
13111343
cd->gpio_rx = gpio_rx;
13121344
cd->gpio_tx = gpio_tx;
1345+
data_state_clear_bits(cd);
13131346
pio_setup(cd, sys_clock, bitrate);
13141347
data_state_go_discard(cd);
13151348
}
13161349

1317-
// API function to stop and uninitialize can2040 code
1350+
// API function to stop can2040 code
13181351
void
1319-
can2040_shutdown(struct can2040 *cd)
1352+
can2040_stop(struct can2040 *cd)
13201353
{
1321-
// XXX
1354+
pio_irq_disable(cd);
1355+
pio_sm_setup(cd);
1356+
}
1357+
1358+
// API function to access can2040 statistics
1359+
void
1360+
can2040_get_statistics(struct can2040 *cd, struct can2040_stats *stats)
1361+
{
1362+
for (;;) {
1363+
memcpy(stats, &cd->stats, sizeof(*stats));
1364+
if (memcmp(stats, &cd->stats, sizeof(*stats)) == 0)
1365+
// Successfully copied data
1366+
return;
1367+
// Raced with irq handler update - retry copy
1368+
}
13221369
}

lib/can2040/can2040.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,18 @@ struct can2040;
2626
typedef void (*can2040_rx_cb)(struct can2040 *cd, uint32_t notify
2727
, struct can2040_msg *msg);
2828

29+
struct can2040_stats {
30+
uint32_t rx_total, tx_total;
31+
uint32_t tx_attempt;
32+
uint32_t parse_error;
33+
};
34+
2935
void can2040_setup(struct can2040 *cd, uint32_t pio_num);
3036
void can2040_callback_config(struct can2040 *cd, can2040_rx_cb rx_cb);
3137
void can2040_start(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate
3238
, uint32_t gpio_rx, uint32_t gpio_tx);
33-
void can2040_shutdown(struct can2040 *cd);
39+
void can2040_stop(struct can2040 *cd);
40+
void can2040_get_statistics(struct can2040 *cd, struct can2040_stats *stats);
3441
void can2040_pio_irq_handler(struct can2040 *cd);
3542
int can2040_check_transmit(struct can2040 *cd);
3643
int can2040_transmit(struct can2040 *cd, struct can2040_msg *msg);
@@ -56,6 +63,7 @@ struct can2040 {
5663
void *pio_hw;
5764
uint32_t gpio_rx, gpio_tx;
5865
can2040_rx_cb rx_cb;
66+
struct can2040_stats stats;
5967

6068
// Bit unstuffing
6169
struct can2040_bitunstuffer unstuf;

0 commit comments

Comments
 (0)