Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: Upload firmware via CANbus

  1. #1

    Upload firmware via CANbus

    I am looking at CANbus for a project I am working on and it has been suggested that some MCU's would allow me to distribute firmware updates via CANbus packets (I realise the the protocol is limited to 8 bytes per frame).

    I am thinking I could transfer the code in 8 byte blocks to attached FRAM (via SPI) / EEPROM and then have the Teensy load the new code on reboot. CANbus has pretty solid CRC checking so I would know that each 8 bytes of the firmware has been successfully delivered and stored in FRAM.

    Can I update firmware on the Teensy 3.5/3.6 via CANbus ? If not are there other remote ways to update the runnign firmware on a Teensy ?

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,886
    PJRC only supports Teensy sketch update over the USB port.

    Others have managed to do code flash updates on T_3.2 - but not seen any notes pass by on T_3.5/3.6 yet?

  3. #3
    Ok thanks. I’ll have to look at ESP32 and STM32 to see if this is possible on them. It’s a shame because I really wanted to be able to support Paul’s product.

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,975
    I managed to use a Teensy as programmer. https://forum.pjrc.com/threads/47783...369#post159369 So, in principle you could connect the programming Teensy to the CAN Bus, transmit the hex file to it and program your Teensy via this programmer. It should also be possible to program more than one Teensy with this setup.

    This is of course by no way an elegant solution but it should work.

  5. #5
    I’ll take a look. Thanks.

  6. #6
    Senior Member Epyon's Avatar
    Join Date
    Apr 2013
    Location
    Belgium
    Posts
    443
    I don't think any of the popular MCU's support uploading code through CAN out of the box. You will need to write you own bootloader for this, just like Paul has done to support uploading code through USB.

  7. #7
    OK - I understand however it is pretty limiting. Anyone who wants to remote deploy one of these then can't manage firmware updates to their code remotely. I have to send someone to site with a laptop and USB cable.

  8. #8
    Senior Member Epyon's Avatar
    Join Date
    Apr 2013
    Location
    Belgium
    Posts
    443
    Quote Originally Posted by ilium007 View Post
    OK - I understand however it is pretty limiting. Anyone who wants to remote deploy one of these then can't manage firmware updates to their code remotely. I have to send someone to site with a laptop and USB cable.
    And now you have an CAN bus between your desk and all your remote devices?

  9. #9
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,077
    i hope you dont reprogram a motor vehicle while its on the road :P

  10. #10
    Member
    Join Date
    Jul 2016
    Location
    Denmark
    Posts
    36
    i have gotten firmware updating to work on t_3.1 t_3.5 and t_3.6 but only with very limited testing, and very few instructions, but you are welcome to have a look
    https://github.com/alex-Arc/Firmware...flash_from_udp

    and the thread about it https://forum.pjrc.com/threads/29607...-updates/page2
    Last edited by alex-arc; 11-29-2017 at 04:49 PM.

  11. #11
    Junior Member
    Join Date
    Aug 2017
    Posts
    2
    Hi

    I had a play with firmware flashing on the teensy 3.6, I found I got quite a few lock ups during the moving of the flash from top halve to bottom halve.
    This only happened when I was compiling the code for cpu speeds higher than 120MHz (like the default 180MHz).

    I was able to fix that by making a local copy of the functions (they are in mk20dx128.c):

    Code:
    kinetis_hsrun_disable()
    kinetis_hsrun_enable()
    and adding the

    Code:
    RAMFUNC
    to the front of them. Like this:

    Code:
    #if defined(HAS_KINETIS_HSRUN) && defined(__MK66FX1M0__) && F_CPU > 120000000
    
    // This reduce the cpu frequency to 120MHz and disable the HSRUN mode (high speed).
    // This is copied from mk20dx128.c and added the RAMFUNC attrib to make sure its run from RAM.
    RAMFUNC int kinetis_hsrun_disable_RAM(void)
    {
    	if (SMC_PMSTAT == SMC_PMSTAT_HSRUN) {
    		// First, reduce the CPU clock speed, but do not change
    		// the peripheral speed (F_BUS).  Serial1 & Serial2 baud
    		// rates will be impacted, but most other peripherals
    		// will continue functioning at the same speed.
    #if F_CPU == 240000000 && F_BUS == 60000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
    #elif F_CPU == 240000000 && F_BUS == 80000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
    #elif F_CPU == 240000000 && F_BUS == 120000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
    #elif F_CPU == 216000000 && F_BUS == 54000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
    #elif F_CPU == 216000000 && F_BUS == 72000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
    #elif F_CPU == 216000000 && F_BUS == 108000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
    #elif F_CPU == 192000000 && F_BUS == 48000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
    #elif F_CPU == 192000000 && F_BUS == 64000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
    #elif F_CPU == 192000000 && F_BUS == 96000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
    #elif F_CPU == 180000000 && F_BUS == 60000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
    #elif F_CPU == 180000000 && F_BUS == 90000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
    #elif F_CPU == 168000000 && F_BUS == 56000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
    #elif F_CPU == 144000000 && F_BUS == 48000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
    #elif F_CPU == 144000000 && F_BUS == 72000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 5); // ok
    #else
    		return 0;
    #endif
    		// Then turn off HSRUN mode
    		SMC_PMCTRL = SMC_PMCTRL_RUNM(0);
    		while (SMC_PMSTAT == SMC_PMSTAT_HSRUN); // wait
    		return 1;
    	}
    	return 0;
    }
    
    RAMFUNC int kinetis_hsrun_enable_RAM(void)
    {
    	if (SMC_PMSTAT == SMC_PMSTAT_RUN) {
    		// Turn HSRUN mode on
    		SMC_PMCTRL = SMC_PMCTRL_RUNM(3);
    		while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) { ; } // wait
    													 // Then configure clock for full speed
    #if F_CPU == 240000000 && F_BUS == 60000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
    #elif F_CPU == 240000000 && F_BUS == 80000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
    #elif F_CPU == 240000000 && F_BUS == 120000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
    #elif F_CPU == 216000000 && F_BUS == 54000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
    #elif F_CPU == 216000000 && F_BUS == 72000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
    #elif F_CPU == 216000000 && F_BUS == 108000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
    #elif F_CPU == 192000000 && F_BUS == 48000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 6);
    #elif F_CPU == 192000000 && F_BUS == 64000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
    #elif F_CPU == 192000000 && F_BUS == 96000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
    #elif F_CPU == 180000000 && F_BUS == 60000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
    #elif F_CPU == 180000000 && F_BUS == 90000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
    #elif F_CPU == 168000000 && F_BUS == 56000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 5);
    #elif F_CPU == 144000000 && F_BUS == 48000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 4);
    #elif F_CPU == 144000000 && F_BUS == 72000000
    		SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 4);
    #else
    		return 0;
    #endif
    		return 1;
    	}
    	return 0;
    }
    #else // HAS_KINETIS_HSRUN && F_CPU > 120000000
    __attribute__((always_inline)) static inline int kinetis_hsrun_disable_RAM(void) { return 0; }
    __attribute__((always_inline)) static inline int kinetis_hsrun_enable_RAM(void) { return 0; }
    #endif
    The problem seemed to have been that those functions (which are only used at cpu speeds > 120MHz) were running from flash memory (which is getting overwritten).

    Does anybody know how to push a function into ram and then run it from there without having to make a copy?

  12. #12
    Junior Member
    Join Date
    Aug 2014
    Location
    Sweden, Växjö
    Posts
    1
    Hi, I realize this is quite an old post.

    But I have managed to build a CAN bootloader that also works on teensy3.2 (and stm32f373)
    It's part of a bigger project.

    If anyone finds it interesting its located here:
    https://github.com/mumme74/CarTransp...are/bootloader

    Although I have tested it, I'm sure there more are issues to find

    It works differently from PhotosyncQ. It can not overwrite the config bytes in lower part of flash.
    Reason for this is that the bootloader is a normal Teensy program, but with a custom linkscript.
    It takes 12Kb of the lower part of flash, that can not be occupied by your normal program.

    When you compile a program for use with this bootloader you must compile against a custom linkscript.
    https://github.com/mumme74/CarTransp...U/mk20dx256.ld

    Otherwise your program.bin will have wrong adressess internally and it wont work.

    To upload, download, erase etc via CAN bus, you use the host program in folder firmware/bootloader/bootloader-host/* which is a commandline program.
    I have tested with raspberrypi industrialberry CAN board through socketcan, and also with Lawicell CANUSB adapter.

    Sorry for my bad english, Swedish is my native tongue.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •