Code Monkey home page Code Monkey logo

toboot's Introduction

Bootloader for Tomu board

This repo contains Toboot and associated support files for the EFM32HG Tomu board.

Toboot is a DFU-based bootloader for Tomu that supports easy and driver-free firmware updates.

Using Toboot

When you insert Tomu, Toboot runs by default. Some programs (such as the u2f code) set the TOBOOT_CONFIG_FLAG_AUTORUN flag, and start running immediately. To enter Toboot on these devices, short out the two outer pins with tweezers as you insert Tomu:

Force Entry

When Toboot runs, the lights will flash like this:

Toboot Pattern

You should install dfu-util. Linux users can find it in your package manager. Mac users can use Homebrew. The Windows binary is provided in the bin/ directory. Chrome users can use a web version (but Linux users should make sure the udev permissions are set up correctly first.)

You can show a list of detected devices with dfu-util --list. You can load a new program image with dfu-util --download.

Toboot API

While Toboot supports jumping straight to code, it is also possible to take advantage of more advanced features such as secure sectors and automatic program booting. This requires setting up a configuration struct located at the correct offset.

More information on the Toboot API is available in API.md.

The API is specified in toboot-api.h.

Watchdog Timer

Toboot Sets the Watchdog Timer. Your program will reboot if the watchdog timer isn't cleared within a few tens of milliseconds. This is to ensure the code returns to the bootloader if you accidentally do something like flash an MP3 file, or try to program the .ihex version.

A quick-and-dirty way to do this is to put the following at the start of your program:

*(uint32_t *)0x40088000UL = 0;

Of course, it's better to actually use a Watchdog driver and keep the watchdog fed normally. But this will at least get you going.

Entering Toboot

By default, Toboot will always run when a board is powered on. To automatically run your program at poweron, create a valid Toboot V2.0 header and set TOBOOT_CONFIG_FLAG_AUTORUN. This was done to make it easy to develop software, because all you need to do to load new firmware is to unplug Tomu and plug it back in.

There are several reasons why a user might end up in Toboot:

  1. The config value doesn't have TOBOOT_CONFIG_FLAG_AUTORUN set, and the board has just been powered on.
  2. There is no main application loaded. This can happen if you've erased the flash, or if you've loaded an invalid binary. The program's start address must be in flash, and the stack pointer must be in RAM.
  3. The board has failed to finish booting three times in a row. This can happen if you've loaded an invalid program, or if you haven't cleared the watchdog timer.
  4. The magic value 0x74624346 is stored in the boot token area, at RAM address 0x20000000.
  5. The user shorts the two outer pads together when they apply power AND the program has NOT set TOBOOT_LOCKOUT_MAGIC.

Installing or Upgrading Toboot

If you have an old toboot that isn't booting after you flashed code, make sure to short pins 1 and 4 as shown above, before plugging tomu in.

To install Toboot, use the boosted files in the prebuilt/ directory. It's a 2 stage process: First, flash Toboot and then flash AN0042 (into the Toboot serial loader). FIXME: what does AN0042 stand for?

Toboot is unable to reflash itself. This is to prevent partial updates from corrupting the firmware. Instead, a support program is appended to the start of Toboot, and the entire thing is uploaded as one chunk.

Building Toboot

Toboot is designed to be simple to build. Ensure you have an ARM toolchain installed such as the official one from ARM, as well as make. Then simply build:

cd toboot/
make

Creating Updates

Toboot is not allowed to overwrite intself, to prevent partial updates from making a board unusable.

The Booster program is used to update or install Toboot. The source code is located in the booster/ directory. Use make-booster to wrap toboot.bin in a booster app, and flash the resulting image using dfu-util:

cd ../booster/
make
gcc make-booster.c -o make-booster
./make-booster ../toboot/toboot.bin toboot-booster.bin
cp toboot-booster.bin toboot-booster.dfu
dfu-suffix --pid 0x70b1 --vid 0x1209 --add toboot-booster.dfu

You can then flash the resulting toboot-booster.dfu using dfu-util, or using the legacy serial uploader to flash toboot-booster.bin:

