From 6fdf57cca7c86285d0e72d67b313b3cd33761021 Mon Sep 17 00:00:00 2001 From: helgie22 Date: Thu, 15 Oct 2026 15:51:19 +0000 Subject: [PATCH] =?UTF-8?q?b=C3=A6tti=20vi=C3=B0=20can=20m=C3=B3tt=C3=B6ku?= =?UTF-8?q?pr=C3=B3fi=20me=C3=B0=20s=C3=ADu=20(Part=202.1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platformio.ini | 6 ++++ src/can_rx_test.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 3 ++ 3 files changed, 89 insertions(+) create mode 100644 src/can_rx_test.c diff --git a/platformio.ini b/platformio.ini index e2183d5..de6a0ed 100644 --- a/platformio.ini +++ b/platformio.ini @@ -33,3 +33,9 @@ build_flags = -D CAN_SEND_TEST=1 [env:can_frame_test] extends = env:nucleo_l432kc build_flags = -D CAN_FRAME_TEST=1 + +; CAN reception with a filter (src/can_rx_test.c) instead of the motor app. +; Build/upload: pio run -e can_rx_test -t upload +[env:can_rx_test] +extends = env:nucleo_l432kc +build_flags = -D CAN_RX_TEST=1 diff --git a/src/can_rx_test.c b/src/can_rx_test.c new file mode 100644 index 0000000..234f8dc --- /dev/null +++ b/src/can_rx_test.c @@ -0,0 +1,80 @@ +// Part 2.1: CAN reception with a filter. Only frames with id RX_CAN_ID are +// accepted. The driver puts them in a message queue from interrupt context, +// and the main loop takes them out and prints them. +// Built only with the can_rx_test environment (-D CAN_RX_TEST=1). +// +// Test from the Pi: +// cansend can0 321#DEADBEEF -> printed by the Nucleo +// cansend can0 322#DEADBEEF -> rejected by the filter, nothing printed + +#include +#include +#include +#include +#include + +#define CANBUS_NODE DT_CHOSEN(zephyr_canbus) +#define CAN_BITRATE 125000 // Must match the bitrate of can0 on the Pi +#define RX_CAN_ID 0x321 // The only id this node accepts + +// Queue for up to 10 received frames. The CAN driver fills it in the +// receive interrupt; nothing else runs in interrupt context. +CAN_MSGQ_DEFINE(rx_msgq, 10); + +void can_rx_test_main(void) +{ + const struct device *dev = DEVICE_DT_GET(CANBUS_NODE); + + if (!device_is_ready(dev)) { + printk("CAN device not ready\n"); + return; + } + + int err = can_set_bitrate(dev, CAN_BITRATE); + if (err != 0) { + printk("Error setting CAN bitrate (err %d)\n", err); + return; + } + + // Accept only RX_CAN_ID: all 11 bits of the id must match the mask. + const struct can_filter filter = { + .id = RX_CAN_ID, + .mask = CAN_STD_ID_MASK, +#ifdef CAN_FILTER_DATA + // Older Zephyr versions must be told to match data frames. + .flags = CAN_FILTER_DATA, +#else + .flags = 0, +#endif + }; + + // Returns a filter id (>= 0) on success. + int filter_id = can_add_rx_filter_msgq(dev, &rx_msgq, &filter); + if (filter_id < 0) { + printk("Error adding RX filter (err %d)\n", filter_id); + return; + } + + err = can_start(dev); + if (err != 0) { + printk("Error starting CAN controller (err %d)\n", err); + return; + } + + printk("CAN RX test: %d bit/s, accepting id 0x%03X\n", + CAN_BITRATE, RX_CAN_ID); + + struct can_frame frame; + + while (1) { + // Sleeps until a frame is in the queue, then processes it here in + // the main thread, where printing is allowed. + k_msgq_get(&rx_msgq, &frame, K_FOREVER); + + printk("Received id 0x%03X [%d]:", frame.id, frame.dlc); + for (int i = 0; i < can_dlc_to_bytes(frame.dlc); i++) { + printk(" %02X", frame.data[i]); + } + printk("\n"); + } +} diff --git a/src/main.c b/src/main.c index cc5c770..a8cee1f 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ void motor_application_main(void); void can_send_test_main(void); void can_frame_test_main(void); +void can_rx_test_main(void); int main(void) { @@ -10,6 +11,8 @@ int main(void) can_send_test_main(); #elif CAN_FRAME_TEST can_frame_test_main(); +#elif CAN_RX_TEST + can_rx_test_main(); #else motor_application_main(); #endif