CAN Bootloader
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
CAN Bootloader
As per title!
Couldn't find anything available so took the bootloader from Johannes and modified it towards a CAN version.
Build a GUI and the rest is history.
The CAN Interface used is a profi one from PEAK Systems.
https://www.peak-system.com/PCAN-USB-FD.365.0.html?&L=1
Didn't optimize yet for performance or size.
Currently 1 msg per mS (8bytes).
+/-8K/sec.
Update:
Currently the size needed is 0x2000 (8K) so we need to modify the LD files.
I'm thinking on a solution for that.
Couldn't find anything available so took the bootloader from Johannes and modified it towards a CAN version.
Build a GUI and the rest is history.
The CAN Interface used is a profi one from PEAK Systems.
https://www.peak-system.com/PCAN-USB-FD.365.0.html?&L=1
Didn't optimize yet for performance or size.
Currently 1 msg per mS (8bytes).
+/-8K/sec.
Update:
Currently the size needed is 0x2000 (8K) so we need to modify the LD files.
I'm thinking on a solution for that.
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
That's cool. Puzzled by the size though... Is it on github for further inspection?
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
No not yet i finished it last night.
Didn't optimize yet for size.
It uses both libraries cm3 and inv.
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
Ok i optimized it a bit i now reserve 8K in the loader.
This is my contribution to the community of OpenInverter.org.
Enjoy!
https://github.com/EV-Builder/CANBootloader
This is my contribution to the community of OpenInverter.org.
Enjoy!
https://github.com/EV-Builder/CANBootloader
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
Superb, thanks!
So I did a build from the cloned repo and the binary was only 7k. Then I enabled -Os (optimize for size) and binary shrunk to 5.5k. While I much sympathize with using libopeninv, in this size critical application it could be worthwhile to carve it out even more than you did already. I can make a few quick experiments tomorrow to see if it's worthwhile
So I did a build from the cloned repo and the binary was only 7k. Then I enabled -Os (optimize for size) and binary shrunk to 5.5k. While I much sympathize with using libopeninv, in this size critical application it could be worthwhile to carve it out even more than you did already. I can make a few quick experiments tomorrow to see if it's worthwhile
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
Ok cool! I'm building the Bootloader GUI app right now.
Current speed is like +/-12 seconds to program 27K but i have some tricks on my sleeve remaining.
I think its the host pc limiting the speed not the uController.
(each msg invokes the GUI currently and that's expensive).
(how big are our inverter / charger programs anyway?)
Another option might be to program it on the end of the memory and jump back and forth...
You can then have: and the Wifi bootloader (serial) and then jump to the CAN bootloader and then back to start address.
(maybe by simply checking in the first bootloader if the CAN bootloader is programmed?).
Current speed is like +/-12 seconds to program 27K but i have some tricks on my sleeve remaining.
I think its the host pc limiting the speed not the uController.
(each msg invokes the GUI currently and that's expensive).
(how big are our inverter / charger programs anyway?)
Another option might be to program it on the end of the memory and jump back and forth...
You can then have: and the Wifi bootloader (serial) and then jump to the CAN bootloader and then back to start address.
(maybe by simply checking in the first bootloader if the CAN bootloader is programmed?).
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
@johu; would you mind add to the bootloader (or paste it here) the code snippet to obtain the unique CPU id?
I need a 5 to 7byte ID.
I want to send it out on the first request for bootloader.
In the GUI we can then select which device we want to adress for the update and give normale names to the devices. (DHCP/DNS style).
This saves us from uploading to the wrong device in the network
I need a 5 to 7byte ID.
I want to send it out on the first request for bootloader.
In the GUI we can then select which device we want to adress for the update and give normale names to the devices. (DHCP/DNS style).
This saves us from uploading to the wrong device in the network
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
Yes, check here: https://github.com/jsphuebner/stm32-sin ... j.cpp#L177
Inverter firmware is currently about 45k
Inverter firmware is currently about 45k
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
txs!
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
Ok made the tool stand-alone.
Node selection works.
Node selection works.
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
That looks very nice! Would the GUI also run on Linux?
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
-
- Posts: 213
- Joined: Mon Jan 18, 2021 12:39 pm
- Location: Edinburgh, Scotland, UK
- Has thanked: 14 times
- Been thanked: 38 times
Re: CAN Bootloader
This thread seems to have stalled when it looked like it was heading towards a useful solution. Are there any updates?
I'm kicking the tyres around a solution for a Tesla Model 3 (i.e. TI C2000 MCU) CAN bootloader. It would seem to be best to try and combine efforts with a solution for STM32 systems.
I'm kicking the tyres around a solution for a Tesla Model 3 (i.e. TI C2000 MCU) CAN bootloader. It would seem to be best to try and combine efforts with a solution for STM32 systems.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
Will revisit this now because my BMS only has CAN communication. @EV_Builder: can you make that GUI available? That said I will probably make a python script anyway.
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
Now that im commercially active I can't share that for the obvious reasons...
Better use a python script; or add-on on savvycan i only use Windows so it won't run on linux. My HW support is limited to peak adapters too.
Most importantly: use the full 8bytes during transfer; and bit bang so ack each message. Flash burn and CRC takes most of the time anyway.
If you run into issues I can help.
You already have my canbus bootloader firmware right?
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
Ok, np.
Yes, I will reuse the protocol and restructure the firmware a bit to hopefully fit into 4k. Did you implement a reset command in firmware? Otherwise I think I'll just add an SDO index for it.
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
-
- Posts: 213
- Joined: Mon Jan 18, 2021 12:39 pm
- Location: Edinburgh, Scotland, UK
- Has thanked: 14 times
- Been thanked: 38 times
Re: CAN Bootloader
When I didn't hear back I looked into the protocol some more. There looks to be a pretty serious problem with it when it comes to supporting more than one device on the same CAN bus. Think on turning on the ignition in a car with stm32-sine, stm32-vcu and your bms. Can I suggest you add a HW platform ID (stm32-sine, stm32-vcu, etc) and a unique node ID (say last 32-bits of the platform ID from DESIG_UNIQUE_ID0) to the initial "HELLO" packet? The reply to start the download would need to include the node ID to allow the competing nodes to determine if it was for them or not.
Was considering doing something similar to replace other serial terminal commands (e.g. save, load, start, stop). Seems a hacky use of the protocol but easy to do. Would be good to share a common approach.
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
Yes; Later versions have that ID for exactly that purpose and the reset could be in the BMS firmware not in the bootloader.
The GUI can decide who to let go into user app and who not.
If you need todo multiple BMS boards i would do them one by one and keep others waiting. You can then release them all at once or one by one. I expect a small program so it won't take the world.
If you have Todo allot of boards i would broadcast the data and enable those devices who should write along. The ones who fail CRC could simply stop. This way I bet you don't over complicate and it will work. CRC never failed.
The GUI can decide who to let go into user app and who not.
If you need todo multiple BMS boards i would do them one by one and keep others waiting. You can then release them all at once or one by one. I expect a small program so it won't take the world.
If you have Todo allot of boards i would broadcast the data and enable those devices who should write along. The ones who fail CRC could simply stop. This way I bet you don't over complicate and it will work. CRC never failed.
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
I went over the code and removed the dependency for the libopeninv CAN module and some other unneeded stuff, see here
https://github.com/jsphuebner/stm32-CANBootloader/
The result:
yay, back to 4k. Now of course I need to test if it still works. I left the program logic mostly untouched.
https://github.com/jsphuebner/stm32-CANBootloader/
The result:
Code: Select all
text data bss dec hex filename
4056 16 2088 6160 1810 stm32_canloader
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
I have now completely rewritten the loader while sticking pretty much to the original protocol. Tested and works. Also got the size down a bit more
Remaining issue: I initialize the clock to run off the internal oscillator (because I omitted the external one on the BMS). Now when I flash stm32_sine, it tries to switch to the external oscillator. This apparently fails and I get a very slow blinking LED. Is it not possible to change the oscillator after initial selection?
Wouldn't be a large problem, would just need to compile different boot loaders.
Protocol is now pretty much like the UART boot loader but I switched to 2k page size to be compatible with F105 and F107 without extra overhead.
EDIT: reset command should contain 32 bits of ID info in the data part to be able to precisely select which device to reset. Said ID should also be an SDO object. That said, the nodes should be set up in a way that they have different node ids anyway.
The BMS will achieve that with a daisy-chained address signal.
Code: Select all
text data bss dec hex filename
3796 12 2064 5872 16f0 stm32_canloader
Wouldn't be a large problem, would just need to compile different boot loaders.
Protocol is now pretty much like the UART boot loader but I switched to 2k page size to be compatible with F105 and F107 without extra overhead.
- Send 0x7DE#1#'2' to indicate we entered version 2 boot loader
- Wait for reception of 0x7DD#1#0xAA magic
- Send 0x7DE#1#'S' to request number of pages, 2k per page
- Wait for reception of page size 0x7DD#1#S
- Send 0x7DE#1#'P' to request the first 8 bytes
- Repeat until full page has been received
- Send 0x7DE#1#'C' to request CRC over the 2k page
- Wait for CRC, check it
- If CRC correct program flash
- If all pages received send 0x7DE#1#'D' and we're done
- Otherwise go to 6
- If CRC incorrect send 0x7DE#1#'E' and go to 6
EDIT: reset command should contain 32 bits of ID info in the data part to be able to precisely select which device to reset. Said ID should also be an SDO object. That said, the nodes should be set up in a way that they have different node ids anyway.
The BMS will achieve that with a daisy-chained address signal.
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
-
- Posts: 213
- Joined: Mon Jan 18, 2021 12:39 pm
- Location: Edinburgh, Scotland, UK
- Has thanked: 14 times
- Been thanked: 38 times
Re: CAN Bootloader
Looked at the code. Unfortunately it fails the "What if I have more than one?" test as explained above.
If you have clashing CANopen node ids then you are in for a world of hurt. Adding redundant information to a network protocol rarely ends well...
If you have clashing CANopen node ids then you are in for a world of hurt. Adding redundant information to a network protocol rarely ends well...
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
Yes, aware of that. Changing the magic to a word of the processor uid would fix it but requires obtaining said uid making the process more complicated.
When you've got your node ids sorted there wouldn't be an issue as you only ever reset one node and the other ones won't even see the updater packets down to filtering. The updater could obtain the firmware version via SDO. If it gets more than one reply, there's trouble.
Then there's the corner case of some devices not being flashed with running firmware. They'd be in the boot loader cycle asking for firmware. In that case you'd flash random firmware to one of them. Not good. You'd have to power down all OI devices except the one you want to flash.
When you've got your node ids sorted there wouldn't be an issue as you only ever reset one node and the other ones won't even see the updater packets down to filtering. The updater could obtain the firmware version via SDO. If it gets more than one reply, there's trouble.
Then there's the corner case of some devices not being flashed with running firmware. They'd be in the boot loader cycle asking for firmware. In that case you'd flash random firmware to one of them. Not good. You'd have to power down all OI devices except the one you want to flash.
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
- EV_Builder
- Posts: 1199
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 16 times
- Been thanked: 33 times
- Contact:
Re: CAN Bootloader
I help:
Include in step 1 6 bytes of chip unique Id.
Now on boot the GUI gives lots of chips. You can self compose list of who is what.
Insert wait loop for can msg if nothing boot user app.
If received 'W' with 6bytes equal Id rerun said loop.
If received 'AA' with 6bytea Id proceed.
Now on boot GUI can show all and if no choice is made it sends to all of them W with id.
Now user selects Id. That one receives AA. Now you have 2 choices keep others waiting..send W and their ID or don't do anything and they will boot user app.
Now Dave's case is solid and johu can control what to update and what not. In step 1 one byte is left. Could be used as device description. ...
Include in step 1 6 bytes of chip unique Id.
Now on boot the GUI gives lots of chips. You can self compose list of who is what.
Insert wait loop for can msg if nothing boot user app.
If received 'W' with 6bytes equal Id rerun said loop.
If received 'AA' with 6bytea Id proceed.
Now on boot GUI can show all and if no choice is made it sends to all of them W with id.
Now user selects Id. That one receives AA. Now you have 2 choices keep others waiting..send W and their ID or don't do anything and they will boot user app.
Now Dave's case is solid and johu can control what to update and what not. In step 1 one byte is left. Could be used as device description. ...
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
- crasbe
- Posts: 243
- Joined: Mon Jul 08, 2019 5:18 pm
- Location: Germany
- Has thanked: 44 times
- Been thanked: 107 times
Re: CAN Bootloader
I can't really say how libopencm3 does it, but I've done some PLL configuration on the register level of the STM32.johu wrote: ↑Mon Feb 06, 2023 1:10 pm I have now completely rewritten the loader while sticking pretty much to the original protocol. Tested and works. Also got the size down a bit moreRemaining issue: I initialize the clock to run off the internal oscillator (because I omitted the external one on the BMS). Now when I flash stm32_sine, it tries to switch to the external oscillator. This apparently fails and I get a very slow blinking LED. Is it not possible to change the oscillator after initial selection?Code: Select all
text data bss dec hex filename 3796 12 2064 5872 16f0 stm32_canloader
Wouldn't be a large problem, would just need to compile different boot loaders.
Generally speaking you have to be very careful about the correct order of operations. The reference manual is unfortunately not veeeery detailed about this, but you could check the PLL status flags as a start to see what's going on.
If the microcontroller doesn't like the PLL settings you're trying to do, it won't apply them. Maybe it thinks, that the clock is not ready yet?
https://www.st.com/resource/en/referenc ... ronics.pdf7.2.6 System clock (SYSCLK) selection
After a system reset, the HSI oscillator is selected as system clock. When a clock source is
used directly or through the PLL as system clock, it is not possible to stop it.
A switch from one clock source to another occurs only if the target clock source is ready
(clock stable after startup delay or PLL locked). If a clock source which is not yet ready is
selected, the switch will occur when the clock source will be ready. Status bits in the Clock
control register (RCC_CR) indicate which clock(s) is (are) ready and which clock is currently
used as system clock.
I think you have to deactivate the peripheral clocks as well before switching over? But I really don't recall.
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
Intead of calling rcc_clock_setup_pll() which sets a whole host of prescalers I have now initialized only what I need:
Then, most importantly the clock source must be reset to pure HSI (8 MHz) and the PLL must be disabled before leaving the boot loader
The peripheral clocks can stay on. Would be more clean to turn them off but they will be used by most applications anyway (GPIO, CRC and CAN)
EDIT: this also saved a few 100 bytes of flash and we're down to 3.4k. I wonder if a unified boot loader supporting both CAN and UART is in reach.
Code: Select all
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL6);
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSI_CLK_DIV2);
rcc_osc_on(RCC_PLL);
rcc_wait_for_osc_ready(RCC_PLL);
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
Code: Select all
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
rcc_osc_off(RCC_PLL);
EDIT: this also saved a few 100 bytes of flash and we're down to 3.4k. I wonder if a unified boot loader supporting both CAN and UART is in reach.
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9
- johu
- Site Admin
- Posts: 5791
- Joined: Thu Nov 08, 2018 10:52 pm
- Location: Kassel/Germany
- Has thanked: 157 times
- Been thanked: 1025 times
- Contact:
Re: CAN Bootloader
I have now handled the multiple device scenario by allowing an optional ID to be specified in the magic packet. So if you have just one device on the bus you can do as before and just send a 1-byte can message with 0xAA to enter update mode. If you have multiple devices you must know their DESIG_UNIQUE_ID2 value. ID2 seems the one that always changes between processors, should be unique enough.
It remains to the user to find this. I don't think having the boot loader send it out is useful as then you still don't know who sent what. If you have a wifi module you can find it out with the "serial" command (it needs to be pimped to place a ":" between the words). In a CAN setup you can only find out with a yet to introduce SDO which means you need your node ids sorted.
Once you know the updater is launched with
It places the ID in the last word or byte 4-7 of the magic packet.
It will wait for an 'S' to be returned forever. If no one returns an S, no update happens.
EDIT: I think it might be useful to develop (if not exists) an ESP32-CAN dongle that runs the openinverter web frontend just transferring its data via CAN.
It remains to the user to find this. I don't think having the boot loader send it out is useful as then you still don't know who sent what. If you have a wifi module you can find it out with the "serial" command (it needs to be pimped to place a ":" between the words). In a CAN setup you can only find out with a yet to introduce SDO which means you need your node ids sorted.
Once you know the updater is launched with
Code: Select all
python3 updater.py -d can2 -f stm32_yourname.bin -i 8721503A
It will wait for an 'S' to be returned forever. If no one returns an S, no update happens.
EDIT: I think it might be useful to develop (if not exists) an ESP32-CAN dongle that runs the openinverter web frontend just transferring its data via CAN.
Support R/D and forum on Patreon: https://patreon.com/openinverter - Subscribe on odysee: https://odysee.com/@openinverter:9