candle-usb / candleLight_fw

gs_usb compatible firmware for candleLight, cantact and canable
Other
603 stars 279 forks source link

Beginning work on porting to STM32G4x for FD CAN #21

Open daniel-santos opened 4 years ago

daniel-santos commented 4 years ago

I'm currently using candleLight in a commercial project (that will hopefully release by next year) but I'm already looking at CAN FD since vehicles will be using that soon (or some now I guess). Has anybody looked at doing a similar project with the STM32G series that does CAN FD?

Interestingly the STM32G47x µCs have 3 CAN FD controllers. That might pair up nicely with the Microchip dual can transceiver as a dual CAN FD to USB interface.

daniel-santos commented 4 years ago

Hello all. I'm beginning work on porting candleLight to FD CAN using an STM32G431x and I would like to coordinate changes so that hopefully we can agree upon all of them and merge them back in. I would like to radically change the Makefile's structure and would very much appreciate your feedback and opinion.

First of all, most users will not be interested in compiling for every board. As such, I would propose it to be reasonable to convert to a configuring type of make (like autotools) that would be less convenient for the maintainer, but provide great benefits to the design and implementation of support for other hardware, features, etc.. I'm thinking of the same code base supporting both existing devices and newer FD CAN devices -- I'm not promising that's a sane idea yet, but it feel like the right way to go at the moment.

Autotools really shines at configuring a software build on varying development environments, and as far as I'm aware, most people will just be using ARM's toolchain (I haven't gotten the build to work using a toolchain built in Gentoo using crossdev, for example). So perhaps the justification for using autotools (or similar) is not as strongly supported as with most software, but it can certainly clean the build up quite a bit -- especially as complexity grows.

Secondly, I have this vision for a µC-based set of USB bridge devices that I've wanted to crowd-source for a long time, but just haven't had time given my current job and health. The requirements for my current project will be to add a CDC ACM USB interface -- I'm hoping my company will let us open source that portion, I haven't breached the topic yet, but since we're starting from candleLight I'll get to release the sources for our changes to that. :)

I'm also wondering about some type of support for STM32Cube. I don't know STM hardware well enough yet to understand all of the ins and outs, but it seems like a handy way to quickly verify a setup (pins and peripherals) and spit out the basic code to init hardware and such. Perhaps using STM32Cube to help port candleLight is best left as a manual process though.

daniel-santos commented 4 years ago

autoconf isn't working out because the default AC_PROG_CC expects to build an executable and when it only has a .o file it thinks it can't make executable files -- and it's correct, it's just that we don't need them.

None the less, I've modified the Makefile so it can pull in optionally headers and sources from an external STM32 firmware library instead of using the copies in-tree and I have it building against ST's v1.10.1 library for F0xx series. My next step is trying to get it to build for G4xx.

normaldotcom commented 4 years ago

Hey Daniel! Any luck with can-fd in candlelight so far? I would love to help out--drop me an email at ethanzonca@gmail.com.

daniel-santos commented 4 years ago

Hi Ethan! Yes, I finally have working firmware. It's not finished, or refined. Also, I'm only testing classic CAN thus far, but using the STM32G431RBx which is CAN FD capable. Getting FD to work is a requirement of the hardware in the (near to medium term) future, but not immediate and I'm suddenly in a time crunch with this project.

I'm pretty sure I'm going to end up forking candleLight, which I really don't prefer to do. The main problem I had was that nothing I did starting from the original project resulted in any CAN traffic in or out (sniffing the wire as well). I spend 8 LONG DAYS stuck on this (and billing) which is really hurt my gego (i.e., geek ego). This despite being able to get ST's FDCAN demo project to work separately, but not once I inserted the code into candleLight.

I finally created a new project in STM32CubeMX and imported the guts of candleLight and got it to work. However, my project requires a minimum of 2Mbps and the original USB protocol / driver wasn't cutting it, so I've modified the driver as well. I'll need to evaluate if the driver should be forked or if a meaningful change set can be made so that this new device can work side-by-side with other devices in the same driver. Obviously, when going to CAN FD the driver will need to be modified anyway. The main change I made was putting more than one CAN frame in a bulk IN URBs and compressing them by bit packing and omitting unused data bytes. The Bulk IN URB on full-speed USB is limited to 64-bytes anyway. -- This whole thing doesn't actually work correctly yet.

The code is currently encumbered by ST's "ultimate freedom license", and if you're familiar with propaganda, it should be immediately obvious that they mean the opposite (i.e., think "Clear Skies Act" or "USA Patriot Act"). TBH, my preference would be to be able to create an STM32CubeMX source code template set to solve this license encumberment while preserving the round-trip engineering that it provides and that makes porting to other ST chips so much easier. I don't think I'm going to get paid to do that part though. :)

