KevinOConnor / can2040

Software CAN bus implementation for rp2040 micro-controllers
GNU General Public License v3.0
636 stars 63 forks source link

Transmit Queue Hangs if no ACK Detected #53

Open wrongbaud opened 1 month ago

wrongbaud commented 1 month ago

Hi All,

I am looking for some insight or guidance on an issue I am running into with the can2040 libraries.

I have noticed that when I attempt to transmit a message, if the ACK is not detected, the RP2040 becomes unresponsive and needs a reset. It is entirely possible that I am using the library incorrectly, my code can be found below:

My code can be seen below:

#include <stdio.h>
#include <stdint.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/irq.h"
#include "can2040.h"
#include "RP2040.h"

static struct can2040 cbus;

static void can2040_cb(struct can2040 *cd, uint32_t notify, struct can2040_msg *msg)
{
    // Add message processing code here...
    return;
}

static void PIOx_IRQHandler(void)
{
    can2040_pio_irq_handler(&cbus);
}

void canbus_setup(void)
{
    uint32_t pio_num = 0;
    uint32_t sys_clock = 125000000, bitrate = 500000;
    uint32_t gpio_rx = 5, gpio_tx = 4;

    // Setup canbus
    can2040_setup(&cbus, pio_num);
    can2040_callback_config(&cbus, can2040_cb);

    // Enable irqs
    irq_set_exclusive_handler(PIO0_IRQ_0_IRQn, PIOx_IRQHandler);
    NVIC_SetPriority(PIO0_IRQ_0_IRQn, 1);
    NVIC_EnableIRQ(PIO0_IRQ_0_IRQn);

    // Start canbus
    can2040_start(&cbus, sys_clock, bitrate, gpio_rx, gpio_tx);
}

int main(void){
        stdio_init_all();
        canbus_setup();
        struct can2040_msg test_msg = {0x123,8,{1,2,3,4,5,6,7,8} };
        can2040_transmit(&cbus,&test_msg);
        can2040_transmit(&cbus,&test_msg);
}

When I run the above code, I only see one attempt at transmitting the test message.

My test setup is as follows:

I have tried both with a 120 ohm termination resistor and without.

Here is a Saleae screenshot of the ACK not being received. For my application, the RP2040 is the first active node on the bus so I expect it to not receive some ACK bits while the system is still powering up.

can-prob

I've tried analyzing this behavior with multiple adapters, and have only ever seen one message transmitted.

Is there a way to tell the Pico to ignore the ACK bit? Is there something blatantly wrong with my setup?

KevinOConnor commented 1 month ago

The screenshot you provided does seem to indicate the message was successfully transmitted. (The received zero bit, that was not transmitted, after the crc information, is what an ack looks like.) So, I'm not sure what you are reporting.

Make sure you are on the latest version of the can2040 code (as there were fixes in this area in earlier versions).

You could try sending several messages with different content. You could also try disconnecting all other nodes on the CANbus to verify the can2040 node continuously transmits when no other nodes are present.

You may also want to try with known working software (Klipper and linux can-utils): https://github.com/KevinOConnor/can2040/blob/master/docs/Tools.md#klipper

-Kevin

wrongbaud commented 3 weeks ago

Thanks for the reply!

I also noticed that the ACK was being transmitted, but I can't figure out why when using the code above, there is only one message being transmitted.

I've tried several messages with different content, and have seen the same behavior.

The behavior remains the same regardless of what nodes are on the network.

Is there something that I am supposed to be doing in the callback after transmitting?