Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: can: stm32fdcan #31061

Merged
merged 7 commits into from
May 7, 2021

Conversation

alexanderwachter
Copy link
Member

@alexanderwachter alexanderwachter commented Dec 31, 2020

STM32FDCAN implementation.
This PR implements a generic Bosch M_CAN driver that can be specialized for dedicated SoCs, such as FDCAN (STmicro), Microchip SAM, and NXP.
The specialization for FDCAN (STmicro) is included in this PR.
Tests are added to test the FD mode.

@legoabram has a prototype prototype specialization for SAM0

@alexanderwachter alexanderwachter added platform: STM32 ST Micro STM32 DNM This PR should not be merged (Do Not Merge) area: CAN labels Dec 31, 2020
@github-actions github-actions bot added area: API Changes to public APIs area: Boards area: Devicetree area: Devicetree Binding PR modifies or adds a Device Tree binding labels Dec 31, 2020
@alexanderwachter alexanderwachter marked this pull request as draft December 31, 2020 12:52
Copy link
Member

@martinjaeger martinjaeger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @alexanderwachter for all your effort. I have tested the driver in a classic CAN network already and can confirm that it works very well.

Still need to go through the can_mcan.c, but here are some small comments already.

drivers/can/Kconfig.mcan Show resolved Hide resolved
boards/arm/nucleo_g474re/nucleo_g474re.dts Outdated Show resolved Hide resolved
drivers/can/Kconfig.stm32fd Outdated Show resolved Hide resolved
include/drivers/can.h Outdated Show resolved Hide resolved
dts/arm/st/g4/stm32g4.dtsi Outdated Show resolved Hide resolved
drivers/can/can_mcan_int.h Outdated Show resolved Hide resolved
@github-actions github-actions bot added the area: Tests Issues related to a particular existing or missing test label Jan 17, 2021
drivers/can/can_mcan.c Outdated Show resolved Hide resolved
Copy link
Collaborator

@KozhinovAlexander KozhinovAlexander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for this PR. I would also test with it with my stm32h7 soon and go through ToDo's.

drivers/can/can_mcan.c Show resolved Hide resolved
drivers/can/can_mcan.c Outdated Show resolved Hide resolved
drivers/can/can_mcan.c Outdated Show resolved Hide resolved
drivers/can/can_mcan.c Show resolved Hide resolved
drivers/can/can_mcan_int.h Outdated Show resolved Hide resolved
drivers/can/can_mcan_int.h Outdated Show resolved Hide resolved
drivers/can/can_mcan_int.h Outdated Show resolved Hide resolved
drivers/can/can_mcan_int.h Outdated Show resolved Hide resolved
drivers/can/can_mcan_int.h Outdated Show resolved Hide resolved
drivers/can/can_mcan_int.h Outdated Show resolved Hide resolved
@@ -302,6 +302,54 @@
label = "SPI_3";
};