dfu-util -d 1209:70b1 -D toboot-booster.dfu

Flashing onto a new Tomu

Brand-new Tomus will not have Toboot installed. Instead, they might have the SiLabs AN0042 bootloader.

The recommend way to load the bootloader onto a Tomu board is using a Raspberry Pi with OpenOCD. Instructions for doing this can be found in the openocd directory. You need OpenOCD version 0.10.0 or later to have EFM32HG support.

Tomu can be powered using the 3.3V pin, so you can create a sort of "programming wand" by bringing 3.3V, GND, SCK, and SIO out to a 0.1" header, running openocd in a loop, and touching the programming pins on the side of a Tomu board. The process only takes a few seconds, so contact doesn't have to be great.

Legacy Bootloader

SiLabs AN0042 was the original bootloader. It requires an IAR compiler to build, as well as custom drivers/software on the host device. This bootloader is available in the 'an0042' branch, and has been removed from the master branch. It is here for historical interest, and for compatibility with stock EFM32HG utilities.

License

This project is broadly licensed under GPL-3.0, except for toboot-api.h which is Apache-licensed.

toboot's People

Contributors

a5464c9f32 avatar baldurmen avatar curiouslearner avatar cyphar avatar devanlai avatar fudanchii avatar gl-sergei avatar kitling avatar kitlith avatar lealanko-rt avatar marcmerlin avatar mithro avatar notthetup avatar slurdge avatar thejj avatar todbot avatar xobs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

toboot's Issues

toboot always runs on power cycle

Hi,
I have successfully put the prebuilt and recompiled versions of toboot on my tomu board. I can then use dfu-util to successfully upload and run any of the im-tomu/tomu-samples examples and the im-tomu/tomu-bootloader/tests/secure-erase/pass-1 test code.

However, on re-applying power to the board (i.e. plugging it back into USB), the toboot bootloader always runs.

