aboutsummaryrefslogtreecommitdiffstats
path: root/src/rp2040
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2022-05-23 01:04:32 -0400
committerKevin O'Connor <kevin@koconnor.net>2022-07-06 00:28:48 -0400
commita831254e833e5713b85b87d5fa27d5d9f2cb3843 (patch)
tree60d20e0fd45b38eb8896e314115212847469e8aa /src/rp2040
parentf10fd7c2fabec78f5b30a2f3e6ec79cd8a3e4805 (diff)
downloadkutter-a831254e833e5713b85b87d5fa27d5d9f2cb3843.tar.gz
kutter-a831254e833e5713b85b87d5fa27d5d9f2cb3843.tar.xz
kutter-a831254e833e5713b85b87d5fa27d5d9f2cb3843.zip
rp2040: Initial support for CANbus
Add support for CANbus on the rp2040 using the can2040 "software canbus" implementation. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/rp2040')
-rw-r--r--src/rp2040/Kconfig13
-rw-r--r--src/rp2040/Makefile7
-rw-r--r--src/rp2040/can.c78
-rw-r--r--src/rp2040/chipid.c13
4 files changed, 104 insertions, 7 deletions
diff --git a/src/rp2040/Kconfig b/src/rp2040/Kconfig
index 8bad20c9..2e5f5019 100644
--- a/src/rp2040/Kconfig
+++ b/src/rp2040/Kconfig
@@ -83,6 +83,19 @@ choice
config RP2040_SERIAL_UART0
bool "Serial (on UART0 GPIO1/GPIO0)"
select SERIAL
+ config RP2040_CANBUS
+ bool "CAN bus"
+ select CANSERIAL
endchoice
+config RP2040_CANBUS_GPIO_RX
+ int "CAN RX gpio number" if CANBUS
+ default 4
+ range 0 29
+
+config RP2040_CANBUS_GPIO_TX
+ int "CAN TX gpio number" if CANBUS
+ default 5
+ range 0 29
+
endif
diff --git a/src/rp2040/Makefile b/src/rp2040/Makefile
index ffc2c4c8..f49d56ac 100644
--- a/src/rp2040/Makefile
+++ b/src/rp2040/Makefile
@@ -3,10 +3,10 @@
# Setup the toolchain
CROSS_PREFIX=arm-none-eabi-
-dirs-y += src/rp2040 src/generic lib/rp2040/elf2uf2
+dirs-y += src/rp2040 src/generic lib/rp2040/elf2uf2 lib/fast-hash lib/can2040
CFLAGS += -mcpu=cortex-m0plus -mthumb -Ilib/cmsis-core
-CFLAGS += -Ilib/rp2040 -Ilib/rp2040/cmsis_include
+CFLAGS += -Ilib/rp2040 -Ilib/rp2040/cmsis_include -Ilib/fast-hash -Ilib/can2040
CFLAGS_klipper.elf += --specs=nano.specs --specs=nosys.specs
CFLAGS_klipper.elf += -T $(OUT)src/rp2040/rp2040_link.ld
@@ -19,6 +19,9 @@ src-y += generic/timer_irq.c rp2040/timer.c rp2040/bootrom.c
src-$(CONFIG_USBSERIAL) += rp2040/usbserial.c generic/usb_cdc.c
src-$(CONFIG_USBSERIAL) += rp2040/chipid.c
src-$(CONFIG_SERIAL) += rp2040/serial.c generic/serial_irq.c
+src-$(CONFIG_CANSERIAL) += rp2040/can.c rp2040/chipid.c ../lib/can2040/can2040.c
+src-$(CONFIG_CANSERIAL) += generic/canserial.c generic/canbus.c
+src-$(CONFIG_CANSERIAL) += ../lib/fast-hash/fasthash.c
src-$(CONFIG_HAVE_GPIO_HARD_PWM) += rp2040/hard_pwm.c
src-$(CONFIG_HAVE_GPIO_SPI) += rp2040/spi.c
src-$(CONFIG_HAVE_GPIO_I2C) += rp2040/i2c.c
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);
diff --git a/src/rp2040/chipid.c b/src/rp2040/chipid.c
index 95e760d1..80182f60 100644
--- a/src/rp2040/chipid.c
+++ b/src/rp2040/chipid.c
@@ -4,11 +4,10 @@
//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#define CHIP_UID_LEN 8
-
#include <string.h> // memcpy
#include "autoconf.h" // CONFIG_USB_SERIAL_NUMBER_CHIPID
#include "board/irq.h" // irq_disable, irq_enable
+#include "board/canserial.h" // canserial_set_uuid
#include "generic/usb_cdc.h" // usb_fill_serial
#include "generic/usbstd.h" // usb_string_descriptor
#include "sched.h" // DECL_INIT
@@ -16,6 +15,8 @@
#include "hardware/structs/ssi.h" // ssi_hw
#include "internal.h"
+#define CHIP_UID_LEN 8
+
static struct {
struct usb_string_descriptor desc;
uint16_t data[CHIP_UID_LEN * 2];
@@ -120,13 +121,15 @@ read_unique_id(uint8_t *out)
void
chipid_init(void)
{
- if (!CONFIG_USB_SERIAL_NUMBER_CHIPID)
+ if (!(CONFIG_USB_SERIAL_NUMBER_CHIPID || CONFIG_CANBUS))
return;
uint8_t data[8] = {0};
read_unique_id(data);
- usb_fill_serial(&cdc_chipid.desc, ARRAY_SIZE(cdc_chipid.data)
- , data);
+ if (CONFIG_USB_SERIAL_NUMBER_CHIPID)
+ usb_fill_serial(&cdc_chipid.desc, ARRAY_SIZE(cdc_chipid.data), data);
+ if (CONFIG_CANBUS)
+ canserial_set_uuid(data, CHIP_UID_LEN);
}
DECL_INIT(chipid_init);