-
Notifications
You must be signed in to change notification settings - Fork 2k
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
tests/candev: add mcp2515 + driver/mcp2515: add driver #13624
Conversation
@JannesVolkens Do you maybe have the hardware to test this? |
308d2f6
to
e44bc99
Compare
@wosym I do. |
e44bc99
to
a801a36
Compare
@wosym I tried to test this PR, but unfortunately I am unable to receive data. I’m using two mcp2515’s and also two nucleo-f207zg’s. I connected the mcp2515's to the boards accordingly and the two lines CANH and CANL are connected to a bus, which is terminated by resistors. Also I adapted the pin configuration for CS and INT (here I chose a empty pin on my board) in the makefile, even though I don’t know what to do with RESET. Furthermore I commented out line 26 in the makefile
(different cpu) because I don’t know which module to use here. Everything else stayed the same. The test is giving me send confirmations although I'm not getting any signals on my logic analyzer. I probably overlooked something here. Can you give me some more information on how to configure the device to make it work? Or is there maybe something wrong with my setup? |
Thanks for taking the time to test @JannesVolkens!
What happens if you send multiple (> 4) messages in a row? Do you get an error? Usually, if the driver fails to transmit the message, it will keep it stored in mailboxes. After all mailboxes are filled, it should print this on screen.
I'm assuming you're also using a CAN-transceiver (such as the MCP2551), right? (I noticed that I didn't really make this clear in the testing-instructions of this PR. I'll fix that tomorrow)
It is also mapped to a GPIO pin. You can set it in the Makefile, just like you did with CS and INT.
I have no experience with external interrupts on an STM32 yet, but I can only imagine that it would also need the interrupts to be enabled. A quick scan through the datasheet tells me a few bits should be set in the NVIC.
It's not unlikely. Getting everything to work properly took me countless of hours of bug-hunting, and very often it turned out to be a hardware problem :) (not setting the terminating resistor is a classic, but you already mentioned that you did set it, so you're safe on this one ;) ) |
b71c608
to
abaf8e6
Compare
@wosym Sorry for the late response!
In this screenshot the MCP2515 was initialized and I tried sending four messages to the bus. This second screenshot was taken not long after, but the printouts looked a bit different compared to the first one. Both of the screenshots were taken with all debug messages turned on.
Yes I'm using a MPC2515 CAN module with a TJA1050 CAN-transceiver just like this one: https://www.makerfabs.com/can-module-mcp2515.html
I figured that the initialization of the INT pin is handled in: During this process I had a logic analyzer connected and noticed that the MCP2515 kept trying to send the test message defined in Then I tried receiving messages over the MCP2515. I checked the reference manual for the MCP2515 and tried changing the mode of operation to the listen-only mode so that theoretically every single message is received (just to be sure). But unfortunately I received none of the messages I sent to the bus. I really want to get it running but sadly I am not able to. Do you maybe have some more ideas? |
@JannesVolkens can you share the changes that you applied to the Makefile please |
Usually this type of behaviour is because of a hardware problem: Faulty wiring, missing terminating resistor, OR interrupts not being received/handled properly.
Mhmmm, this one looks strange. Is it possible that you reset the microcontroller, but not the MCP2515? Maybe some data was still in the mcp when the controller tried sending again?
I personally don't have any experience with this transceiver, but by the looks of it it works pretty much the same as the MCP2551. 120 ohm on both sides, close enough to the transceiver pins should work.
Correct. This function enables the interrupts. However, for AVR I needed an extra line in the Makefile. As far as I could tell, no such line is needed for STM32, but I can be wrong. Maybe some RIOT-STM32 expert can shed light on this :)
This really sounds like an issue with the interrupts. I think SPI communication between controller and MCP2515 works just fine, but once the mcp has finished sending the CAN-data, it needs to notify the controller of this so that it can clear its mailboxes. This is done by means of an interrupt. I have tried to clone your setup on a nucleo-board, and have not been able to send myself either. So indeed... Something still needs to be done for STM, but for now I don't really have an idea what that is. I'll try to do some more experimenting in the coming days/weeks, but I can't say yet how much time I will have to invest in this. Corona is wreaking some havoc in my professional life :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wosym thanks for your contribution and @JannesVolkens thanks for the testing efforts. This is just a very early review. Once we sorted out the issues with other platforms than AVRs, we can go into more detail, but some parts can already be cleaned up.
@wosym I cannot access the reset pin on the board that I use, because it is directly connected to VCC. Is the reset needed for this driver to work? And if yes does the |
@JannesVolkens I think that's the way I did it as well. If you look in the Makefile, there's a line But yes, I think a reset is required for the driver to work. |
The mcp2515 breakout board does not expose the reset pin. Instead, the pin is wired to Vcc on the PCB |
Aha! I didn't know that. I use discrete components myself. That complicates things a bit :D However, I've been having another look at the code (the reset function in particular) and it seems like this reset-pin is never even used... The resetting happens in a different way, over SPI. Maybe it'll work without defining this reset-pin? Because the way I currently see it (only by looking at the diff, don't have my laptop or hardware near me) I think there's a fair chance that it will work just fine. Can you test this, @JannesVolkens ? (I'll try testing it myself if I get the chance tomorrow) |
The code compiles just fine without the definition of the reset pin. But I still get the same behaviour as described above. |
Yep, you are right @PeterKietzmann ! It seems like there are two options: either connect the rst-pin to a GPIO and set it in the Makefile, or connect the reset of the mcp to the reset of the controller. I think both will work. |
We will definitely try to modify our breakout board to make the reset pin available in order to test this PR. But we should not forget about option number three: explore an alternative reset mechanism so we don't rely on the reset pin. Our MCP2515 breakout board is a common piece of hardware which should be working out of the box with this driver . |
I have ordered one of those breakout-boards myself a while ago, and expect it to arrive in a few days now. I'll test the driver once I have it. If the breakoutboard really does not work out of the box, then it probably will need the RESET-byte written to it over SPI. This is what the |
@JannesVolkens did you give it a try to replace the calls to |
88bd025
to
4154a8d
Compare
@wosym only https://github.com/RIOT-OS/RIOT/pull/13624/files#r495732584 missing from my side and we can move forward with this one. |
8b8fd14
to
f94c3e4
Compare
Since I think we're nearing the finish now, I already ran those tests again: Sending a standard frame:
Receiving a standard frame:
Sending an extended frame:
Receiving an extended frame:
(of course the last line of each code-box is not output from RIOT, but from candump running on Linux. It was sniffing the canbus during the test to verify all data being sent and received.) |
This driver implements the candev interface
f94c3e4
to
e1ebd28
Compare
I rebased on master to resolve the merge conflicts introduced in #14909 . Feel free to share your opinion on this though if you think there's another approach that works better without making it overcomplicated to the user! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to share your opinion on this though if you think there's another approach that works better without making it overcomplicated to the user!
Lets not forget that this is a test application! Which means it should build for as many ARCH as possible,
the mcp2515
can be built for all platforms while periph_can
can only be built for platforms with that module which are so far native
and some stm32
boards. So that makes me think that maybe the best thing is actually to have two separate applications tests/periph_can
and tests/driver_mcp2515
, maybe configuration and code could be share between both. What do you think @wosym?
tests/candev/README.md
Outdated
By default the mcp2515 driver is used. Change this line to your desired driver. | ||
If the line is removed, the application will default to native-can. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not valid anymore.
tests/candev/README.md
Outdated
@@ -5,6 +5,10 @@ | |||
This application is a test for using the candev abstraction directly. | |||
Use this if you want to use a single CAN driver and thus don't need the CAN-DLL layer. | |||
|
|||
Include the module for your desired driver in the Makefile. The application will automatically adapt its initialization procedure to the selected driver. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include the module for your desired driver in the Makefile. The application will automatically adapt its initialization procedure to the selected driver. | |
Include the module for your desired driver in the Makefile. The application will automatically | |
adapt its initialization procedure to the selected driver. |
tests/candev/Makefile
Outdated
|
||
# define the CAN driver you want to use here | ||
CAN_DRIVER ?= CAN_EXT | ||
CAN_DRIVER ?= NATIVE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CAN_DRIVER ?= NATIVE | |
CAN_DRIVER ?= PERIPH_CAN |
tests/candev/Makefile
Outdated
ifeq ($(CAN_DRIVER), NATIVE) | ||
|
||
FEATURES_OPTIONAL += periph_can | ||
|
||
else ifeq ($(CAN_DRIVER), MCP2515) | ||
USEMODULE += mcp2515 | ||
|
||
else ifeq ($(CAN_DRIVER), CAN_ALT) | ||
# other can modules can be defined here | ||
|
||
endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ifeq ($(CAN_DRIVER), NATIVE) | |
FEATURES_OPTIONAL += periph_can | |
else ifeq ($(CAN_DRIVER), MCP2515) | |
USEMODULE += mcp2515 | |
else ifeq ($(CAN_DRIVER), CAN_ALT) | |
# other can modules can be defined here | |
endif | |
ifeq ($(CAN_DRIVER), PERIPH_CAN) | |
FEATURES_REQUIRED += periph_can | |
else ifeq ($(CAN_DRIVER), MCP2515) | |
USEMODULE += mcp2515 | |
else ifeq ($(CAN_DRIVER), CAN_ALT) | |
# other can modules can be defined here | |
endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would match better the current status.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I applied your suggestion, with the addition of an additional check on the used board. If the board is native, it will always default to periph_can, and not allow a different driver.
Why? Well... because before it was pretty clear that you had to use can_native on the native board. With the recent changes in the can structure it has (imo) become a little bit confusing that you have to use can_periph now for native.
So for users who are unfamiliar with can in RIOT, I think forcing this option on them will save them a lot of headaches I think :)
When I read your comment this morning I was very opposed to your suggestion. The original idea of this test application was to have a demo of the candev abstraction in RIOT that could be used with any of the available can drivers. Similar to But... two hours later I read you comment again, and I must admit... it would make sense in a way to split the application, and instead of making a single test for candev, we could indeed make a test for each of the can-devices (in this case there's only two: mcp2515 and can_periph, since apparently can_native is now deprecated and is also included in can_periph) that both communicate with their drivers through the candev abstraction. This would add quite a bit of duplicate code, but then the tests would be more in line with the other tests in RIOT. I'll try to split them as per your suggestion somewhere this week. I postpone resolving those last comments about the doc and Makefile for now, because those will need significant rewrites after the split anyways. |
@wosym since this PR has been dragging out for a while we could keep it somehow as is and split up as a future step? |
Sure, I'm okay with that. The extra benefit of merging this one first, and then splitting in a separate PR is that everyone involved still has time to share their opinion about it. Because I can imagine some will be opposed to it. I'll try to address those last comments this evening. |
Let me know what you prefer! But if we keep it somehow at is we would still need it the application to be in a way where Option A
It wouldn't have the configurability you want but it would allow us to get this PR in. The other option is have Option B
Either of the two options is fine with me so pick which one you prefer (whats important for me is that the And then as a second stage we could think of something similar to what is done for |
@fjmolinas This is again the same chicken-and-egg question as before: what is it that this test is testing? The drivers? Or the candev abstraction? After the split, we can repurpose the test(s) and place the focus on the drivers, instead of the candev abstraction. I hope this is ok for you. (Do note that we're essentially reverting the changes of the previous PR by doing this :) ) |
e1ebd28
to
3a53f9b
Compare
3a53f9b
to
4c2bc23
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK, @PeterKietzmann did the initial review of the code, I took over with the last details and @wosym provided test output for the most recent changes. Lets wait for murdock!
@wosym hope you don't mind I pushed a change fixing a dependency issue for native, it was the only build failure, so I think this murdock run should be the last one... we will see in ~30min |
GO! |
Thanks for taking over this PR @wosym and for sticking through to the end, I'm sorry this took so long... |
It was my pleasure @fjmolinas ! |
Contribution description
Testing procedure
send
command will send a CAN message to can0. It should become visible in candump. Optionally you can pass some bytes (in decimal notation) as arguments (e.g.send 12 34 56
). If no arguments are supplied, three default bytes will be sent.cansend can0 001#AABB
) or with cangen (e.g.cangen can0 -v -n 1
).receive
. (an optional argument n can be passed to receive multiple can-messages). If there are no CAN-messages in the buffer whenreceive
is called, it will block until a message is received.Issues/PRs references
replaces #6276