Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Klipper3d/klipper.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2022-06-12 02:37:30 +0300
committerKevin O'Connor <kevin@koconnor.net>2022-06-27 17:50:23 +0300
commitc8cc98ce5dce3771cf2728eee7b1bdb026504f75 (patch)
tree9a381181998d1a33c39b2c9c16697c5a9e038f90
parent11828387d93f1f68107858d98fc81e2e29b5edf6 (diff)
canserial: Rename canbus.c to canserial.c
Rename the canbus.c code to canserial.c and introduce new wrapper functions in canbus.c that connect the low-level canbus hardware code to the high-level canserial.c code. This is in preparation for adding "usb to canbus bridge mode". Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/Kconfig5
-rw-r--r--src/generic/canbus.c334
-rw-r--r--src/generic/canbus.h4
-rw-r--r--src/generic/canserial.c343
-rw-r--r--src/generic/canserial.h19
-rw-r--r--src/stm32/Makefile4
-rw-r--r--src/stm32/can.c1
-rw-r--r--src/stm32/chipid.c6
-rwxr-xr-xsrc/stm32/fdcan.c1
9 files changed, 385 insertions, 332 deletions
diff --git a/src/Kconfig b/src/Kconfig
index 79cb4182c..921370f69 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -80,8 +80,11 @@ endmenu
# Generic configuration options for CANbus
config CANSERIAL
bool
+config CANBUS
+ bool
+ default y if CANSERIAL
config CANBUS_FREQUENCY
- int "CAN bus speed" if LOW_LEVEL_OPTIONS && CANSERIAL
+ int "CAN bus speed" if LOW_LEVEL_OPTIONS && CANBUS
default 500000
config CANBUS_FILTER
bool
diff --git a/src/generic/canbus.c b/src/generic/canbus.c
index 3cc051c8b..a4f33aa1f 100644
--- a/src/generic/canbus.c
+++ b/src/generic/canbus.c
@@ -1,342 +1,32 @@
-// Generic handling of serial over CAN support
+// Wrapper functions connecting canserial.c to low-level can hardware
//
-// Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
-// Copyright (C) 2020 Pontus Borg <glpontus@gmail.com>
-// Copyright (C) 2021 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2022 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#include <string.h> // memcpy
-#include "board/armcm_reset.h" // try_request_canboot
-#include "board/io.h" // readb
-#include "board/irq.h" // irq_save
-#include "board/misc.h" // console_sendf
-#include "canbus.h" // canbus_set_uuid
-#include "command.h" // DECL_CONSTANT
-#include "fasthash.h" // fasthash64
-#include "sched.h" // sched_wake_task
+#include "canbus.h" // canbus_send
+#include "canserial.h" // canserial_send
-#define CANBUS_UUID_LEN 6
-
-// Global storage
-static struct canbus_data {
- uint32_t assigned_id;
- uint8_t uuid[CANBUS_UUID_LEN];
-
- // Tx data
- struct task_wake tx_wake;
- uint8_t transmit_pos, transmit_max;
-
- // Rx data
- struct task_wake rx_wake;
- uint8_t receive_pos;
- uint32_t admin_pull_pos, admin_push_pos;
-
- // Transfer buffers
- struct canbus_msg admin_queue[8];
- uint8_t transmit_buf[96];
- uint8_t receive_buf[192];
-} CanData;
-
-
-/****************************************************************
- * Data transmission over CAN
- ****************************************************************/
-
-void
-canbus_notify_tx(void)
+int
+canserial_send(struct canbus_msg *msg)
{
- sched_wake_task(&CanData.tx_wake);
+ return canbus_send(msg);
}
void
-canbus_tx_task(void)
+canserial_set_filter(uint32_t id)
{
- if (!sched_check_wake(&CanData.tx_wake))
- return;
- uint32_t id = CanData.assigned_id;
- if (!id) {
- CanData.transmit_pos = CanData.transmit_max = 0;
- return;
- }
- struct canbus_msg msg;
- msg.id = id + 1;
- uint32_t tpos = CanData.transmit_pos, tmax = CanData.transmit_max;
- for (;;) {
- int avail = tmax - tpos, now = avail > 8 ? 8 : avail;
- if (avail <= 0)
- break;
- msg.dlc = now;
- memcpy(msg.data, &CanData.transmit_buf[tpos], now);
- int ret = canbus_send(&msg);
- if (ret <= 0)
- break;
- tpos += now;
- }
- CanData.transmit_pos = tpos;
+ canbus_set_filter(id);
}
-DECL_TASK(canbus_tx_task);
-// Encode and transmit a "response" message
void
-console_sendf(const struct command_encoder *ce, va_list args)
-{
- // Verify space for message
- uint32_t tpos = CanData.transmit_pos, tmax = CanData.transmit_max;
- if (tpos >= tmax)
- CanData.transmit_pos = CanData.transmit_max = tpos = tmax = 0;
- uint32_t max_size = ce->max_size;
- if (tmax + max_size > sizeof(CanData.transmit_buf)) {
- if (tmax + max_size - tpos > sizeof(CanData.transmit_buf))
- // Not enough space for message
- return;
- // Move buffer
- tmax -= tpos;
- memmove(&CanData.transmit_buf[0], &CanData.transmit_buf[tpos], tmax);
- CanData.transmit_pos = tpos = 0;
- CanData.transmit_max = tmax;
- }
-
- // Generate message
- uint32_t msglen = command_encode_and_frame(&CanData.transmit_buf[tmax]
- , ce, args);
-
- // Start message transmit
- CanData.transmit_max = tmax + msglen;
- canbus_notify_tx();
-}
-
-
-/****************************************************************
- * CAN "admin" command handling
- ****************************************************************/
-
-// Available commands and responses
-#define CANBUS_CMD_QUERY_UNASSIGNED 0x00
-#define CANBUS_CMD_SET_KLIPPER_NODEID 0x01
-#define CANBUS_CMD_REQUEST_BOOTLOADER 0x02
-#define CANBUS_RESP_NEED_NODEID 0x20
-
-// Helper to verify a UUID in a command matches this chip's UUID
-static int
-can_check_uuid(struct canbus_msg *msg)
-{
- return (msg->dlc >= 7
- && memcmp(&msg->data[1], CanData.uuid, sizeof(CanData.uuid)) == 0);
-}
-
-// Helpers to encode/decode a CAN identifier to a 1-byte "nodeid"
-static int
-can_get_nodeid(void)
-{
- if (!CanData.assigned_id)
- return 0;
- return (CanData.assigned_id - 0x100) >> 1;
-}
-static uint32_t
-can_decode_nodeid(int nodeid)
-{
- return (nodeid << 1) + 0x100;
-}
-
-static void
-can_process_query_unassigned(struct canbus_msg *msg)
-{
- if (CanData.assigned_id)
- return;
- struct canbus_msg send;
- send.id = CANBUS_ID_ADMIN_RESP;
- send.dlc = 8;
- send.data[0] = CANBUS_RESP_NEED_NODEID;
- memcpy(&send.data[1], CanData.uuid, sizeof(CanData.uuid));
- send.data[7] = CANBUS_CMD_SET_KLIPPER_NODEID;
- // Send with retry
- for (;;) {
- int ret = canbus_send(&send);
- if (ret >= 0)
- return;
- }
-}
-
-static void
-can_id_conflict(void)
-{
- CanData.assigned_id = 0;
- canbus_set_filter(CanData.assigned_id);
- shutdown("Another CAN node assigned this ID");
-}
-
-static void
-can_process_set_klipper_nodeid(struct canbus_msg *msg)
-{
- if (msg->dlc < 8)
- return;
- uint32_t newid = can_decode_nodeid(msg->data[7]);
- if (can_check_uuid(msg)) {
- if (newid != CanData.assigned_id) {
- CanData.assigned_id = newid;
- canbus_set_filter(CanData.assigned_id);
- }
- } else if (newid == CanData.assigned_id) {
- can_id_conflict();
- }
-}
-
-static void
-can_process_request_bootloader(struct canbus_msg *msg)
-{
- if (!can_check_uuid(msg))
- return;
- try_request_canboot();
-}
-
-// Handle an "admin" command
-static void
-can_process_admin(struct canbus_msg *msg)
-{
- if (!msg->dlc)
- return;
- switch (msg->data[0]) {
- case CANBUS_CMD_QUERY_UNASSIGNED:
- can_process_query_unassigned(msg);
- break;
- case CANBUS_CMD_SET_KLIPPER_NODEID:
- can_process_set_klipper_nodeid(msg);
- break;
- case CANBUS_CMD_REQUEST_BOOTLOADER:
- can_process_request_bootloader(msg);
- break;
- }
-}
-
-
-/****************************************************************
- * CAN packet reading
- ****************************************************************/
-
-static void
-canbus_notify_rx(void)
+canbus_notify_tx(void)
{
- sched_wake_task(&CanData.rx_wake);
+ canserial_notify_tx();
}
-DECL_CONSTANT("RECEIVE_WINDOW", ARRAY_SIZE(CanData.receive_buf));
-
-// Handle incoming data (called from IRQ handler)
void
canbus_process_data(struct canbus_msg *msg)
{
- uint32_t id = msg->id;
- if (CanData.assigned_id && id == CanData.assigned_id) {
- // Add to incoming data buffer
- int rpos = CanData.receive_pos;
- uint32_t len = CANMSG_DATA_LEN(msg);
- if (len > sizeof(CanData.receive_buf) - rpos)
- len = sizeof(CanData.receive_buf) - rpos;
- memcpy(&CanData.receive_buf[rpos], msg->data, len);
- CanData.receive_pos = rpos + len;
- canbus_notify_rx();
- } else if (id == CANBUS_ID_ADMIN
- || (CanData.assigned_id && id == CanData.assigned_id + 1)) {
- // Add to admin command queue
- uint32_t pushp = CanData.admin_push_pos;
- if (pushp >= CanData.admin_pull_pos + ARRAY_SIZE(CanData.admin_queue))
- // No space - drop message
- return;
- uint32_t pos = pushp % ARRAY_SIZE(CanData.admin_queue);
- memcpy(&CanData.admin_queue[pos], msg, sizeof(*msg));
- CanData.admin_push_pos = pushp + 1;
- canbus_notify_rx();
- }
-}
-
-// Remove from the receive buffer the given number of bytes
-static void
-console_pop_input(int len)
-{
- int copied = 0;
- for (;;) {
- int rpos = readb(&CanData.receive_pos);
- int needcopy = rpos - len;
- if (needcopy) {
- memmove(&CanData.receive_buf[copied]
- , &CanData.receive_buf[copied + len], needcopy - copied);
- copied = needcopy;
- canbus_notify_rx();
- }
- irqstatus_t flag = irq_save();
- if (rpos != readb(&CanData.receive_pos)) {
- // Raced with irq handler - retry
- irq_restore(flag);
- continue;
- }
- CanData.receive_pos = needcopy;
- irq_restore(flag);
- break;
- }
-}
-
-// Task to process incoming commands and admin messages
-void
-canbus_rx_task(void)
-{
- if (!sched_check_wake(&CanData.rx_wake))
- return;
-
- // Process pending admin messages
- for (;;) {
- uint32_t pushp = readl(&CanData.admin_push_pos);
- uint32_t pullp = CanData.admin_pull_pos;
- if (pushp == pullp)
- break;
- uint32_t pos = pullp % ARRAY_SIZE(CanData.admin_queue);
- struct canbus_msg *msg = &CanData.admin_queue[pos];
- uint32_t id = msg->id;
- if (CanData.assigned_id && id == CanData.assigned_id + 1)
- can_id_conflict();
- else if (id == CANBUS_ID_ADMIN)
- can_process_admin(msg);
- CanData.admin_pull_pos = pullp + 1;
- }
-
- // Check for a complete message block and process it
- uint_fast8_t rpos = readb(&CanData.receive_pos), pop_count;
- int ret = command_find_block(CanData.receive_buf, rpos, &pop_count);
- if (ret > 0)
- command_dispatch(CanData.receive_buf, pop_count);
- if (ret) {
- console_pop_input(pop_count);
- if (ret > 0)
- command_send_ack();
- }
-}
-DECL_TASK(canbus_rx_task);
-
-
-/****************************************************************
- * Setup and shutdown
- ****************************************************************/
-
-void
-command_get_canbus_id(uint32_t *args)
-{
- sendf("canbus_id canbus_uuid=%.*s canbus_nodeid=%u"
- , sizeof(CanData.uuid), CanData.uuid, can_get_nodeid());
-}
-DECL_COMMAND_FLAGS(command_get_canbus_id, HF_IN_SHUTDOWN, "get_canbus_id");
-
-void
-canbus_set_uuid(uint8_t *raw_uuid, uint32_t raw_uuid_len)
-{
- uint64_t hash = fasthash64(raw_uuid, raw_uuid_len, 0xA16231A7);
- memcpy(CanData.uuid, &hash, sizeof(CanData.uuid));
- canbus_notify_rx();
-}
-
-void
-canbus_shutdown(void)
-{
- canbus_notify_tx();
- canbus_notify_rx();
+ canserial_process_data(msg);
}
-DECL_SHUTDOWN(canbus_shutdown);
diff --git a/src/generic/canbus.h b/src/generic/canbus.h
index 79cb3245b..8032611a2 100644
--- a/src/generic/canbus.h
+++ b/src/generic/canbus.h
@@ -3,9 +3,6 @@
#include <stdint.h> // uint32_t
-#define CANBUS_ID_ADMIN 0x3f0
-#define CANBUS_ID_ADMIN_RESP 0x3f1
-
struct canbus_msg {
uint32_t id;
uint32_t dlc;
@@ -27,6 +24,5 @@ void canbus_set_filter(uint32_t id);
// canbus.c
void canbus_notify_tx(void);
void canbus_process_data(struct canbus_msg *msg);
-void canbus_set_uuid(uint8_t *raw_uuid, uint32_t raw_uuid_len);
#endif // canbus.h
diff --git a/src/generic/canserial.c b/src/generic/canserial.c
new file mode 100644
index 000000000..ba0ec4614
--- /dev/null
+++ b/src/generic/canserial.c
@@ -0,0 +1,343 @@
+// Generic handling of serial over CAN support
+//
+// Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
+// Copyright (C) 2020 Pontus Borg <glpontus@gmail.com>
+// Copyright (C) 2021 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include <string.h> // memcpy
+#include "board/armcm_reset.h" // try_request_canboot
+#include "board/io.h" // readb
+#include "board/irq.h" // irq_save
+#include "board/misc.h" // console_sendf
+#include "canbus.h" // canbus_set_uuid
+#include "canserial.h" // canserial_notify_tx
+#include "command.h" // DECL_CONSTANT
+#include "fasthash.h" // fasthash64
+#include "sched.h" // sched_wake_task
+
+#define CANBUS_UUID_LEN 6
+
+// Global storage
+static struct canbus_data {
+ uint32_t assigned_id;
+ uint8_t uuid[CANBUS_UUID_LEN];
+
+ // Tx data
+ struct task_wake tx_wake;
+ uint8_t transmit_pos, transmit_max;
+
+ // Rx data
+ struct task_wake rx_wake;
+ uint8_t receive_pos;
+ uint32_t admin_pull_pos, admin_push_pos;
+
+ // Transfer buffers
+ struct canbus_msg admin_queue[8];
+ uint8_t transmit_buf[96];
+ uint8_t receive_buf[192];
+} CanData;
+
+
+/****************************************************************
+ * Data transmission over CAN
+ ****************************************************************/
+
+void
+canserial_notify_tx(void)
+{
+ sched_wake_task(&CanData.tx_wake);
+}
+
+void
+canserial_tx_task(void)
+{
+ if (!sched_check_wake(&CanData.tx_wake))
+ return;
+ uint32_t id = CanData.assigned_id;
+ if (!id) {
+ CanData.transmit_pos = CanData.transmit_max = 0;
+ return;
+ }
+ struct canbus_msg msg;
+ msg.id = id + 1;
+ uint32_t tpos = CanData.transmit_pos, tmax = CanData.transmit_max;
+ for (;;) {
+ int avail = tmax - tpos, now = avail > 8 ? 8 : avail;
+ if (avail <= 0)
+ break;
+ msg.dlc = now;
+ memcpy(msg.data, &CanData.transmit_buf[tpos], now);
+ int ret = canserial_send(&msg);
+ if (ret <= 0)
+ break;
+ tpos += now;
+ }
+ CanData.transmit_pos = tpos;
+}
+DECL_TASK(canserial_tx_task);
+
+// Encode and transmit a "response" message
+void
+console_sendf(const struct command_encoder *ce, va_list args)
+{
+ // Verify space for message
+ uint32_t tpos = CanData.transmit_pos, tmax = CanData.transmit_max;
+ if (tpos >= tmax)
+ CanData.transmit_pos = CanData.transmit_max = tpos = tmax = 0;
+ uint32_t max_size = ce->max_size;
+ if (tmax + max_size > sizeof(CanData.transmit_buf)) {
+ if (tmax + max_size - tpos > sizeof(CanData.transmit_buf))
+ // Not enough space for message
+ return;
+ // Move buffer
+ tmax -= tpos;
+ memmove(&CanData.transmit_buf[0], &CanData.transmit_buf[tpos], tmax);
+ CanData.transmit_pos = tpos = 0;
+ CanData.transmit_max = tmax;
+ }
+
+ // Generate message
+ uint32_t msglen = command_encode_and_frame(&CanData.transmit_buf[tmax]
+ , ce, args);
+
+ // Start message transmit
+ CanData.transmit_max = tmax + msglen;
+ canserial_notify_tx();
+}
+
+
+/****************************************************************
+ * CAN "admin" command handling
+ ****************************************************************/
+
+// Available commands and responses
+#define CANBUS_CMD_QUERY_UNASSIGNED 0x00
+#define CANBUS_CMD_SET_KLIPPER_NODEID 0x01
+#define CANBUS_CMD_REQUEST_BOOTLOADER 0x02
+#define CANBUS_RESP_NEED_NODEID 0x20
+
+// Helper to verify a UUID in a command matches this chip's UUID
+static int
+can_check_uuid(struct canbus_msg *msg)
+{
+ return (msg->dlc >= 7
+ && memcmp(&msg->data[1], CanData.uuid, sizeof(CanData.uuid)) == 0);
+}
+
+// Helpers to encode/decode a CAN identifier to a 1-byte "nodeid"
+static int
+can_get_nodeid(void)
+{
+ if (!CanData.assigned_id)
+ return 0;
+ return (CanData.assigned_id - 0x100) >> 1;
+}
+static uint32_t
+can_decode_nodeid(int nodeid)
+{
+ return (nodeid << 1) + 0x100;
+}
+
+static void
+can_process_query_unassigned(struct canbus_msg *msg)
+{
+ if (CanData.assigned_id)
+ return;
+ struct canbus_msg send;
+ send.id = CANBUS_ID_ADMIN_RESP;
+ send.dlc = 8;
+ send.data[0] = CANBUS_RESP_NEED_NODEID;
+ memcpy(&send.data[1], CanData.uuid, sizeof(CanData.uuid));
+ send.data[7] = CANBUS_CMD_SET_KLIPPER_NODEID;
+ // Send with retry
+ for (;;) {
+ int ret = canserial_send(&send);
+ if (ret >= 0)
+ return;
+ }
+}
+
+static void
+can_id_conflict(void)
+{
+ CanData.assigned_id = 0;
+ canserial_set_filter(CanData.assigned_id);
+ shutdown("Another CAN node assigned this ID");
+}
+
+static void
+can_process_set_klipper_nodeid(struct canbus_msg *msg)
+{
+ if (msg->dlc < 8)
+ return;
+ uint32_t newid = can_decode_nodeid(msg->data[7]);
+ if (can_check_uuid(msg)) {
+ if (newid != CanData.assigned_id) {
+ CanData.assigned_id = newid;
+ canserial_set_filter(CanData.assigned_id);
+ }
+ } else if (newid == CanData.assigned_id) {
+ can_id_conflict();
+ }
+}
+
+static void
+can_process_request_bootloader(struct canbus_msg *msg)
+{
+ if (!can_check_uuid(msg))
+ return;
+ try_request_canboot();
+}
+
+// Handle an "admin" command
+static void
+can_process_admin(struct canbus_msg *msg)
+{
+ if (!msg->dlc)
+ return;
+ switch (msg->data[0]) {
+ case CANBUS_CMD_QUERY_UNASSIGNED:
+ can_process_query_unassigned(msg);
+ break;
+ case CANBUS_CMD_SET_KLIPPER_NODEID:
+ can_process_set_klipper_nodeid(msg);
+ break;
+ case CANBUS_CMD_REQUEST_BOOTLOADER:
+ can_process_request_bootloader(msg);
+ break;
+ }
+}
+
+
+/****************************************************************
+ * CAN packet reading
+ ****************************************************************/
+
+static void
+canserial_notify_rx(void)
+{
+ sched_wake_task(&CanData.rx_wake);
+}
+
+DECL_CONSTANT("RECEIVE_WINDOW", ARRAY_SIZE(CanData.receive_buf));
+
+// Handle incoming data (called from IRQ handler)
+void
+canserial_process_data(struct canbus_msg *msg)
+{
+ uint32_t id = msg->id;
+ if (CanData.assigned_id && id == CanData.assigned_id) {
+ // Add to incoming data buffer
+ int rpos = CanData.receive_pos;
+ uint32_t len = CANMSG_DATA_LEN(msg);
+ if (len > sizeof(CanData.receive_buf) - rpos)
+ len = sizeof(CanData.receive_buf) - rpos;
+ memcpy(&CanData.receive_buf[rpos], msg->data, len);
+ CanData.receive_pos = rpos + len;
+ canserial_notify_rx();
+ } else if (id == CANBUS_ID_ADMIN
+ || (CanData.assigned_id && id == CanData.assigned_id + 1)) {
+ // Add to admin command queue
+ uint32_t pushp = CanData.admin_push_pos;
+ if (pushp >= CanData.admin_pull_pos + ARRAY_SIZE(CanData.admin_queue))
+ // No space - drop message
+ return;
+ uint32_t pos = pushp % ARRAY_SIZE(CanData.admin_queue);
+ memcpy(&CanData.admin_queue[pos], msg, sizeof(*msg));
+ CanData.admin_push_pos = pushp + 1;
+ canserial_notify_rx();
+ }
+}
+
+// Remove from the receive buffer the given number of bytes
+static void
+console_pop_input(int len)
+{
+ int copied = 0;
+ for (;;) {
+ int rpos = readb(&CanData.receive_pos);
+ int needcopy = rpos - len;
+ if (needcopy) {
+ memmove(&CanData.receive_buf[copied]
+ , &CanData.receive_buf[copied + len], needcopy - copied);
+ copied = needcopy;
+ canserial_notify_rx();
+ }
+ irqstatus_t flag = irq_save();
+ if (rpos != readb(&CanData.receive_pos)) {
+ // Raced with irq handler - retry
+ irq_restore(flag);
+ continue;
+ }
+ CanData.receive_pos = needcopy;
+ irq_restore(flag);
+ break;
+ }
+}
+
+// Task to process incoming commands and admin messages
+void
+canserial_rx_task(void)
+{
+ if (!sched_check_wake(&CanData.rx_wake))
+ return;
+
+ // Process pending admin messages
+ for (;;) {
+ uint32_t pushp = readl(&CanData.admin_push_pos);
+ uint32_t pullp = CanData.admin_pull_pos;
+ if (pushp == pullp)
+ break;
+ uint32_t pos = pullp % ARRAY_SIZE(CanData.admin_queue);
+ struct canbus_msg *msg = &CanData.admin_queue[pos];
+ uint32_t id = msg->id;
+ if (CanData.assigned_id && id == CanData.assigned_id + 1)
+ can_id_conflict();
+ else if (id == CANBUS_ID_ADMIN)
+ can_process_admin(msg);
+ CanData.admin_pull_pos = pullp + 1;
+ }
+
+ // Check for a complete message block and process it
+ uint_fast8_t rpos = readb(&CanData.receive_pos), pop_count;
+ int ret = command_find_block(CanData.receive_buf, rpos, &pop_count);
+ if (ret > 0)
+ command_dispatch(CanData.receive_buf, pop_count);
+ if (ret) {
+ console_pop_input(pop_count);
+ if (ret > 0)
+ command_send_ack();
+ }
+}
+DECL_TASK(canserial_rx_task);
+
+
+/****************************************************************
+ * Setup and shutdown
+ ****************************************************************/
+
+void
+command_get_canbus_id(uint32_t *args)
+{
+ sendf("canbus_id canbus_uuid=%.*s canbus_nodeid=%u"
+ , sizeof(CanData.uuid), CanData.uuid, can_get_nodeid());
+}
+DECL_COMMAND_FLAGS(command_get_canbus_id, HF_IN_SHUTDOWN, "get_canbus_id");
+
+void
+canserial_set_uuid(uint8_t *raw_uuid, uint32_t raw_uuid_len)
+{
+ uint64_t hash = fasthash64(raw_uuid, raw_uuid_len, 0xA16231A7);
+ memcpy(CanData.uuid, &hash, sizeof(CanData.uuid));
+ canserial_notify_rx();
+}
+
+void
+canserial_shutdown(void)
+{
+ canserial_notify_tx();
+ canserial_notify_rx();
+}
+DECL_SHUTDOWN(canserial_shutdown);
diff --git a/src/generic/canserial.h b/src/generic/canserial.h
new file mode 100644
index 000000000..ac4b77143
--- /dev/null
+++ b/src/generic/canserial.h
@@ -0,0 +1,19 @@
+#ifndef __CANSERIAL_H__
+#define __CANSERIAL_H__
+
+#include <stdint.h> // uint32_t
+
+#define CANBUS_ID_ADMIN 0x3f0
+#define CANBUS_ID_ADMIN_RESP 0x3f1
+
+// callbacks provided by board specific code
+struct canbus_msg;
+int canserial_send(struct canbus_msg *msg);
+void canserial_set_filter(uint32_t id);
+
+// canserial.c
+void canserial_notify_tx(void);
+void canserial_process_data(struct canbus_msg *msg);
+void canserial_set_uuid(uint8_t *raw_uuid, uint32_t raw_uuid_len);
+
+#endif // canbus.h
diff --git a/src/stm32/Makefile b/src/stm32/Makefile
index fa662f910..2fbf75498 100644
--- a/src/stm32/Makefile
+++ b/src/stm32/Makefile
@@ -59,10 +59,10 @@ serial-src-$(CONFIG_MACH_STM32F0) := stm32/stm32f0_serial.c
serial-src-$(CONFIG_MACH_STM32G0) := stm32/stm32f0_serial.c
serial-src-$(CONFIG_MACH_STM32H7) := stm32/stm32h7_serial.c
src-$(CONFIG_SERIAL) += $(serial-src-y) generic/serial_irq.c
-canbus-src-y := generic/canbus.c ../lib/fast-hash/fasthash.c
+canbus-src-y := generic/canserial.c ../lib/fast-hash/fasthash.c
canbus-src-$(CONFIG_HAVE_STM32_CANBUS) += stm32/can.c
canbus-src-$(CONFIG_HAVE_STM32_FDCANBUS) += stm32/fdcan.c
-src-$(CONFIG_CANSERIAL) += $(canbus-src-y) stm32/chipid.c
+src-$(CONFIG_CANSERIAL) += $(canbus-src-y) generic/canbus.c stm32/chipid.c
src-$(CONFIG_HAVE_GPIO_HARD_PWM) += stm32/hard_pwm.c
# Binary output file rules
diff --git a/src/stm32/can.c b/src/stm32/can.c
index 6e50cea97..427a78551 100644
--- a/src/stm32/can.c
+++ b/src/stm32/can.c
@@ -12,6 +12,7 @@
#include "command.h" // DECL_CONSTANT_STR
#include "generic/armcm_boot.h" // armcm_enable_irq
#include "generic/canbus.h" // canbus_notify_tx
+#include "generic/canserial.h" // CANBUS_ID_ADMIN
#include "internal.h" // enable_pclock
#include "sched.h" // DECL_INIT
diff --git a/src/stm32/chipid.c b/src/stm32/chipid.c
index 035177397..e30563cde 100644
--- a/src/stm32/chipid.c
+++ b/src/stm32/chipid.c
@@ -4,7 +4,7 @@
//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#include "generic/canbus.h" // canbus_set_uuid
+#include "generic/canserial.h" // canserial_set_uuid
#include "generic/usb_cdc.h" // usb_fill_serial
#include "generic/usbstd.h" // usb_string_descriptor
#include "internal.h" // UID_BASE
@@ -29,7 +29,7 @@ chipid_init(void)
if (CONFIG_USB_SERIAL_NUMBER_CHIPID)
usb_fill_serial(&cdc_chipid.desc, ARRAY_SIZE(cdc_chipid.data)
, (void*)UID_BASE);
- if (CONFIG_CANSERIAL)
- canbus_set_uuid((void*)UID_BASE, CHIP_UID_LEN);
+ if (CONFIG_CANBUS)
+ canserial_set_uuid((void*)UID_BASE, CHIP_UID_LEN);
}
DECL_INIT(chipid_init);
diff --git a/src/stm32/fdcan.c b/src/stm32/fdcan.c
index 3af9ffa8b..c142420e4 100755
--- a/src/stm32/fdcan.c
+++ b/src/stm32/fdcan.c
@@ -12,6 +12,7 @@
#include "command.h" // DECL_CONSTANT_STR
#include "generic/armcm_boot.h" // armcm_enable_irq
#include "generic/canbus.h" // canbus_notify_tx
+#include "generic/canserial.h" // CANBUS_ID_ADMIN
#include "generic/serial_irq.h" // serial_rx_byte
#include "internal.h" // enable_pclock
#include "sched.h" // DECL_INIT