Another thing that doesn't work is using -flto. I believe this is due to a flaw in ST's library somewhere (optimization barriers and such). I'm currently using their HAL, which is expensive without LTO (which is able to remove most of the "fluff"). That's also a low priority item though.

I've also directly pulling in some slightly modified headers from the Linux kernel, thus making it GPL2 encumbered:

asm/byteorder.h
linux/usb/ch9.h
linux/types.h
linux/can/error.h
linux/can.h

Anyway, I'll try to get the sources online somewhere this week. In the end, if it can be merged back into candleLight it would be nice, but I'm calling this one "candy" for now.

Cheers

BTW, I'm using a nucleo-64 g431rb for development. The chip is super cheap -- $2.75-ish.

jhofstee commented 4 years ago

@daniel-santos not sure you are still working on this but trying to put 2 x 10mbit/s + overhead and poll delays through a 12Mbit/s full speed USB might not be a great idea. Isn't there a high speed option?

daniel-santos commented 4 years ago

@jhofstee I don't need 2 x 10Mbps for my purposes, I just need 1x 2Mbps. ST has µCs with high-speed USB, but they are quite a bit more expensive. The cheapest (STM32H750VB) is $3.378 at qty 10k compared to $2.012 for the STM32G431C6T. Actually, I'm not really sure that device was available when I started this project.

Anyway, you don't want for the poll the device for frames to the host, you send several bulk URB requests in advance -- the driver currently keeps 16 or so outstanding -- and then the device responds when it's ready. The overhead has been the issue for me, which is why I'm now packing multiple frames into a single bulk IN URB -- something like this should have been done in the first place because the overhead can easily be consistently larger than the actual CAN data.

However, due to being full-speed USB, bulk URBs are limited to 64 bytes in size so I can only pack 8 CAN frames in a single bulk URB at most. Hopefully the firmware won't end up being too difficult to port to one of the high-speed USB µCs -- I think these are all in the STM32F7xx and STM32H7xx lines and they have USB OTG, cortex M7 cores and are all at least 480MHz.

Linjieqiang commented 4 years ago

@daniel-santos Any news?

daniel-santos commented 4 years ago

@Linjieqiang Hopefullly in a few days, maybe early next week. If you want to jump in quickly, you can order some NUCLEO-G474RE boards ($12 from Mouser, $16 each from Digikey) -- make sure you get the 64-pin version and not the 32-pin (like I did)! You'll also need a USB connector, I like Adifruit's USB Mini-B Breakout Board. Here's the board's schematic and pinouts: image

When I'm further along I'll post better instructions, but here they are in short.

  1. Change option bytes using the STM32CubeProgrammer gui tool (only runs on Windows last I tried) or your favorite tool. Clear nSWBOOT0 and I think set nBOOT0 and ignore nBOOT1.
  2. Hook USB up to your breadboard or breakout: PA11 is D- (CN10, pin 14) and PA12 is D+ (CN10, pin 12)
  3. Hook up CAN to your transceiver (I'm using an MCP2562FD): PB9 is FDCAN_TX (CN5, pin 9) and PB8-BOOT0 is FDCAN_RX (JP7, pin 1) -- the later being the reason we have to disable nSWBOOT0, else the state of the CAN bus would decide rather we boot system or main memory! (I think the 100 pin packages have another option on where to pin out FDCAN.)

This code is available at http://git.gsat.us/dansan/candy but it's currently SUPER, HORRIBLE, UGLY, UGLY! I'll clean it up soon enough. :)

daniel-santos commented 4 years ago

I should add that I've made some major departures from the original design. Almost everything is interrupt-driven now -- these are changes I would like to backport into candleLight!

I'm currently making heavy use of ST's HAL, but some of that is ugly and written in a way that it may be easy to maintain with less skill, but unnecessarily prevents the C compiler from making MANY optimizations! For instance, I replaced their HAL_FDCAN_IRQHandler with my fdcan_isr for such reasons. (In this case, all the volatile reads cannot be folded, forcing a gazillion reads to I/O registers). I'm hoping I can end up with a compromise that leaves it easier to port (and maybe even back port to STM32Fxxx), but doesn't waste too much on bulky HAL functions.

At least it's correct (the most important part). I was forced to use the directories Src and Inc instead of world-wide standard of src and include due to the STM32CubeMX tool (I hope I can fix that in freemarker).

normaldotcom commented 4 years ago

If any of you guys are interested, I've designed a fork of the CANable Pro with the STM32G431 processor paired with an isolated CANFD transceiver. I've got boards in-hand for quantity 10, just have to paste, place, and reflow. If you would like one, let me know! I'm definitely willing to give a few away.

Hoping to leverage/help out with the firmware you've been working on @daniel-santos alongside some abomination of slcan that I might come up with which incorporates CAN-FD frames.

daniel-santos commented 4 years ago

@normaldotcom wow, that was fast! In case I haven't mentioned it, the low speed external oscillator (LSE) isn't necessary, but the high-speed external oscillator (HSE) is in order to meet the +/- 0.5% tolerance for the FDCAN speed (I think it was 0.5%). I don't think the oscillator value matters much because the PLL unit on these things is just amazing! (Well, that's coming from somebody who just learned what a phase-locked loop is. :)

