Releases: lupyuen/pinetime-rust-mynewt
MCUBoot with Vector Table Relocation (Official PineTime Preload)
Final release of MCUBoot Bootloader for PineTime Preload yay!
-
Bootloader Firmware Image for preloading on PineTime: https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.7/mynewt_nosemi.elf.bin
-
Tested according to https://gist.github.com/lupyuen/fb4cc04f03219d913cba8ec371f8c644
-
Built with
v4.1.7
of this repo under branchota2
-
With Apache Mynewt
v1.7.0
and MCUBootv1.5.0
repository.apache-mynewt-core: type: github vers: 1.7.0 user: apache repo: mynewt-core repository.mcuboot: type: github vers: 1.5.0 user: JuulLabs-OSS repo: mcuboot
-
Build instructions for MCUBoot: https://lupyuen.github.io/pinetime-rust-mynewt/articles/mcuboot#build-and-flash-mcuboot-bootloader
-
ota2
branch has been merged to themaster
branch as of 1 Aug 2020. All new development of MCUBoot shall continue with themaster
branch.
Previous Notes
Tested OK with FreeRTOS yay!
Demo video: https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.7/mcuboot-freertos.mp4
Set flash-app.ocd
to...
program /Users/Luppy/Downloads/jf.bin verify 0x00008000
FreeRTOS firmware jf.bin
may be found here: https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.5
Stub Bootloader for Debugging MCUBoot
v4.1.6 Added semihosting compiler flag
Debugging FreeRTOS + MCUBoot on PineTime
-
Generate the disassembly
pinetime-app.S
from the executablepinetime-app.out
...arm-none-eabi-objdump -t -S --demangle --line-numbers --wide pinetime-app.out >pinetime-app.S 2>&1
-
Flash the Stub Bootloader
boot_stub.elf.bin
to address0x0
: https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.6This allows the debugger to jump to the application firmware properly, even when the firmware doesn't have a valid MCUBoot Image Header.
-
For VSCode Debugger, edit
.vscode/launch.json
and set the executable to be debugged...{ "version": "0.2.0", "configurations": [ { "executable": "/Users/Luppy/Downloads/pinetime-app.out",
-
Start the VSCode debugger
-
Function
vPortStartFirstTask()
in FreeRTOS is executing the Arm instructionSVC 0
(System Call) and it fails -
Is it because SCB VTOR Register is pointing to the wrong Interrupt Vector Table?
See "Special Note to Arm Cortex-M Users": https://www.freertos.org/FAQHelp.html
-
What is the Interrupt Vector Table? It's a table of pointers to exception and interrupt handlers...
See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABIFJFG.html
Usually the table is stored at the start of ROM, at addresses 0x0. Now with the MCUBoot Bootloader we allow each operating system to set their own vector table. Which could be the problem here.
-
The SCB VTOR Register should point to the Interrupt Vector Table: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Ciheijba.html
VTOR Register is located at
0xE000ED08
:
http://infocenter.arm.com/help/topic/com.arm.doc.100166_0001_04_en/ric1417011873697.html -
Our VTOR Register at
0xE000ED08
points to0x20000000
, which is the start of RAM:x/x 0xE000ED08 0xe000ed08: 0x20000000
-
What's at
0x20000000
? Looks like garbage, not an Interrupt Vector Table...x/40x 0x20000000 0x20000000: 0x00000000 0x20000008 0x00000000 0x0004894c 0x20000010 <impure_data+8>: 0x0004896c 0x0004892c 0x00000000 0x00000000 0x20000020 <impure_data+24>: 0x00000000 0x00000000 0x00000000 0x00000000 0x20000030 <impure_data+40>: 0x00000000 0x00000000 0x00000000 0x00000000 0x20000040 <impure_data+56>: 0x2000bde0 0x00000000 0x00000000 0x00000000 0x20000050 <impure_data+72>: 0x00000000 0x00000000 0x00000000 0x00000000 0x20000060 <impure_data+88>: 0x00000000 0x00000000 0x03d09000 0x00000000 0x20000070 <log_backend_cb_rtt_log_backend+4>: 0x00000100 0x00045a78 0x00043d0c 0x00043d14 0x20000080 <_ZN8Pinetime12Applications7Screens5Clock10DaysStringE+12>: 0x00043d1c 0x00043d28 0x00043d34 0x00043d3c 0x20000090 <_ZN8Pinetime12Applications7Screens5Clock10DaysStringE+28>: 0x00043d48 0x00045a78 0x00043cdc 0x00043ce0
-
MCUBoot set the VTOR to
0x20000000
at startup, but FreeRTOS doesn't set VTOR. Hence the conflict. -
Let's fix VTOR and the Interrupt Vector Table. There is a valid Interrupt Vector Table for FreeRTOS at
0x8020
, aliased to__isr_vector
...x/40x 0x8020 0x8020 <__isr_vector>: 0x20010000 0x0000870d 0x00008735 0x00008737 0x8030 <__isr_vector+16>: 0x00008739 0x0000873b 0x0000873d 0x00000000 0x8040 <__isr_vector+32>: 0x00000000 0x00000000 0x00000000 0x000143bd 0x8050 <__isr_vector+48>: 0x00008741 0x00000000 0x000143dd 0x00008745 0x8060 <__isr_vector+64>: 0x00008935 0x00010d91 0x00008747 0x00010d2d 0x8070 <__isr_vector+80>: 0x0000edf1 0x00008747 0x00008c55 0x00009255 0x8080 <__isr_vector+96>: 0x00008747 0x00008747 0x00008747 0x00010da9 0x8090 <__isr_vector+112>: 0x00008747 0x00010d9d 0x00008747 0x00008747 0x80a0 <__isr_vector+128>: 0x00010db5 0x0001443d 0x00008747 0x00008747 0x80b0 <__isr_vector+144>: 0x00008747 0x00008747 0x00008747 0x00008747
-
Can we just set VTOR to
0x8020
? Apparently not, since0x8020
is not a page-aligned address. -
Thus we should set VTOR to
0x20000000
SCB->VTOR = 0x20000000;
Then reserve
0xD8
bytes at0x20000000
for the Interrupt Vector Table, and we should manually copy0xD8
bytes from0x8020
to0x20000000
memcpy((void *) 0x20000000, (void *) 0x8020, 0xd8);
-
0x20000000
is already used by other variables, see https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.5/Screenshot.2020-05-21.at.8.08.29.AM.pngSo we need to edit the Linker Script to reserve
0xD8
bytes for a section named.vector_relocation
at0x20000000
...... __etext = .; .vector_relocation : { . = ALIGN(4); __vector_tbl_reloc__ = .; . = . + (__isr_vector_end - __isr_vector_start); . = ALIGN(4); } > RAM .data : { __data_start__ = .; *(vtable) *(.data*) ...
From https://github.com/apache/mynewt-core/blob/master/hw/mcu/nordic/nrf52xxx/nrf52.ld
Note that
.vector_relocation
MUST be the first thing in RAM (0x20000000
). It should appear before.data
. -
For reference, check the vector table relocation code in https://github.com/apache/mynewt-core/blob/master/hw/cmsis-core/src/cmsis_nvic.c
extern char __isr_vector[]; extern char __vector_tbl_reloc__[]; void NVIC_Relocate(void) { uint32_t *current_location; uint32_t *new_location; int i; /* * Relocate the vector table from its current position to the position * designated in the linker script. */ current_location = (uint32_t *)&__isr_vector; new_location = (uint32_t *)&__vector_tbl_reloc__; if (new_location != current_location) { for (i = 0; i < NVIC_NUM_VECTORS; i++) { new_location[i] = current_location[i]; } } /* Set VTOR except for M0 */ SCB->VTOR = (uint32_t)&__vector_tbl_reloc__; }
MCUBoot with Semihosting Disabled
PineTime Firmware Update Video
To download the video, scroll to the end of this page, click Assets
then pinetime-dfu.mp4
Refer to the article:
Wireless Firmware Update In Action on PineTime Smart Watch (nRF52)
Mynewt Firmware Update Test
Testing Firmware Update with 2 versions of Mynewt Firmware: 1.1.0 and 1.2.0
Refer to the articles...
MCUBoot with Firmware Update over Bluetooth
Contents:
-
mynewt.*
: Enhanced Build of MCUBoot Bootloader 1.5.0, supports Boot Graphic and SPI Flash -
my_sensor_app.*
: Application Firmware that supports firmware upgrade over Bluetooth. -
boot-graphic.bin
: Boot Graphic in RGB565 format (Hand-drawn PineTime Logo) -
pinetime-rust-mynewt.7z
: Complete set of build files generated on macOS
Refer to the articles...
Log:
Starting Bootloader...
Displaying image...
Image displayed
Button: 0
[INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INF] Boot source: primary slot
[INF] Swap type: none
Button: 0
Button: 0
Bootloader done
TMP create temp_stub_0
NET hwid 4a f8 cf 95 6a be c1 f6 89 ba 12 1a
NET standalone node
Testing flash...
Read Internal Flash ROM...
Read 0x0 + 20
0x0000: 0x00 0x00 0x01 0x20 0xd9 0x00 0x00 0x00
0x0008: 0x35 0x01 0x00 0x00 0x37 0x01 0x00 0x00
0x0010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0018: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Read External SPI Flash...
Read 0x0 + 20
0x0000: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0008: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0018: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Flash OK
Rust test display
MCUBoot with Firmware Update over Bluetooth (Work In Progress)
Work In Progress: Build of MCUBoot Bootloader 1.5.0 (mynewt.*
) and Application Firmware (my_sensor_app.*
) that supports firmware upgrade over Bluetooth. Boots OK. Firmware upgrade not tested yet.
pinetime-rust-mynewt.7z
contains the complete set of build files generated on macOS
See https://lupyuen.github.io/pinetime-rust-mynewt/articles/dfu
PineTime Firmware with Visual Rust and Mynewt (Raspberry Pi Build)
TODO
PineTime Firmware with Visual Rust and Mynewt (macOS Build)
TODO