Any idea why this is happening? (also, thanks for toboot, it's awesome)

Autorun flag behaviour is opposed to documented one

I read following comment:

/// When running a normal program, you won't want Toboot to run.
/// However, when developing new software it is handy to have
/// Toboot run at poweron.  Set this flag to enter Toboot whenever
/// the system has powered on for the first time.
#define TOBOOT_CONFIG_FLAG_AUTORUN_MASK        0x02
#define TOBOOT_CONFIG_FLAG_AUTORUN_SHIFT       1
#define TOBOOT_CONFIG_FLAG_AUTORUN             (1 << 1)

as "if I want to enter toboot on cold boot, I must set config=TOBOOT_CONFIG_FLAG_AUTORUN". But actual behaviour is opposite. I must set config to TOBOOT_CONFIG_FLAG_AUTORUN to disable entering toboot.

Please clarify what is correct behaviour.

Reset pin not connected

The /RESET pin (pin 7 of the MCU) is not made available. This is an issue when working on the bootloader.

Ordinarily, the system relies on being able to send a JTAG reset. This is fine if the MCU isn't locked up. However, if the MCU crashes then it is impossible to reattach gdb without a reset.

In order to develop on the bootloader itself, /RESET should be brought out to a pad.

Signed tags

Hey!

Would it be possible to sign future tags? I would make verifying the authenticity of tags much easier and isn't really much more work for you.

TOMU detects as "ComNav GNSS receiver" on Windows 10

Fixing the "ComNav GNSS Receiver" issue

I've had two laptops where the TOMU detected as a "ComNav GNSS Receiver" and would not act as a virtual COM port.

This resolved the issue for me.

  1. Leave the TOMU from your USB port

  2. Start a CMD prompt, but ensure you run it as administrator. (Press Windows Key, type "cmd", right-click on "Command Prompt" and select "Run as Administrator")

  3. In the command prompt, type the following to start device manager with special settings:
    set DEVMGR_SHOW_NONPRESENT_DEVICES=1
    devmgmt.msc

  4. From the "view" menu, select "Show hidden Devices"

  5. Navigate to "Universal Serial Bus controller", and expand it.

  6. Right-click on the "ComNav GNSS Receiver" item and choose properties

  7. Go to the "Driver panel", and click on the "Uninstall driver" button

  8. Make sure you click the "Delete the driver software for this device" checkbox, then click "Uninstall"

  9. From the "Actions" menu, choose "Rescan hardware". Your TOMU, and it should now detect as a "USB Serial Device (COMx)" device, under "Ports (COM & LPT)"

Toboot must clear entire application area

I have a security concern. When using Tomu as U2F device, it storing secret key on flash. Someone with physical access to the Tomu board can easily readout that key. He will need to boot into Toboot, upload malicious firmware which gives away secret key via USB, and then upload U2F firmware back, so that owner wouldn't even notice that secret key is stolen.
SWD can be disabled and it will be impossible to enable it without erasing flash contents. Toboot must also make sure that new firmware cannot be uploaded without erasing the whole application area.
It is also useful to leave few pages which would persist between software updates for the purpose of storing user configuration. These can be part of documented Toboot API. It should also be adviced to not store any sensitive information in this area.

U1 pin 1 marker is confusing

The "pin 1" marker for U1 is very subtle, and multiple assembly shops have had trouble identifying it.

"pin 1" should be changed to use the more traditional "pin 1 dot", rather than the current arrangement of a broken box.

Clarify API license

The tomu-bootloader repo is licensed (presumably in its entirety) under GPL3. It's not immediately clear what this means for DFU applications that are made compatible with Toboot with the aid of toboot-api.h. It seems exceedingly unlikely that using a single header with some constant and struct definitions would turn an application into a "modified version" of Toboot in the sense of GPL.

Still, it would be clearer if the API header were licensed more permissively, e.g. with an explicit permission that allowed it to be used for making non-GPL applications compatible with toboot.

Programming via ST-LinkV2

I was able to flash the bootloader with an STLinkV2, but encountered some issues. I'm exceptionally new to OpenOCD, so it may just be inexperience on my part.

Using OpenOCD and an ST-LinkV2 gives a chip ID error:

Warn : 230 69 hla_interface.c:95 hl_interface_init_target(): UNEXPECTED idcode: 0x0bc11477
Error: 231 69 hla_interface.c:98 hl_interface_init_target(): expected 1 of 1: 0x2ba01477
Debug: 232 69 command.c:628 run_command(): Command failed with error code -4

It seems that the efm32hg309 is not defined and falls through to default (0x2ba01477)
From (tcl/target/efm32.cfg):

if { [info exists CPUTAPID] } {
   set _CPUTAPID $CPUTAPID
} else {
   set _CPUTAPID 0x2ba01477
}

Using a very recent build of OpenOCD

$openocd --version
Open On-Chip Debugger 0.10.0+dev-00096-gf605a23 (2017-04-07-09:10)

Workaround - Q&D Modify openocd/tomu.conf to define CPUTAPID

-source [find interface/raspberrypi-native.cfg]
-transport select swd
+set CPUTAPID 0x0bc11477

Then this works:
openocd -f interface/stlink-v2.cfg -f ./tomu.conf

Some questions, maybe more OpenOCD related than tomu-bootloader related:
Am I building OpenOCD wrong or is the efm32hg309 just not properly supported?
Perhaps you were doing development with one of the Cortex M3 or M4 which has the chip ID of 0x2ba01477?
Or does transport select swd on the RPi config get the ID right while hla_swd transport supported by STLink somehow get it wrong?

Bootloader shouldn't need `C` line pulled high to enter

Currently you have to have a short which pulls C high to get into the boot loader.

Other options are;

  • Always boot into the boot loader, boot application if not stopped after X seconds.
  • Boot into the boot loader when buttons are pressed.
  • ????

Remove the old Silicon Labs bootloader

The DFU bootloader is better in every way;

  • It is half the size
  • It doesn't need drivers on Windows / Linux / etc
  • It's open source
  • It compiles with GCC

Clarify license

toboot being a great software using much of it's code from other projects. Some parts like vectors.c look much like borrowed from ChibiOS which is GPLv3. Others, like usb_dev.c look much like taken from https://github.com/im-tomu/chopstx/blob/efm32/mcu/usb-efm32.c which is also GPLv3, but contain wrong attribution for Teensyduino Core Library for some reason. There are parts (mcu.h) copied from Gecko SDK. It pretty much requires toboot to be licensed as GPLv3.

I think it would be great to put COPYING or LICENSE file into the project directory.

Documentation

There should probably be some documentation, for how to build, flash, and modify the bootloader, maybe about how it works too.

API docs improvements

I'll post an issue so that someone better than me at english could fix it.

I think it might be more correct to replace "The EFM32HG has 21 interrupt vectors" with "The EFM32HG has 21 external interrupt vectors".

Referring external interrupt handlers by labels (like VectorN) looks confusing as neither EFM32HG manual nor ARM manual 1 doesn't do that. After some googling I found that it probably comes from ChibiOS where corresponding code was copy-pasted from. Maybe replace labels with offsets or IRQ line numbers?

It would be great to add that in order to implement toboot configuration in Gecko SDK, one must hack on startup_efm32hg.c file and append something like this to the vectors array:

diff --git i/platform/Device/SiliconLabs/EFM32HG/Source/GCC/startup_efm32hg.c w/platform/Device/SiliconLabs/EFM32HG/Sour
ce/GCC/startup_efm32hg.c
index d3eaacee..3714743d 100644
--- i/platform/Device/SiliconLabs/EFM32HG/Source/GCC/startup_efm32hg.c
+++ w/platform/Device/SiliconLabs/EFM32HG/Source/GCC/startup_efm32hg.c
@@ -173,6 +173,8 @@ const pFunc __Vectors[] __attribute__ ((section(".vectors"))) = {
   USART0_TX_IRQHandler,                       /*  18 - USART0_TX       */
   USB_IRQHandler,                       /*  19 - USB       */
   TIMER2_IRQHandler,                       /*  20 - TIMER2       */
+  0x000070b0UL,                            /* toboot cfg flags */
+  0x00046fb0UL,                            /* toboot app flags */
 
 };

Clarify documentation points.

README.md doesn't include:

  • What to do after dfu-util has completed in the prebuilt directory
  • dfu-util usage with prebuilt should be in the first paragraph for "quickstart" instead of down the page
  • Should contain what version the firmware "will be"
  • Should contain instructions on how to verify the firmware successfully flashed (lsusb or system information on osx)

These would help make the "new user" experience better.

Cannot boot after flashing

The bootloader cannot boot an application immediately after the bootloader has been flashed and reset. This is a (minor) inconvenience when developing the bootloader.

The problem is that flashing leaves the contents of RAM in an unspecified state with the reset cause SYSREQRST. The bootloader only initializes the boot token when the reset cause is PORST and otherwise assumes that it has valid contents. So what happens is that after flashing the bootloader happily checks the value of boot_count field of the boot token, and this field most probably contains some large value left by the flashing. Hence the application boot is aborted due to BOOT_FAILED_TOO_MANY_TIMES.

To solve this, the bootloader should somehow verify that the boot token contents are valid without depending on the reset cause. Perhaps use some (non-zero) magic value in the magic field of the boot token even when not forcing bootloader entry?

Packet-sized control transfers broken

Something goes wrong when the size of an IN control transfer is an exact multiple of the packet size (64 bytes). This is perhaps easiest to test by trying out a string descriptor that is 31 characters long. I haven't investigated exactly what happens, but I suspect that two zero-length packets are sent when only one is mandated.

The easiest way to fix this is to change < to <= in https://github.com/im-tomu/tomu-bootloader/blob/master/toboot/usb_dev.c#L242 but I believe it's also possible to get rid of require_zlp altogether so then the current comparison is correct: the packet is last if it is not full.

Unless I'm missing something, there's also another issue: according to USB 1.1 section 5.5.3, a zero-length packet should not be sent after the last packet, if data_p->len == len_asked, even if the the last packet is full.

Presumably these situations have never come up so far, so they are hardly critical, but they are certainly nasty pitfalls in waiting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.