Also, it's helpful if you have SWO (PB3) out to your programming test pads. I'm using it via a simple FTDI serial interface at 500Kbps to help with debugging.

So the only code involved in the license conflict (between ST's "Ultimate Freedom" and GPL2) is the USB middleware code. This was only introduced because I pulled in some Linux headers (GPL2), so I'll either need to write an unencumbered USB stack (or find an existing one) or get rid of the Linux headers. I really don't want to do either, but I'm more inclined towards writing a new USB stack -- we'll see. I really don't like defining the descriptors with char arrays, that's a horrible thing to do and in one case the STM32CubeMX tool screws up the definition and breaks it.

Another thing I'm looking forward to at some point is hardware filters. I moaned on LKML about netlink not supporting it and somebody jumped up and added it! So now the driver just needs to support it and we can set hardware filters with the "ip link" command. It's kind of sad, I really should have helped and I contributed very little to the effort. :(

jhofstee commented 4 years ago

Hello Daniel,

On 11/1/19 11:12 AM, Daniel Santos wrote:

@normaldotcom https://github.com/normaldotcom wow, that was fast! In case I haven't mentioned it, the low speed external oscillator (LSE) isn't necessary, but the high-speed external oscillator (HSE) is in order to meet the +/- 0.5% tolerance for the FDCAN speed (I think it was 0.5%). I don't think the oscillator value matters much because the PLL unit on these things is just amazing! (Well, that's coming from somebody who just learned what a phase-locked loop is. :)

Also, it's helpful if you have SWO (PB3) out to your programming test pads. I'm using it via a simple FTDI serial interface at 500Kbps to help with debugging.

So the only code involved in the license conflict (between ST's "Ultimate Freedom" and GPL2) is the USB middleware code. This was only introduced because I pulled in some Linux headers (GPL2), so I'll either need to write an unencumbered USB stack (or find an existing one) or get rid of the Linux headers. I really don't want to do either, but I'm more inclined towards writing a new USB stack -- we'll see. I really don't like defining the descriptors with char arrays, that's a horrible thing to do and in one case the STM32CubeMX tool screws up the definition and breaks it.

It depends a bit of which header you are using, but the userland api ones should be subject to an exception I think. See [1]

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/LICENSES/exceptions/Linux-syscall-note

Regards,

Jeroen

brandonros commented 4 years ago

I've designed a fork of the CANable Pro with the STM32G431 processor paired with an isolated CANFD transceiver.

What are the benefits of this versus regular CANAble pro?

I think a big selling feature is DB9 serial port instead of having to deal with spliced OBD-II cable.

Linjieqiang commented 4 years ago

@normaldotcom wow, that was fast! In case I haven't mentioned it, the low speed external oscillator (LSE) isn't necessary, but the high-speed external oscillator (HSE) is in order to meet the +/- 0.5% tolerance for the FDCAN speed (I think it was 0.5%). I don't think the oscillator value matters much because the PLL unit on these things is just amazing! (Well, that's coming from somebody who just learned what a phase-locked loop is. :)

Also, it's helpful if you have SWO (PB3) out to your programming test pads. I'm using it via a simple FTDI serial interface at 500Kbps to help with debugging.

So the only code involved in the license conflict (between ST's "Ultimate Freedom" and GPL2) is the USB middleware code. This was only introduced because I pulled in some Linux headers (GPL2), so I'll either need to write an unencumbered USB stack (or find an existing one) or get rid of the Linux headers. I really don't want to do either, but I'm more inclined towards writing a new USB stack -- we'll see. I really don't like defining the descriptors with char arrays, that's a horrible thing to do and in one case the STM32CubeMX tool screws up the definition and breaks it.

Another thing I'm looking forward to at some point is hardware filters. I moaned on LKML about netlink not supporting it and somebody jumped up and added it! So now the driver just needs to support it and we can set hardware filters with the "ip link" command. It's kind of sad, I really should have helped and I contributed very little to the effort. :(

Why not use the internal clock?

adaasch commented 2 years ago

Any news regarding this? I would be highly interested. The link to the code is not available (anymore?).

KhazAkar commented 1 year ago

@daniel-santos so how does it go?

marckleinebudde commented 1 year ago

The candlelight firmware supports the STM32F4VE Dev Board, see https://github.com/candle-usb/candleLight_fw/blob/537c0860c398e7180263cf98e42ba5e3d6a99ea3/include/config.h#L265

linuxguy123 commented 4 months ago

Is the STM32G431 now supported ?