zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.84k stars 6.6k forks source link

Cannot build CAN driver sample for anything except nucleo_l432kc and stm32f072b_disco #12052

Closed laperie closed 5 years ago

laperie commented 5 years ago

Describe the bug samples/drivers/CAN cannot be built for any other boards except for nucleo_l432kc and stm32f072b_disco If that is intended, then this probably needs to be mentioned in readme I verified the build fails for the following boards (supporting CAN bus):

To Reproduce Steps to reproduce the behavior:

  1. mkdir build; cd build
  2. cmake -DBOARD=board_xyz
  3. make
  4. See error

Expected behavior Not have error?

Impact Cannot try CAN on any boards except for these two.

alexanderwachter commented 5 years ago

This is because I have added the CAN device to the device tree only for those two boards. I didn't wanted to add support to other boards than I've tested. If someone owns one of this board, pleas test them and add the can device to the device tree.

laperie commented 5 years ago

@alexanderwachter, we have a few boards here -- can you please share any details on how to enable CAN device to these?
We can start for example with nucleo_l476rg:

I copied a dts section &can1 { pinctrl-0 = <&can_pins_a>; pinctrl-names = "default"; bus-speed = <250000>; status = "ok"; }; from a working nucleo_l432kc and now can build okay but CAN sample still reports CAN device not found. Please advise next steps

alexanderwachter commented 5 years ago

You also need to add the pin multiplexing for each board. This is done in pinmux.c

ifdef CONFIG_CAN_1

{STM32_PIN_PB8, STM32F0_PINMUX_FUNC_PB8_CAN_RX},
{STM32_PIN_PB9, STM32F0_PINMUX_FUNC_PB9_CAN_TX},

endif / CONFIG_CAN_1 /

Use pins that are easy to connect from outside because you need some additional hardware, the so called CAN transceiver. can_transr

At the first and last node on the bus you also need a termination resistor of 120 Ohm.

Check if something like this (stm32f072.dtsi): can1: can@40006400 { compatible = "st,stm32-can";

address-cells = <1>;

        #size-cells = <0>;
        reg = <0x40006400 0x400>;
        interrupts = <30 0>;
        clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>;
        status = "disabled";
        label = "CAN_1";
        bus-speed = <250000>;
        sjw = <1>;
        prop_seg_phase_seg1 = <5>;
        phase_seg2 = <6>;
    };

is present for your device family. If not, add it and adapt the registers, and clock. Then Enable the driver from menuconfig -> Device Drivers -> CAN Drivers

alexanderwachter commented 5 years ago

If you don't want to connect two boards, you can also use loopback mode. But you have to connect the CAN transceiver because the CAN Tx pin is high in idle mode. If this pin is low for a certain time while initializing the device, it will fail.

laperie commented 5 years ago

@alexanderwachter, thanks! Where do I get the board-specific information on registers and clocks? For example, for said nucleo_l476rg.

alexanderwachter commented 5 years ago

@laperie since the nucleo_l476rg is based on a stm32L4* the can1: can@40006400 {...} is already defined in the stm32l4.dtsi . As far as I know, all stm32L4 cpu's have a can interface so I added it to the top layer dts include file. Registers an clocks are not a property of the board but the CPU so you will find that information in the CPU's reference manual.

alexanderwachter commented 5 years ago

For the NUCLEO-L476RG board you can use PA11 as CAN1_RX and PA12 as CAN1_TX. Add following lines to the pinmux.c of your board:

ifdef CONFIG_CAN_1

{STM32_PIN_PA11, STM32L4X_PINMUX_FUNC_PA11_CAN_RX},
{STM32_PIN_PA12, STM32L4X_PINMUX_FUNC_PA12_CAN_TX},

endif / CONFIG_CAN_1 /

erwango commented 5 years ago

@laperie

I verified the build fails for the following boards (supporting CAN bus)

Can I ask how did you compute this list? I had a quick check on few of those and I couldn't find code enabling CAN for these boards.

laperie commented 5 years ago

@erwango I tried to build CAN sample for all boards supporting CAN hardware-wise. I couldn't find any specific document limiting an applicability of stm32 CAN driver to stm32f072b_disco,. @alexanderwachter , is it described anywhere?

alexanderwachter commented 5 years ago

In principle it is not limited to any board but you need additional hardware (transceiver) . As far as I know there is no board that has this kind of hardware by default. If the MPU has a CAN module ob board you can use it but you need the transceiver.

erwango commented 5 years ago

@laperie, ok. So indeed HW supported does not mean feature support enabled. If you look in details, you'll see that boards in general support wide variety of HW, enabling all of this is a significant amount of work. It's actually done step by step.

Usually, in board docs, you'll find "Supported Features" section which should document features enabled and validated for a board. Besides, it should be reflected in board yaml file ("supported" section), and this actually should be the reference. Looking in detail, it seems this is not up to date. I'll fix that.

alexanderwachter commented 5 years ago

@erwango the problem is that none of this boards support CAN by default. Without the additional CAN transceiver the device can't be initialized. Maybe that fact should be stated somehow.

laperie commented 5 years ago

Okay, I guess that at this stage the best thing would be to just update the documentation. Shall we add CAN as supported feature to nucleo_l432kc and stm32f072b_disco ?

erwango commented 5 years ago

@laperie: sure, I'll do it by today

laperie commented 5 years ago

Thank you @erwango . Please resolve this issue with these changes.

laperie commented 5 years ago

I can confirm that event without CAN transceiver (which I am hoping to get right after NY) CAN sample works on STM32F072B_disco