aboutsummaryrefslogtreecommitdiffstats
path: root/src/rp2040/can.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rp2040/can.c')
-rw-r--r--src/rp2040/can.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/rp2040/can.c b/src/rp2040/can.c
new file mode 100644
index 00000000..9c42cf36
--- /dev/null
+++ b/src/rp2040/can.c
@@ -0,0 +1,78 @@
+// Serial over CAN emulation for rp2040 using can2040 software canbus
+//
+// Copyright (C) 2022 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include <stdint.h> // uint32_t
+#include <string.h> // memcpy
+#include "autoconf.h" // CONFIG_CANBUS_FREQUENCY
+#include "board/armcm_boot.h" // armcm_enable_irq
+#include "board/io.h" // readl
+#include "can2040.h" // can2040_setup
+#include "command.h" // DECL_CONSTANT_STR
+#include "fasthash.h" // fasthash64
+#include "generic/canbus.h" // canbus_notify_tx
+#include "generic/canserial.h" // CANBUS_ID_ADMIN
+#include "hardware/structs/resets.h" // RESETS_RESET_PIO0_BITS
+#include "internal.h" // DMA_IRQ_0_IRQn
+#include "sched.h" // DECL_INIT
+
+#define GPIO_STR_CAN_RX "gpio" __stringify(CONFIG_RP2040_CANBUS_GPIO_RX)
+#define GPIO_STR_CAN_TX "gpio" __stringify(CONFIG_RP2040_CANBUS_GPIO_TX)
+DECL_CONSTANT_STR("RESERVE_PINS_CAN", GPIO_STR_CAN_RX "," GPIO_STR_CAN_TX);
+
+static struct can2040 cbus;
+
+// Transmit a packet
+int
+canbus_send(struct canbus_msg *msg)
+{
+ int ret = can2040_transmit(&cbus, (void*)msg);
+ if (ret < 0)
+ return -1;
+ return CANMSG_DATA_LEN(msg);
+}
+
+// Setup the receive packet filter
+void
+canbus_set_filter(uint32_t id)
+{
+ // Filter not implemented (and not necessary)
+}
+
+// can2040 callback function - handle rx and tx notifications
+static void
+can2040_cb(struct can2040 *cd, uint32_t notify, struct can2040_msg *msg)
+{
+ if (notify & CAN2040_NOTIFY_TX) {
+ canbus_notify_tx();
+ return;
+ }
+ if (notify & CAN2040_NOTIFY_RX)
+ canbus_process_data((void*)msg);
+}
+
+// Main PIO irq handler
+void
+PIOx_IRQHandler(void)
+{
+ can2040_pio_irq_handler(&cbus);
+}
+
+void
+can_init(void)
+{
+ // Setup canbus
+ can2040_setup(&cbus, 0);
+ can2040_callback_config(&cbus, can2040_cb);
+
+ // Enable irqs
+ armcm_enable_irq(PIOx_IRQHandler, PIO0_IRQ_0_IRQn, 1);
+
+ // Start canbus
+ uint32_t pclk = get_pclock_frequency(RESETS_RESET_PIO0_RESET);
+ can2040_start(&cbus, pclk, CONFIG_CANBUS_FREQUENCY
+ , CONFIG_RP2040_CANBUS_GPIO_RX, CONFIG_RP2040_CANBUS_GPIO_TX);
+}
+DECL_INIT(can_init);