can {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This leads to a warning during DTS generation:

board_name.dts.pre.tmp:281.7-324.5: Warning (simple_bus_reg): /soc/can: missing or empty reg/ranges property

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbolivar any suggestions on how we can improve the DT bindings?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the top-level node could be set to the general CANFD configuration register?

Suggested change
can {
can: can@40006500 {

Copy link
Member

@erwango erwango May 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It possibly misses a reg = <0>;

@alexanderwachter alexanderwachter force-pushed the can_mcan_stm branch 3 times, most recently from 107a72f to ecc1e3b Compare January 30, 2021 16:00
@alexanderwachter alexanderwachter force-pushed the can_mcan_stm branch 3 times, most recently from b84aa20 to efdebda Compare January 31, 2021 09:03
@alexanderwachter alexanderwachter marked this pull request as ready for review January 31, 2021 09:04
@alexanderwachter alexanderwachter removed the DNM This PR should not be merged (Do Not Merge) label Jan 31, 2021
@alexanderwachter alexanderwachter added this to the v2.6.0 milestone Jan 31, 2021
@KozhinovAlexander
Copy link
Collaborator

KozhinovAlexander commented Mar 20, 2021

Exactly. Its for the newer series with FDCAN (M_CAN), like the stm32g4, g0 and H7

In my opinion it is to early to speak about h7. I've tested it on h723 and it needs some changes due to different registers structure. I'll prepare driver update as soon as your development of this branch will be in master.

@raul-klg
Copy link
Contributor

Hi! Thanks for your work on this branch.

I think I found a problem running the tests/drivers/can/canfd/ example. I hope this is the right place to discuss this, otherwise please, accept my apologies and let me know where else I should address this information.

I have tried it merged with a slightly more recent zephyr (2235c71) on a nucleo_g0b1re board. For being able to use the driver on the g0b1 board I created a dts overlay for it (it is taken from your stm32g4 proposal):

/ {

    chosen {
                zephyr,can-primary = &can1;
    };

    soc {
                can {
                        compatible = "bosch,m-can-base";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        std-filter-elements = <28>;
                        ext-filter-elements = <8>;
                        rx-fifo0-elements = <3>;
                        rx-fifo1-elements = <3>;
                        rx-buffer-elements = <0>;
                        tx-buffer-elements = <3>;

                        can1: can@40006400 {
                                compatible = "st,stm32-fdcan";
                                #address-cells = <1>;
                                #size-cells = <0>;
                                reg = <0x40006400 0x400>, <0x4000A400 0x350>;
                                reg-names = "m_can", "message_ram";
                                interrupts = <21 0>, <22 0>;
                                interrupt-names = "LINE_0", "LINE_1";
                                status = "disabled";
                                label = "CAN_1";
                        };
                };

    };
};

&can1 {
        pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>;
        bus-speed = <125000>;
        sjw = <1>;
        sample-point = <875>;
        bus-speed-data = <1000000>;
        sjw-data = <1>;
        sample-point-data = <875>;
        status = "okay";
};

I then build the tests/drivers/can/canfd/ example and run it on the target with the following serial output:


*** Booting Zephyr OS build zephyr-v2.5.0-1509-gc0835a12fd30  ***
Running test suite canfd_driver
===================================================================
START - test_set_loopback
 PASS - test_set_loopback in 0.1 seconds
===================================================================
START - test_send_receive_std

    Assertion failed at WEST_TOPDIR/sample.git/canfd/src/main.c:117: check_msg: (msg1->id not equal to msg2->id)
ID does not match
 FAIL - test_send_receive_std in 0.13 seconds
===================================================================
START - test_send_receive_fd

Apparently it stalls on the test_send_receive_fd test and also there is an assertion on the previous test_send_receive_std This does not look to me like a successful test run.

For the sake of not cluttering the PR, I am omitting some debug information I could provide if it can be helpful to anyone.

@legoabram
Copy link
Collaborator

Something I noticed: CAN_MAX_DLC is hard coded to 8 even if FD mode is enabled with a higher CAN_MAX_DLEN. We will likely need an #if tree to make it reflect the max data length. That said, I think changing this define will cause issues since many modules support both classic and CAN-FD, and they will need to use the correct max dlc when checking data depending on the requested mode.

On that same note, a number of the existing drivers depend on this value while iterating through data bytes. Though it will likely work, it's not semantically correct since DLC is no longer explicitly the number of bytes with the introduction of CAN-FD.

@alexanderwachter
Copy link
Member Author

@raul-klg do the api tests pass?
I'll rerun the tests on my g4 when time permits.

@raul-klg
Copy link
Contributor

raul-klg commented Mar 31, 2021

Edit:
For the sake of completeness I found out the problem. I reused the register range from stm32g4 and I didn't noticed that the FDCAN message RAM in stm32g0b1 is 0x4000B400 (unlike the stm32g4 0x400A400).

-- Old post
@alexanderwachter Thanks for your reply.
Maybe I am not running the test properly. When I wrote #31061 (comment) I didn't enable the CAN_LOOPBACK and I also didn't connect the nucleo-g0b1re CAN bus to any other device or even bus termination.
I have build now the tests/drivers/can/api application with the same board overlay as detailed in #31061 (comment)

I have run three cases:

  1. default configuration. CONFIG_CAN_LOOPBACK is not set and CONFIG_CAN_STM32FD=y
    ->Test failed.
*** Booting Zephyr OS build zephyr-v2.5.0-1509-gc0835a12fd30  ***
Running test suite can_driver
===================================================================
START - test_set_loopback
 PASS - test_set_loopback in 0.1 seconds
===================================================================
START - test_send_and_forget
 PASS - test_send_and_forget in 0.1 seconds
===================================================================
START - test_filter_attach
 PASS - test_filter_attach in 0.1 seconds
===================================================================
START - test_receive_timeout
 PASS - test_receive_timeout in 0.101 seconds
===================================================================
START - test_send_callback

    Assertion failed at WEST_TOPDIR/scratch/can-api/src/main.c:609: test_send_callback: (ret not equal to 0)
Missing TX callback
 FAIL - test_send_callback in 0.113 seconds
===================================================================
START - test_send_receive_std
  1. Both CAN loopback and stm32fd driver enabled. CONFIG_CAN_LOOPBACK=y and CONFIG_CAN_STM32FD=y
    ->Test crashed
I: Init of CAN_LOOPBACK done
*** Booting Zephyr OS build zephyr-v2.5.0-1509-gc0835a12fd30  ***
Running test suite can_driver
===================================================================
START - test_set_loopback
 PASS - test_set_loopback in 0.1 seconds
===================================================================
START - test_send_and_forget
ASSERTION FAIL [z_spin_lock_valid(l)] @ WEST_TOPDIR/zephyr/include/spinlock.h:129
        Recursive spinlock 0x20000d14
E: r0/a1:  0x00000004  r1/a2:  0x00000081  r2/a3:  0x080095cd
E: r3/a4:  0x08005d81 r12/ip:  0x00000002 r14/lr:  0x08005d89
E:  xpsr:  0x21000000
E: Faulting instruction address (r15/pc): 0x0800769a
E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
E: Current thread: (nil) (unknown)
E: Halting system
  1. Only CAN loopback is enabled.can32fd driver is not: CONFIG_CAN_LOOPBACK=y, CONFIG_CAN_STM32FD is not set
    ->Test passed
I: Init of CAN_LOOPBACK done
*** Booting Zephyr OS build zephyr-v2.5.0-1509-gc0835a12fd30  ***
Running test suite can_driver
===================================================================
START - test_set_loopback
 PASS - test_set_loopback in 0.1 seconds
===================================================================
START - test_send_and_forget
 PASS - test_send_and_forget in 0.1 seconds
===================================================================
START - test_filter_attach
 PASS - test_filter_attach in 0.1 seconds
===================================================================
START - test_receive_timeout
 PASS - test_receive_timeout in 0.101 seconds
===================================================================
START - test_send_callback
 PASS - test_send_callback in 0.1 seconds
===================================================================
START - test_send_receive_std
 PASS - test_send_receive_std in 0.1 seconds
===================================================================
START - test_send_invalid_dlc
E: DLC of 9 exceeds maximum (8)
 PASS - test_send_invalid_dlc in 0.3 seconds
===================================================================
START - test_send_receive_ext
 PASS - test_send_receive_ext in 0.1 seconds
===================================================================
START - test_send_receive_std_masked
 PASS - test_send_receive_std_masked in 0.1 seconds
===================================================================
START - test_send_receive_ext_masked
 PASS - test_send_receive_ext_masked in 0.2 seconds
===================================================================
START - test_send_receive_buffer
 PASS - test_send_receive_buffer in 0.2 seconds
===================================================================
START - test_send_receive_wrong_id
 PASS - test_send_receive_wrong_id in 0.101 seconds
===================================================================
Test suite can_driver succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL

Please, let me know if I am doing anything wrong and how else could I help.


if (can->ir & CAN_MCAN_IR_ARA) {
can->ir = CAN_MCAN_IR_ARA;
LOG_ERR("Acces to reserved address");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a small typo:

Suggested change
LOG_ERR("Acces to reserved address");
LOG_ERR("Access to reserved address");

@flaminggoat
Copy link

I have been testing this CAN implementation on a ATSAME51 using the prototype specialisations mentioned in the OP.
I found their is no register state change isr so I had to add the following to can_sam0.c

static void can_sam0_register_state_change_isr(const struct device *dev,
						can_state_change_isr_t isr)
{
	const struct can_sam0_config *cfg = DEV_CFG(dev);
	const struct can_mcan_config *mcan_cfg = &cfg->mcan_cfg;
	struct can_mcan_reg *can = mcan_cfg->can;
	struct can_mcan_data *mcan_data = &DEV_DATA(dev)->mcan_data;
	struct can_mcan_msg_sram *msg_ram = cfg->msg_sram;

	mcan_data->state_change_isr = isr;

	if (isr == NULL) {
		can->ie &= ~CAN_MCAN_IE_EP;
	} else {
		can->ie |= CAN_MCAN_IE_EP;
	}
}

I also have found that the bitrate does not seem to be working as expected with this device tree I am getting a bitrate of 370k:

&can0 {
	status = "okay";
	bus-speed = <1000000>;
	sjw = <1>;
	sjw-data = <1>;
	sample-point-data = <875>;
	bus-speed-data = <1000000>;
};

@alexanderwachter alexanderwachter force-pushed the can_mcan_stm branch 2 times, most recently from b6e1e6a to 2c03505 Compare May 6, 2021 19:24
@alexanderwachter
Copy link
Member Author

alexanderwachter commented May 6, 2021

@raul-klg the test run on my stm32g474 sucessfully.
west build -b nucleo_g474re zephyr/tests/drivers/can/api and west build -b nucleo_g474re zephyr/tests/drivers/can/canfd

Copy link
Member

@martinjaeger martinjaeger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still finishing final can_mcan.c review, but here are some remarks already and one point that's not clear for me. Maybe you can comment already, @alexanderwachter?

drivers/can/Kconfig Outdated Show resolved Hide resolved
drivers/can/can_mcan.h Show resolved Hide resolved
drivers/can/can_mcan.c Show resolved Hide resolved
drivers/can/can_mcan.h Outdated Show resolved Hide resolved
drivers/can/can_mcan.c Outdated Show resolved Hide resolved
Copy link
Member

@martinjaeger martinjaeger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, only got above minor comments left.

I've been using this code in classic mode for a while already without any issues.

Thanks again for all the time you put into getting this done @alexanderwachter!

@raul-klg
Copy link
Contributor

raul-klg commented May 7, 2021

@raul-klg the test run on my stm32g474 sucessfully.
west build -b nucleo_g474re zephyr/tests/drivers/can/api and west build -b nucleo_g474re zephyr/tests/drivers/can/canfd

Thanks for the verification (and for your additional work). I'll retry when I'm able to. Maybe I need to review how I used the branch.

@galak galak dismissed KozhinovAlexander’s stale review May 7, 2021 13:26

I believe the issues have been resolved

Add Kconfig option to select appropriate can data field length

Signed-off-by: Alexander Wachter <[email protected]>
Implementation of the Bosch M_CAN IP driver.
This driver is just the base for a specific SoC implementation.

Signed-off-by: Alexander Wachter <[email protected]>
This driver is the SoC specific implementation of the
Bosch M_CAN IP.

Signed-off-by: Alexander Wachter <[email protected]>
This commit adds the CAN nodes to the STM32g4 SoCs.

Signed-off-by: Alexander Wachter <[email protected]>
This commit adds CAN support to the nucleo_g474re board.

Signed-off-by: Alexander Wachter <[email protected]>
This commit enhances the CAN API test. In the send_receive tests,
we are using two filters and frames at the same time to check
if the frame gets dispatched to the correct filter.

Signed-off-by: Alexander Wachter <[email protected]>
This commit adds tests for CAN-FD frames.

Signed-off-by: Alexander Wachter <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: API Changes to public APIs area: Boards area: CAN area: Devicetree Binding PR modifies or adds a Device Tree binding area: Devicetree area: Tests Issues related to a particular existing or missing test platform: STM32 ST Micro STM32
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants