diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..afbfdcc
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,11 @@
+# From https://code.visualstudio.com/docs/remote/troubleshooting#_resolving-git-line-ending-issues-in-wsl-resulting-in-many-modified-files
+* text=auto eol=lf
+*.{cmd,[cC][mM][dD]} text eol=crlf
+*.{bat,[bB][aA][tT]} text eol=crlf
+*.bin binary
+*.ch8 binary
+*.exe binary
+*.fzz binary
+*.jpg binary
+*.png binary
+*.woff binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ef3f288
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,48 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+.app.db
+.app
+bin
+obj
+tags
+.gdb_history
+.gdb_out
+.gdb_cmds
+*~
+.DS_Store
+*.swp
+*.swo
+.vscode/ipch/
+openocd
+repos
+project.state
+**/*.rs.bk
+# .#*
+# .gdb_history
+Cargo.lock
+target/
+OLDrust
+tmprustlib
+*.7z
+xPack*/
+libftdi1*/
+libftdi1*.bz2
+libusb*/
+hidapi*/
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..81b77cd
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/pinetime-rust-mynewt-restore-factory-image.iml b/.idea/pinetime-rust-mynewt-restore-factory-image.iml
new file mode 100644
index 0000000..bc2cd87
--- /dev/null
+++ b/.idea/pinetime-rust-mynewt-restore-factory-image.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..8d78521
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..af47bc1
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1608644408188
+
+
+ 1608644408188
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vscode/.cortex-debug.peripherals.state.json b/.vscode/.cortex-debug.peripherals.state.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/.vscode/.cortex-debug.peripherals.state.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/.vscode/.cortex-debug.registers.state.json b/.vscode/.cortex-debug.registers.state.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/.vscode/.cortex-debug.registers.state.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/.vscode/bookmarks.json b/.vscode/bookmarks.json
new file mode 100644
index 0000000..7a4ba82
--- /dev/null
+++ b/.vscode/bookmarks.json
@@ -0,0 +1,332 @@
+[
+ {
+ "path": "$ROOTPATH$/bin/targets/bluepill_my_sensor/generated/src/bluepill_my_sensor-sysinit-app.c",
+ "bookmarks": [
+ {
+ "line": 21,
+ "column": 11,
+ "label": "sysinit"
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/targets/bluepill_my_sensor/syscfg.yml",
+ "bookmarks": [
+ {
+ "line": 18,
+ "column": 3,
+ "label": "syscfg bluepill"
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/apps/my_sensor_app/pkg.yml",
+ "bookmarks": [
+ {
+ "line": 72,
+ "column": 5,
+ "label": "pkg"
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/sensor/creator/src/sensor_creator.c",
+ "bookmarks": [
+ {
+ "line": 199,
+ "column": 37,
+ "label": "sensor creator"
+ },
+ {
+ "line": 459,
+ "column": 12,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/libs/semihosting_console/src/semihosting_console.c",
+ "bookmarks": [
+ {
+ "line": 21,
+ "column": 11,
+ "label": "semihosting console"
+ }
+ ]
+ },
+ {
+ "path": "/Users/Luppy/mynewt/stm32bluepill-mynewt-sensor\\bin\\targets\\bluepill_my_sensor\\generated\\src\\bluepill_my_sensor-sysinit-app.c",
+ "bookmarks": [
+ {
+ "line": 1,
+ "column": 18,
+ "label": "sysinit"
+ }
+ ]
+ },
+ {
+ "path": "/Users/Luppy/mynewt/stm32bluepill-mynewt-sensor\\apps\\my_sensor_app\\syscfg.yml",
+ "bookmarks": [
+ {
+ "line": 0,
+ "column": 13,
+ "label": "syscfg"
+ }
+ ]
+ },
+ {
+ "path": "/Users/Luppy/mynewt/stm32bluepill-mynewt-sensor\\targets\\bluepill_my_sensor\\syscfg.yml",
+ "bookmarks": [
+ {
+ "line": 0,
+ "column": 3,
+ "label": "syscfg target"
+ }
+ ]
+ },
+ {
+ "path": "/Users/Luppy/mynewt/stm32bluepill-mynewt-sensor\\bin\\targets\\bluepill_my_sensor\\generated\\include\\syscfg\\syscfg.h",
+ "bookmarks": [
+ {
+ "line": 4,
+ "column": 15,
+ "label": "syscfg generated"
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/drivers/sensors/bme280/src/bme280.c",
+ "bookmarks": [
+ {
+ "line": 694,
+ "column": 9,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/net/oic/src/api/oc_rep.c",
+ "bookmarks": [
+ {
+ "line": 143,
+ "column": 12,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/net/oic/src/messaging/coap/coap.c",
+ "bookmarks": [
+ {
+ "line": 339,
+ "column": 19,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/encoding/tinycbor/src/cborencoder.c",
+ "bookmarks": [
+ {
+ "line": 241,
+ "column": 17,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/scripts/gen-bindings.sh",
+ "bookmarks": [
+ {
+ "line": 1,
+ "column": 5,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/sensor/src/sensor.c",
+ "bookmarks": [
+ {
+ "line": 237,
+ "column": 15,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/kernel/os/src/os_callout.c",
+ "bookmarks": [
+ {
+ "line": 123,
+ "column": 7,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/kernel/os/src/os.c",
+ "bookmarks": [
+ {
+ "line": 140,
+ "column": 14,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c",
+ "bookmarks": [
+ {
+ "line": 139,
+ "column": 9,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/kernel/os/src/os_time.c",
+ "bookmarks": [
+ {
+ "line": 26,
+ "column": 15,
+ "label": ""
+ },
+ {
+ "line": 85,
+ "column": 11,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/mcu/stm/stm32f1xx/src/ext/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c",
+ "bookmarks": [
+ {
+ "line": 165,
+ "column": 13,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/mcu/stm/stm32f1xx/src/ext/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c",
+ "bookmarks": [
+ {
+ "line": 64,
+ "column": 15,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/mcu/stm/stm32l4xx/src/ext/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c",
+ "bookmarks": [
+ {
+ "line": 2,
+ "column": 15,
+ "label": ""
+ },
+ {
+ "line": 3179,
+ "column": 22,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/mcu/stm/stm32_common/src/hal_uart.c",
+ "bookmarks": [
+ {
+ "line": 469,
+ "column": 20,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-core/hw/mcu/stm/stm32l4xx/src/ext/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h",
+ "bookmarks": [
+ {
+ "line": 967,
+ "column": 10,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/hw/bsp/stm32l4/bsp.yml",
+ "bookmarks": [
+ {
+ "line": 19,
+ "column": 14,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/apps/my_sensor_app/src/device_composition.c",
+ "bookmarks": [
+ {
+ "line": 288,
+ "column": 16,
+ "label": ""
+ },
+ {
+ "line": 2548,
+ "column": 42,
+ "label": ""
+ },
+ {
+ "line": 2697,
+ "column": 34,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/apps/my_sensor_app/src/app_gpio.c",
+ "bookmarks": [
+ {
+ "line": 74,
+ "column": 10,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/apps/my_sensor_app/src/publisher.c",
+ "bookmarks": [
+ {
+ "line": 63,
+ "column": 18,
+ "label": ""
+ },
+ {
+ "line": 68,
+ "column": 7,
+ "label": ""
+ },
+ {
+ "line": 76,
+ "column": 21,
+ "label": ""
+ },
+ {
+ "line": 99,
+ "column": 29,
+ "label": ""
+ }
+ ]
+ },
+ {
+ "path": "$ROOTPATH$/repos/apache-mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c",
+ "bookmarks": [
+ {
+ "line": 63,
+ "column": 16,
+ "label": ""
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000..4b29453
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,80 @@
+{
+ "configurations": [
+ {
+ "name": "Mynewt",
+ "includePath": [
+ "${workspaceFolder}/bin/targets/nrf52_my_sensor/generated/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/boot/split/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/time/datetime/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/encoding/json/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/encoding/tinycbor/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/hw/drivers/flash/spiflash/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/hw/hal/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/hw/mcu/nordic/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/hw/mcu/nordic/nrf52xxx/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/hw/mcu/nordic/src/ext/nrfx/",
+ "${workspaceFolder}/repos/apache-mynewt-core/hw/mcu/nordic/src/ext/nrfx/mdk",
+ "${workspaceFolder}/repos/apache-mynewt-core/hw/sensor/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/kernel/os/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/kernel/os/include/os",
+ "${workspaceFolder}/repos/apache-mynewt-core/kernel/os/include/os/arch/cortex_m4",
+ "${workspaceFolder}/repos/apache-mynewt-core/mgmt/imgmgr/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/mgmt/newtmgr/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/mgmt/newtmgr/transport/ble/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/net/oic/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/config/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/defs/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/flash_map/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/log/common/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/log/modlog/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/log/stub/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/sys/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/sysdown/include",
+ "${workspaceFolder}/repos/apache-mynewt-core/sys/sysinit/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/host/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/host/services/ans/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/host/services/dis/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/host/services/gap/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/host/services/gatt/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/host/store/config/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/host/util/include",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/nimble/transport",
+ "${workspaceFolder}/repos/apache-mynewt-nimble/porting/npl/mynewt/include",
+ "${workspaceFolder}/repos/mcuboot/boot/bootutil/include",
+ "${workspaceFolder}/hw/bsp/nrf52/include",
+ "${workspaceFolder}/libs/esp8266/include",
+ "${workspaceFolder}/libs/hmac_prng/include",
+ "${workspaceFolder}/libs/nrf24l01/include",
+ "${workspaceFolder}/libs/pinetime_boot/include",
+ "${workspaceFolder}/libs/pinetime_lvgl_mynewt",
+ "${workspaceFolder}/libs/pinetime_lvgl_mynewt/include",
+ "${workspaceFolder}/libs/semihosting_console/include",
+ "${workspaceFolder}/libs/sensor_coap/include",
+ "${workspaceFolder}/libs/sensor_network/include"
+ ],
+ "defines": [
+ "APP_NAME=my_sensor_app",
+ "APP_my_sensor_app",
+ "ARCH_NAME=cortex_m3",
+ "ARCH_cortex_m3",
+ "BSP_NAME=nrf52",
+ "BSP_nrf52",
+ "FLOAT_SUPPORT",
+ "MCUBOOT_HAVE_LOGGING=1",
+ "MYNEWT=1",
+ "SECURE=0",
+ "STM32F103xB",
+ "_DEBUG",
+ "UNICODE",
+ "_UNICODE"
+ ],
+ "windowsSdkVersion": "10.0.10586.0",
+ "compilerPath": "/usr/local/bin/arm-none-eabi-gcc",
+ "cStandard": "c11",
+ "cppStandard": "c++17",
+ "intelliSenseMode": "gcc-x64"
+ }
+ ],
+ "version": 4
+}
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..6c58981
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,6 @@
+{
+ "recommendations": [
+ "sanaajani.taskrunnercode",
+ "marus25.cortex-debug"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/launch-bluepill.json b/.vscode/launch-bluepill.json
new file mode 100644
index 0000000..6704dfc
--- /dev/null
+++ b/.vscode/launch-bluepill.json
@@ -0,0 +1,58 @@
+{
+ // VSCode Debugger Config for Cortex Debug Extension. We use Cortex Debug because it shows more details, e.g. the STM32 Peripherals.
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // Cortex Debug Configuration: https://marcelball.ca/projects/cortex-debug/cortex-debug-launch-configurations/
+ "name": "Blue Pill",
+ "type": "cortex-debug",
+ "request": "launch",
+ // OpenOCD path is defined in workspace.code-workspace.
+ "servertype": "openocd",
+ "cwd": "${workspaceRoot}",
+ // Application Executable to be flashed to Blue Pill before debugging. Note that the Application ELF image does not contain a valid Image Header. So we must bypass the Bootloader, shown below.
+ "executable": "bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ // For Bootloader: "executable": "bin/targets/bluepill_boot/app/apps/boot_stub/boot_stub.elf",
+ "device": "STM32F103C8",
+ "svdFile": "scripts/STM32F103xx.svd",
+ "configFiles": [
+ // Tell OpenOCD to open the ST Link connection to STM32F1 MCU.
+ "interface/stlink-v2.cfg",
+ "target/stm32f1x.cfg",
+ // Tell OpenOCD to run our custom debug commands.
+ "scripts/debug.ocd"
+ ],
+ "preLaunchCommands": [
+ // Before loading the Application, run these gdb commands.
+ // Set timeout for executing openocd commands.
+ "set remotetimeout 60",
+
+ // This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
+ "set breakpoint pending on"
+
+ // Display the Arm instruction when hitting breakpoint.
+ // "display/i $pc",
+
+ // Load Bootloader symbols in case we jump to the Bootloader.
+ // "symbol-file bin/targets/bluepill_boot/app/apps/boot/boot.elf",
+
+ // Restore Application symbols.
+ // "symbol-file bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ ],
+ "postLaunchCommands": [
+ // After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
+ // If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
+ // "stepi", // Must step before setting PC
+ // "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
+ // "stepi", // Execute the Reset Handler
+ "break main", // Break at main()
+ "break __assert_func", // Break for any assert failures
+ "break os_default_irq" // Break for any unhandled interrupts
+ ],
+ "preRestartCommands": [
+ ],
+ "postRestartCommands": [
+ ]
+ }
+ ]
+}
diff --git a/.vscode/launch-gd32vf103.json b/.vscode/launch-gd32vf103.json
new file mode 100644
index 0000000..4d526f1
--- /dev/null
+++ b/.vscode/launch-gd32vf103.json
@@ -0,0 +1,42 @@
+{
+ // VSCode Debugger Config
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "GD32VF103",
+ "type": "gdb",
+ "request": "launch",
+ // Application Executable to be flashed to Blue Pill before debugging. Note that the Application ELF image does not contain a valid Image Header. So we must bypass the Bootloader, shown below.
+ "target": "${workspaceRoot}/bin/targets/gd32vf103c-start_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ // For Bootloader: "target": "${workspaceRoot}/bin/targets/gd32vf103c-start_boot/app/apps/boot_stub/boot_stub.elf",
+ "cwd": "${workspaceRoot}",
+ "gdbpath": "${workspaceRoot}/xPacks/riscv-none-embed-gcc/8.2.0-3.1/bin/riscv-none-embed-gdb",
+ "valuesFormatting": "parseText",
+ "autorun": [
+ // Before loading the Application, run these gdb commands.
+ // Set timeout for executing openocd commands.
+ "set remotetimeout 600",
+
+ // This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
+ "set breakpoint pending on",
+
+ // Set breakpoints
+ "break main", // Break at main()
+ "break __assert_func", // Break for any assert failures
+ "break os_default_irq", // Break for any unhandled interrupts
+
+ // Launch OpenOCD. Based on https://www.justinmklam.com/posts/2017/10/vscode-debugger-setup/
+ "target remote | riscv-openocd/src/openocd -s riscv-openocd/tcl -c \"gdb_port pipe; log_output openocd.log\" -f scripts/gd32vf103/flash-init.ocd -f interface/cmsis-dap.cfg -f scripts/gd32vf103/gd32vf103.ocd -f scripts/gd32vf103/debug.ocd ",
+
+ // After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
+ ////"monitor reset halt", // Restart and halt
+ ////"flushregs", // Flush the register cache
+
+ // If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
+ // "stepi", // Must step before setting PC
+ // "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
+ // "stepi", // Execute the Reset Handler
+ ]
+ }
+ ]
+}
diff --git a/.vscode/launch-nrf52-pi.json b/.vscode/launch-nrf52-pi.json
new file mode 100644
index 0000000..f6ec45e
--- /dev/null
+++ b/.vscode/launch-nrf52-pi.json
@@ -0,0 +1,62 @@
+{
+ // VSCode Debugger Config for Cortex Debug Extension. We use Cortex Debug because it shows more details, e.g. the nRF52 Peripherals.
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // Cortex Debug Configuration: https://marcelball.ca/projects/cortex-debug/cortex-debug-launch-configurations/
+ "name": "nRF52832",
+ "type": "cortex-debug",
+ "request": "launch",
+ // OpenOCD path is defined in workspace.code-workspace.
+ "servertype": "openocd",
+ "cwd": "${workspaceRoot}",
+ // Application Executable to be flashed before debugging. Note that the Application ELF image does not contain a valid Image Header, so we must install the Stub Bootloader.
+ "executable": "bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ // Uncomment one of these lines to debug MCUBoot or Stub Bootloader:
+ // "executable": "bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf",
+ // "executable": "bin/targets/nrf52_boot/app/apps/boot_stub/boot_stub.elf",
+ "device": "nRF52832",
+ // Arm System View Description, from apache-mynewt-core/hw/mcu/nordic/src/ext/nrfx/mdk
+ "svdFile": "scripts/nrf52/nrf52.svd",
+ "configFiles": [
+ // Tell OpenOCD to open the SPI connection to SWD Port on PineTime.
+ "scripts/nrf52-pi/swd-pi.ocd",
+ // Tell OpenOCD to run our custom debug commands.
+ "scripts/nrf52/debug.ocd"
+ ],
+ "preLaunchCommands": [
+ // Before loading the Application, run these gdb commands.
+ // Set timeout for executing openocd commands.
+ "set remotetimeout 60",
+
+ // This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
+ "set breakpoint pending on"
+
+ // Display the Arm instruction when hitting breakpoint.
+ // "display/i $pc",
+
+ // Load Bootloader symbols in case we jump to the Bootloader.
+ // "symbol-file bin/targets/bluepill_boot/app/apps/boot/boot.elf",
+
+ // Restore Application symbols.
+ // "symbol-file bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ ],
+ "postLaunchCommands": [
+ // After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
+ // If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
+ // "stepi", // Must step before setting PC
+ // "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
+ // "stepi", // Execute the Reset Handler
+ // "break os_default_irq", // Break for any Mynewt unhandled interrupts
+ // "break core::result::unwrap_failed", // Break for any Rust unwrap and expect failures
+ "break main", // Break at main()
+ "break __assert_func", // Break for any C assert failures
+ "break core::panicking::panic" // Break for any Rust assert failures and panics
+ ],
+ "preRestartCommands": [
+ ],
+ "postRestartCommands": [
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/launch-nrf52.json b/.vscode/launch-nrf52.json
new file mode 100644
index 0000000..1abdae4
--- /dev/null
+++ b/.vscode/launch-nrf52.json
@@ -0,0 +1,63 @@
+{
+ // VSCode Debugger Config for Cortex Debug Extension. We use Cortex Debug because it shows more details, e.g. the nRF52 Peripherals.
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // Cortex Debug Configuration: https://marcelball.ca/projects/cortex-debug/cortex-debug-launch-configurations/
+ "name": "nRF52832",
+ "type": "cortex-debug",
+ "request": "launch",
+ // OpenOCD path is defined in workspace.code-workspace.
+ "servertype": "openocd",
+ "cwd": "${workspaceRoot}",
+ // Application Executable to be flashed before debugging. Note that the Application ELF image does not contain a valid Image Header, so we must install the Stub Bootloader.
+ "executable": "bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ // Uncomment one of these lines to debug MCUBoot or Stub Bootloader:
+ // "executable": "bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf",
+ // "executable": "bin/targets/nrf52_boot/app/apps/boot_stub/boot_stub.elf",
+ "device": "nRF52832",
+ // Arm System View Description, from apache-mynewt-core/hw/mcu/nordic/src/ext/nrfx/mdk
+ "svdFile": "scripts/nrf52/nrf52.svd",
+ "configFiles": [
+ // Tell OpenOCD to open the ST Link connection to SWD Port on PineTime.
+ "interface/stlink-v2.cfg",
+ "target/nrf52.cfg",
+ // Tell OpenOCD to run our custom debug commands.
+ "scripts/nrf52/debug.ocd"
+ ],
+ "preLaunchCommands": [
+ // Before loading the Application, run these gdb commands.
+ // Set timeout for executing openocd commands.
+ "set remotetimeout 60",
+
+ // This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
+ "set breakpoint pending on"
+
+ // Display the Arm instruction when hitting breakpoint.
+ // "display/i $pc",
+
+ // Load Bootloader symbols in case we jump to the Bootloader.
+ // "symbol-file bin/targets/bluepill_boot/app/apps/boot/boot.elf",
+
+ // Restore Application symbols.
+ // "symbol-file bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ ],
+ "postLaunchCommands": [
+ // After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
+ // If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
+ // "stepi", // Must step before setting PC
+ // "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
+ // "stepi", // Execute the Reset Handler
+ // "break os_default_irq", // Break for any Mynewt unhandled interrupts
+ // "break core::result::unwrap_failed", // Break for any Rust unwrap and expect failures
+ "break main", // Break at main()
+ "break __assert_func", // Break for any C assert failures
+ "break core::panicking::panic" // Break for any Rust assert failures and panics
+ ],
+ "preRestartCommands": [
+ ],
+ "postRestartCommands": [
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/launch-stm32l4.json b/.vscode/launch-stm32l4.json
new file mode 100644
index 0000000..72e099b
--- /dev/null
+++ b/.vscode/launch-stm32l4.json
@@ -0,0 +1,45 @@
+{
+ // VSCode Debugger Config
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "GD32VF103",
+ "type": "gdb",
+ "request": "launch",
+ // Application Executable to be flashed to Blue Pill before debugging. Note that the Application ELF image does not contain a valid Image Header. So we must bypass the Bootloader, shown below.
+ "target": "${workspaceRoot}/bin/targets/gd32vf103c-start_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ // For Bootloader: "target": "${workspaceRoot}/bin/targets/gd32vf103c-start_boot/app/apps/boot_stub/boot_stub.elf",
+ "cwd": "${workspaceRoot}",
+ "gdbpath": "${workspaceRoot}/xPacks/riscv-none-embed-gcc/8.2.0-3.1/bin/riscv-none-embed-gdb",
+ "valuesFormatting": "parseText",
+ "autorun": [
+ // Before loading the Application, run these gdb commands.
+ // Set the architecture to 32-bit RISC-V.
+ "set arch riscv:rv32",
+
+ // Set timeout for executing openocd commands.
+ "set remotetimeout 600",
+
+ // This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
+ "set breakpoint pending on",
+
+ // Set breakpoints
+ "break main", // Break at main()
+ "break __assert_func", // Break for any assert failures
+ "break os_default_irq", // Break for any unhandled interrupts
+
+ // Launch OpenOCD. Based on https://www.justinmklam.com/posts/2017/10/vscode-debugger-setup/
+ "target remote | riscv-openocd/src/openocd -s riscv-openocd/tcl -c \"gdb_port pipe; log_output openocd.log\" -f scripts/gd32vf103/flash-init.ocd -f interface/cmsis-dap.cfg -f scripts/gd32vf103/gd32vf103.ocd -f scripts/gd32vf103/debug.ocd ",
+
+ // After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
+ ////"monitor reset halt", // Restart and halt
+ ////"flushregs", // Flush the register cache
+
+ // If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
+ // "stepi", // Must step before setting PC
+ // "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
+ // "stepi", // Execute the Reset Handler
+ ]
+ }
+ ]
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..1abdae4
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,63 @@
+{
+ // VSCode Debugger Config for Cortex Debug Extension. We use Cortex Debug because it shows more details, e.g. the nRF52 Peripherals.
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // Cortex Debug Configuration: https://marcelball.ca/projects/cortex-debug/cortex-debug-launch-configurations/
+ "name": "nRF52832",
+ "type": "cortex-debug",
+ "request": "launch",
+ // OpenOCD path is defined in workspace.code-workspace.
+ "servertype": "openocd",
+ "cwd": "${workspaceRoot}",
+ // Application Executable to be flashed before debugging. Note that the Application ELF image does not contain a valid Image Header, so we must install the Stub Bootloader.
+ "executable": "bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ // Uncomment one of these lines to debug MCUBoot or Stub Bootloader:
+ // "executable": "bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf",
+ // "executable": "bin/targets/nrf52_boot/app/apps/boot_stub/boot_stub.elf",
+ "device": "nRF52832",
+ // Arm System View Description, from apache-mynewt-core/hw/mcu/nordic/src/ext/nrfx/mdk
+ "svdFile": "scripts/nrf52/nrf52.svd",
+ "configFiles": [
+ // Tell OpenOCD to open the ST Link connection to SWD Port on PineTime.
+ "interface/stlink-v2.cfg",
+ "target/nrf52.cfg",
+ // Tell OpenOCD to run our custom debug commands.
+ "scripts/nrf52/debug.ocd"
+ ],
+ "preLaunchCommands": [
+ // Before loading the Application, run these gdb commands.
+ // Set timeout for executing openocd commands.
+ "set remotetimeout 60",
+
+ // This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
+ "set breakpoint pending on"
+
+ // Display the Arm instruction when hitting breakpoint.
+ // "display/i $pc",
+
+ // Load Bootloader symbols in case we jump to the Bootloader.
+ // "symbol-file bin/targets/bluepill_boot/app/apps/boot/boot.elf",
+
+ // Restore Application symbols.
+ // "symbol-file bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
+ ],
+ "postLaunchCommands": [
+ // After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
+ // If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
+ // "stepi", // Must step before setting PC
+ // "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
+ // "stepi", // Execute the Reset Handler
+ // "break os_default_irq", // Break for any Mynewt unhandled interrupts
+ // "break core::result::unwrap_failed", // Break for any Rust unwrap and expect failures
+ "break main", // Break at main()
+ "break __assert_func", // Break for any C assert failures
+ "break core::panicking::panic" // Break for any Rust assert failures and panics
+ ],
+ "preRestartCommands": [
+ ],
+ "postRestartCommands": [
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c1c4e66
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,22 @@
+{
+ // Path of OpenOCD excecutable
+ "cortex-debug.openocdPath": "openocd/bin/openocd",
+ // Exclude these files from VSCode change watcher because Raspberry Pi shows "unable to watch for file changes in this large workspace"
+ "files.watcherExclude": {
+ "**/.git/objects/**": true,
+ "**/.git/subtree-cache/**": true,
+ "**/bin/**": true,
+ "**/logs/**": true,
+ "**/newt/**": true,
+ "**/openocd/**": true,
+ "**/target/**": true,
+ "**/targets/**": true,
+ "**/tmprustlib/**": true,
+ "**/rust/druid-embedded/**": true,
+ "**/rust/kurbo-embedded/**": true,
+ "**/rust/piet-embedded/**": true,
+ "**/rust/st7735-lcd-batch-rs/**": true
+ },
+ // Disable minimap
+ "editor.minimap.enabled": false
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..eb53820
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,381 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ // Build the Bootloader.
+ "label": "1️⃣ Build Bootloader",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " scripts\\nrf52\\build-boot.cmd && echo ✅ ◾ ️Done! "
+ ]
+ },
+ "osx": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/build-boot.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "linux": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/build-boot.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Build the Application.
+ "label": "2️⃣ Build Application",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " scripts\\build-app.cmd && echo ✅ ◾ ️Done! "
+ ]
+ },
+ "osx": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/build-app.sh && cp .vscode/launch-nrf52.json .vscode/launch.json && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "linux": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/build-app.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": [
+ {
+ // Problem matcher for GNU Linker, e.g. /Users/Luppy/mynewt/stm32bluepill-mynewt-sensor/apps/my_sensor_app/src/ATParser.h:82: undefined reference to `operator delete[](void*)'
+ "fileLocation": [ "absolute" ],
+ "pattern": {
+ "regexp": "^(/.*):(\\d+):\\s+(.*)$",
+ "file": 1,
+ "line": 2,
+ "message": 3,
+ // "code": 3,
+ // "severity": 4,
+ }
+ }
+ ],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Create the Application ROM Image.
+ "label": "3️⃣ Image Application",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " scripts\\nrf52\\image-app.cmd && echo ✅ ◾ ️Done! "
+ ]
+ },
+ "osx": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/image-app.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "linux": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/image-app.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Flash the Bootloader. We use custom scripts instead of "newt load" because "newt" runs in Ubuntu while the ST Link driver runs under Windows.
+ "label": "4️⃣ Flash Bootloader",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " scripts\\nrf52\\flash-boot.cmd && echo ✅ ◾ ️Done! "
+ ]
+ },
+ "osx": {
+ // Previously: " newt load -v bluepill_boot && echo '**** Done!' "
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/flash-boot.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "linux": {
+ // Previously: " newt load -v bluepill_boot && echo '**** Done!' "
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/flash-boot.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Flash the Application. We use custom scripts instead of "newt load" because "newt" runs in Ubuntu while the ST Link driver runs under Windows.
+ "label": "5️⃣ Flash Application",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " scripts\\nrf52\\flash-app.cmd && echo ✅ ◾ ️Done! "
+ ]
+ },
+ "osx": {
+ // Previously: " newt load -v bluepill_my_sensor && echo '**** Done!' "
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/flash-app.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "linux": {
+ // Previously: " newt load -v bluepill_my_sensor && echo '**** Done!' "
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/flash-app.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Erase the Flash ROM
+ "label": "⚡️ Erase Flash",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " scripts\\nrf52\\flash-erase.cmd && echo ✅ ◾ ️Done! "
+ ]
+ },
+ "osx": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/flash-erase.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "linux": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/nrf52/flash-erase.sh && echo ✅ ◾ ️Done! "
+ ],
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Generate Rust bindings for C libraries.
+ "label": "⛓ Generate Rust Bindings",
+ "type": "shell",
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " set -e -x ; ./scripts/gen-bindings.sh ; ./scripts/gen-bindings-lvgl.sh ; echo ✅ ◾ ️Done! "
+ ],
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Build Rust library with macros expanded, output to logs/libmylib-expanded.rs.
+ "label": "👓 Expand Rust Macros",
+ "type": "shell",
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " set -e -x ; ./scripts/build-rustlib.sh ; echo ✅ ◾ ️Done! "
+ ],
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Generate documentation.
+ "label": "📖 Generate Doc",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " cargo doc --document-private-items && echo ✅ ◾ ️Done! target/thumbv7m-none-eabi/doc "
+ ]
+ },
+ "osx": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " article=handdrawn ; set -e -x ; cat scripts/articles/$article-header.html scripts/rustdoc-header.html >article-rustdoc-header.html ; rustdoc --output docs/articles --html-in-header article-rustdoc-header.html --html-before-content scripts/rustdoc-before.html rust/app/src/$article.md ; cargo doc --document-private-items ; echo ✅ ◾ ️Done! target/thumbv7m-none-eabi/doc "
+ ]
+ },
+ "linux": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " set -e -x ; cargo doc --document-private-items ; echo ✅ ◾ ️Done! target/thumbv7m-none-eabi/doc "
+ ]
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Remove all compiled files.
+ "label": "🗑 Clean",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " newt\\newt.exe clean -v all && rd /q /s target && echo ✅ ◾ ️Done!"
+ ]
+ },
+ "osx": {
+ // Previously: " newt load -v bluepill_my_sensor && echo '**** Done!' "
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " newt clean -v all && rm -r target ; echo ✅ ◾ ️Done! "
+ ],
+ },
+ "linux": {
+ // Previously: " newt load -v bluepill_my_sensor && echo '**** Done!' "
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " newt clean -v all && rm -r target ; echo ✅ ◾ ️Done! "
+ ],
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Install Mynewt source, build tools, sample.
+ "label": "Install Mynewt",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " echo Done! Please restart Visual Studio Code to activate the extensions"
+ ]
+ },
+ "osx": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/install-mac.sh "
+ ]
+ },
+ "linux": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " scripts/install-linux.sh "
+ ]
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ {
+ // Prompt the user to restart.
+ "label": "Prompt Restart",
+ "type": "shell",
+ "windows": {
+ "command": "cmd",
+ "args": [
+ "/c",
+ " echo Done! Please restart Visual Studio Code to activate the extensions "
+ ]
+ },
+ "osx": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " echo Done! Please restart Visual Studio Code to activate the extensions "
+ ]
+ },
+ "linux": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " echo Done! Please restart Visual Studio Code to activate the extensions "
+ ]
+ },
+ "problemMatcher": [],
+ "presentation": {
+ "clear": true
+ }
+ },
+ /* For debug we now use the Cortex Debug Extension.
+ {
+ "label": "💣 Debug bluepill_my_sensor",
+ "type": "shell",
+ "windows": {
+ "command": "bash",
+ "args": [
+ "-c", "-l",
+ " newt debug -v bluepill_my_sensor ",
+ // "-n",
+ ]
+ },
+ "osx": {
+ "command":
+ " newt debug -v bluepill_my_sensor "
+ },
+ "linux": {
+ "command":
+ " newt debug -v bluepill_my_sensor "
+ },
+ "problemMatcher": [
+ ]
+ },
+ */
+ ]
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..4ba7354
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,8 @@
+Apache Mynewt
+Copyright 2015-2017 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of this software were developed at
+Runtime Inc, copyright 2015.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..dd5b55b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,892 @@
+
+
+# PineTime Smart Watch Firmware with Apache Mynewt and Embedded Rust
+
+![PineTime Smart Watch with Apache Mynewt and Embedded Rust](https://lupyuen.github.io/images/pinetime-title.jpg)
+
+This `master` branch of `pinetime-rust-mynewt` contains the firmware source code for PineTime Smart Watch with...
+
+1. [Apache Mynewt 1.7](https://mynewt.apache.org/), [Apache NimBLE 1.2](https://github.com/apache/mynewt-nimble) and [Embedded Rust (nightly build)](https://www.rust-lang.org/)
+
+1. [MCUBoot Bootloader 1.5](https://juullabs-oss.github.io/mcuboot/)
+
+`pinetime-rust-mynewt` is an Educational Embedded OS that supports...
+
+1. Wireless Firmware Updates over Bluetooth LE, based on MCU Manager's Simple Management Protocol
+
+1. LVGL UI Library Version 7, based on [`pinetime_lvgl_mynewt`](https://gitlab.com/lupyuen/pinetime_lvgl_mynewt)
+
+1. Time Sync with Bluetooth LE Current Time Service
+
+1. Rust Watch Faces from crates.io
+
+This branch no longer supports `druid`, `embedded-graphics` and Visual Rust. Check out the older version in the [`pre-lvgl`](https://github.com/lupyuen/pinetime-rust-mynewt/tree/pre-lvgl) branch.
+
+Refer to the articles...
+
+1. [_PineTime doesn't run Linux... But that's OK!_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/pinetime)
+
+1. [_Create Your Own PineTime Watch Face in Rust... And Publish on crates.io_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/watchface)
+
+1. [_Bluetooth Time Sync and LVGL on PineTime Mynewt_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/timesync)
+
+1. [_Firmware Update over Bluetooth Low Energy on PineTime Smart Watch_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/dfu)
+
+1. [_Configure Mynewt for SPI Flash on PineTime Smart Watch (nRF52)_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/spiflash)
+
+1. [_MCUBoot Bootloader for PineTime Smart Watch (nRF52)_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/mcuboot)
+
+1. [_Wireless Firmware Update In Action on PineTime Smart Watch (nRF52)_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/dfutest)
+
+1. [_Your First Bluetooth Low Energy App with Flutter_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/flutter)
+
+1. [_Convert Go to Flutter and Dart for PineTime Companion App_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/companion)
+
+1. [_Your First GTK App with Go and VSCodium_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/gotk3)
+
+1. [_Flutter State Management with Bloc for PineTime Companion App_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/bloc)
+
+1. [_Auto Convert Go to Dart with an Abstract Syntax Tree_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/ast)
+
+1. [_My First Week As Embedded FOSS Advocate_](https://medium.com/@ly.lee/my-first-week-as-embedded-foss-advocate-106d625deae?source=friends_link&sk=4128d2bb8a7098658fafc462a1531d34)
+
+1. [_Rust Documentation_](https://lupyuen.github.io/pinetime-rust-mynewt/?1)
+
+The following articles were written for the older version of this firmware. Refer to the [`pre-lvgl`](https://github.com/lupyuen/pinetime-rust-mynewt/tree/pre-lvgl) branch for the source code...
+
+1. [_Visual Rust for PineTime Smart Watch_](https://marketplace.visualstudio.com/items?itemName=LeeLupYuen.visual-embedded-rust)
+
+1. [_Build and Flash Rust+Mynewt Firmware for PineTime Smart Watch_](https://medium.com/@ly.lee/build-and-flash-rust-mynewt-firmware-for-pinetime-smart-watch-5e14259c55?source=friends_link&sk=150b2a73b84144e5ef25b985e65aebe9)
+
+1. [_Debug Rust+Mynewt Firmware for PineTime on Raspberry Pi_](https://medium.com/@ly.lee/debug-rust-mynewt-firmware-for-pinetime-on-raspberry-pi-4b9ac2d093a9?source=friends_link&sk=edb508c31e43d3ec40ecd8554f3405f6)
+
+1. [_Sneak Peek of PineTime Smart Watch… And why it's perfect for teaching IoT_](https://medium.com/swlh/sneak-peek-of-pinetime-smart-watch-and-why-its-perfect-for-teaching-iot-81b74161c159?source=friends_link&sk=d9301466f5499bece3e7b638e99ec20d)
+
+1. [_Building a Rust Driver for PineTime’s Touch Controller_](https://medium.com/@ly.lee/building-a-rust-driver-for-pinetimes-touch-controller-cbc1a5d5d3e9?source=friends_link&sk=d8cf73fc943d9c0e960627d768f309cb)
+
+1. [_Porting [druid] Rust Widgets to PineTime Smart Watch_](https://medium.com/@ly.lee/porting-druid-rust-widgets-to-pinetime-smart-watch-7e1d5a5d977a?source=friends_link&sk=09b153c68483f7fa9e63350efd167b07)
+
+1. [_Optimising PineTime’s Display Driver with Rust and Mynewt_](https://medium.com/@ly.lee/optimising-pinetimes-display-driver-with-rust-and-mynewt-3ba269ea2f5c?source=friends_link&sk=4d2cbd2e6cd2343eed62d214814f7b81)
+
+1. [_OpenOCD on Raspberry Pi: Better with SWD on SPI_](https://medium.com/@ly.lee/openocd-on-raspberry-pi-better-with-swd-on-spi-7dea9caeb590?source=friends_link&sk=df399bfd913d3e262447d28aa5af6b63)
+
+1. [_CHIP-8 Game Emulator in Rust for PineTime Smart Watch_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/chip8)
+
+1. [_Porting MicroPython and wasp-os to Mynewt on PineTime Smart Watch (nRF52)_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/micropython)
+
+The firmware design is similar to this earlier article on nRF52...
+
+[_Coding nRF52 with Rust and Apache Mynewt on Visual Studio Code_](https://medium.com/@ly.lee/coding-nrf52-with-rust-and-apache-mynewt-on-visual-studio-code-9521bcba6004?source=friends_link&sk=bb4e2523b922d0870259ab3fa696c7da)
+
+[More Articles](https://lupyuen.github.io)
+
+[RSS Feed](https://lupyuen.github.io/rss.xml)
+
+# Automated Build with GitHub Actions
+
+The MCUBoot Bootloader and Rust + Mynewt Firmware are built automatically in the GitHub Cloud.
+
+Just fork this repo, update the source code and the built firmware will be available for download under "Actions".
+
+The Automated Build is performed according to the following GitHub Actions Workflow...
+
+[`.github/workflows/main.yml`](.github/workflows/main.yml)
+
+The Worklow is similar to the one described in this article...
+
+[_Build PineTime Firmware in the Cloud with GitHub Actions_](https://lupyuen.github.io/pinetime-rust-mynewt/articles/cloud)
+
+# Automated Build with GitLab CI
+
+The MCUBoot Bootloader and Rust + Mynewt Firmware are also built automatically with GitLab CI.
+
+This repo is mirrored to GitLab as...
+
+[`gitlab.com/lupyuen/pinetime-rust-mynewt`](https://gitlab.com/lupyuen/pinetime-rust-mynewt)
+
+The GitLab CI Workflow is at [`.gitlab-ci.yml`](https://gitlab.com/lupyuen/pinetime-rust-mynewt/-/blob/master/.gitlab-ci.yml)
+
+# Build Instructions
+
+If you are building from this repository from scratch instead of the Released Packages, here are the steps for Linux (x64, Arm32 and Arm64, including Raspberry Pi), macOS and Windows (no need for WSL, MinGW and Docker)...
+
+## Install Build Tools
+
+1. Download and extract [xPack OpenOCD](https://xpack.github.io/openocd/install/). Other versions of OpenOCD are known to have problems flashing with ST-Link.
+
+ - [xPack OpenOCD for Linux x64](https://github.com/xpack-dev-tools/openocd-xpack/releases/download/v0.10.0-15/xpack-openocd-0.10.0-15-linux-x64.tar.gz)
+
+ - [xPack OpenOCD for Linux Arm32](https://github.com/xpack-dev-tools/openocd-xpack/releases/download/v0.10.0-15/xpack-openocd-0.10.0-15-linux-arm.tar.gz)
+
+ - [xPack OpenOCD for Linux Arm64](https://github.com/xpack-dev-tools/openocd-xpack/releases/download/v0.10.0-15/xpack-openocd-0.10.0-15-linux-arm64.tar.gz)
+
+ - [xPack OpenOCD for macOS](https://github.com/xpack-dev-tools/openocd-xpack/releases/download/v0.10.0-15/xpack-openocd-0.10.0-15-darwin-x64.tar.gz)
+
+ - [xPack OpenOCD for Windows x64](https://github.com/xpack-dev-tools/openocd-xpack/releases/download/v0.10.0-15/xpack-openocd-0.10.0-15-win32-x64.zip)
+
+ __For Linux with ST-Link (not Raspberry Pi):__ Download and extract xPack OpenOCD from above. Then install the ST-Link driver as follows...
+
+ ```bash
+ # For Linux Only: Install UDEV Rules according to https://xpack.github.io/openocd/install/#udev
+ if [ -d /etc/udev/rules.d ]; then
+ sudo cp xpack-openocd/contrib/60-openocd.rules /etc/udev/rules.d/
+ sudo udevadm control --reload-rules
+ fi
+ ```
+
+ __For Windows:__ Download and extract xPack OpenOCD from above. Then install the ST-Link v2 Driver for Windows...
+
+ - Download the ST-Link USB driver from [ST-Link Driver Website](https://www.st.com/en/development-tools/stsw-link009.html) (email registration required)
+
+ - Click `Get Software`
+
+ - Unzip the downloaded file. Double-click the driver installer: `dpinst_amd64.exe`
+
+ __For Raspberry Pi:__ Install `openocd-spi` according to the instructions here...
+
+ [_"OpenOCD on Raspberry Pi: Better with SWD on SPI"_](https://medium.com/@ly.lee/openocd-on-raspberry-pi-better-with-swd-on-spi-7dea9caeb590?source=friends_link&sk=df399bfd913d3e262447d28aa5af6b63)
+
+1. Download the [Arm Embedded Toolchain 9-2020-q2-update](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). Other versions of the toolchain are known to have problems building the firmware.
+
+ - [Embedded Toolchain for Linux x64](https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2?revision=05382cca-1721-44e1-ae19-1e7c3dc96118&la=en&hash=D7C9D18FCA2DD9F894FD9F3C3DC9228498FA281A)
+
+ - [Embedded Toolchain for Linux Arm32](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/install-pi.sh#L30-L41) (install via `apt`)
+
+ - [Embedded Toolchain for Linux Arm64](https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-aarch64-linux.tar.bz2?revision=7166404a-b4f5-4598-ac75-e5f8b90abb09&la=en&hash=01D713C1174E80C856385F5732E9BDC466DB729B)
+
+ - [Embedded Toolchain for macOS](https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-mac.tar.bz2?revision=d0d318de-b746-489f-98b0-9d89648ce910&la=en&hash=9E035CEF6261AA1387D3DCC8B86FA1A20E92B9AB)
+
+ - [Embedded Toolchain for Windows](https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-win32.exe?revision=50c95fb2-67ca-4df7-929b-55396266b4a1&la=en&hash=DE1CD6E7A15046FD1ADAF828EA4FA82228E682E2)
+
+ __For Linux and macOS:__ Unzip the toolchain and add it to your PATH
+
+ __For Windows:__ Run the installer and check the option for `Add to PATH`
+
+1. Install `rustup` with support for nightly target `thumbv7em-none-eabihf`.
+
+ Follow the instructions at https://rustup.rs/
+
+ Press Enter to select `1) Proceed with installation (default)`
+
+ __For Linux and macOS:__ Open a command prompt and enter...
+
+ ```bash
+ source $HOME/.cargo/env
+ rustup update
+ rustup default nightly
+ rustup target add thumbv7em-none-eabihf
+ ```
+
+ __For Windows:__ Enter the above commands in a Windows Command Prompt (not WSL Terminal). Omit the `source` line.
+
+1. __For Linux and macOS:__ Install the `newt` build tool for Mynewt. Refer to these scripts...
+
+ - [`scripts/install-version.sh`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/install-version.sh): To set the version numbers
+
+ - [`scripts/install-pi.sh`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/install-pi.sh): To build and install `newt`, look under the section `"Build newt"`
+
+ __For Windows:__ The `newt` tool has been prebuilt at `pinetime-rust-mynewt/newt/newt.exe`
+
+## Download Source Files
+
+1. Download the source files to `~/pinetime`...
+
+ __For Linux and macOS:__
+
+ ```bash
+ mkdir ~/pinetime
+ cd ~/pinetime
+ git clone --recursive https://github.com/lupyuen/pinetime-rust-mynewt
+ ```
+
+ __For Windows:__
+
+ ```cmd
+ cd \
+ mkdir pinetime
+ cd pinetime
+ git clone --recursive https://github.com/lupyuen/pinetime-rust-mynewt
+ ```
+
+1. Update the MCUBoot version number to 1.3.1. Edit [`pinetime/pinetime-rust-mynewt/project.yml`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/project.yml)
+
+ Change...
+
+ ```yaml
+ repository.mcuboot:
+ type: github
+ vers: 1.5.0
+ ```
+
+ to...
+
+ ```yaml
+ repository.mcuboot:
+ type: github
+ vers: 1.3.1
+ ```
+
+1. Download the source code for Mynewt, NimBLE and MCUBoot...
+
+ __For Linux and macOS:__
+
+ ```bash
+ cd ~/pinetime/pinetime-rust-mynewt
+ newt install
+ ```
+
+ We should see...
+
+ ```
+ Downloading repository mynewt-core (commit: master) from https://github.com/apache/mynewt-core.git
+ Downloading repository mynewt-mcumgr (commit: master) from https://github.com/apache/mynewt-mcumgr.git
+ Downloading repository mynewt-nimble (commit: master) from https://github.com/apache/mynewt-nimble.git
+ Downloading repository mcuboot (commit: master) from https://github.com/JuulLabs-OSS/mcuboot.git
+ Making the following changes to the project:
+ install apache-mynewt-core (1.7.0)
+ install apache-mynewt-nimble (1.2.0)
+ install mcuboot (1.3.1)
+ apache-mynewt-core successfully installed version 1.7.0
+ apache-mynewt-nimble successfully installed version 1.2.0
+ Error: Error updating "mcuboot": error: The following untracked working tree files would be overwritten by checkout:
+ ext/mbedtls/include/mbedtls/check_config.h
+ ext/mbedtls/include/mbedtls/config.h
+ Please move or remove them before you switch branches.
+ Aborting
+ ```
+
+ Ignore the `mcuboot` error above and proceed to the next step.
+
+ __For Windows:__
+
+ ```cmd
+ cd \pinetime\pinetime-rust-mynewt
+ mkdir repos
+ xcopy /s patch\repos-windows repos
+ cd repos
+ git clone --recursive --branch mynewt_1_7_0_tag https://github.com/apache/mynewt-core.git apache-mynewt-core
+ git clone --recursive --branch nimble_1_2_0_tag https://github.com/apache/mynewt-nimble.git apache-mynewt-nimble
+ ```
+
+1. Restore the MCUBoot version number to 1.5.0. Edit [`pinetime/pinetime-rust-mynewt/project.yml`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/project.yml)
+
+ Change...
+
+ ```yaml
+ repository.mcuboot:
+ type: github
+ vers: 1.3.1
+ ```
+
+ to...
+
+ ```yaml
+ repository.mcuboot:
+ type: github
+ vers: 1.5.0
+ ```
+
+1. Download version 1.5.0 of MCUBoot to `repos/mcuboot`
+
+ __For Linux and macOS:__
+
+ ```bash
+ cd ~/pinetime/pinetime-rust-mynewt/repos
+ rm -rf mcuboot
+ git clone --recursive --branch v1.5.0 https://github.com/JuulLabs-OSS/mcuboot
+ ```
+
+ __For Windows:__
+
+ ```cmd
+ cd \pinetime\pinetime-rust-mynewt\repos
+ git clone --recursive --branch v1.5.0 https://github.com/JuulLabs-OSS/mcuboot
+ ```
+
+ Why are we doing this? Because we are using a more recent version of MCUBoot (1.5.0), but that's not in sync with the older Mynewt version (1.7.0). This will cause `newt install` to fail. Hence we do this workaround to force Mynewt to build with the newer MCUBoot.
+
+1. Copy the unzipped OpenOCD from [xPack OpenOCD](https://xpack.github.io/openocd/install/) or `openocd-spi` to the folder...
+
+ ```
+ pinetime/pinetime-rust-mynewt/openocd
+ ```
+
+ The `openocd` executable should be located at `pinetime/pinetime-rust-mynewt/openocd/bin/openocd`
+
+## Build MCUBoot Bootloader
+
+Build the MCUBoot Bootloader...
+
+__For Linux and macOS:__
+
+```bash
+cd ~/pinetime/pinetime-rust-mynewt
+scripts/nrf52/build-boot.sh
+```
+
+__For Windows:__
+
+```cmd
+cd \pinetime\pinetime-rust-mynewt
+scripts\nrf52\build-boot.cmd
+```
+
+We should see...
+
+```
+Linking pinetime/pinetime-rust-mynewt/pinetime-rust-mynewt/bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf
+Target successfully built: targets/nrf52_boot
++ newt size -v nrf52_boot
+Size of Application Image: app
+Mem FLASH: 0x0-0x7000
+Mem RAM: 0x20000000-0x20010000
+ FLASH RAM
+ 97 230 *fill*
+ 756 0 libgcc.a
+ 6959 5996 boot_bootutil.a
+ 124 0 boot_mynewt.a
+ 18 0 boot_mynewt_flash_map_backend.a
+ 1182 0 crypto_mbedtls.a
+ 392 444 hw_bsp_nrf52.a
+ 52 0 hw_cmsis-core.a
+ 1280 80 hw_drivers_flash_spiflash.a
+ 654 1 hw_hal.a
+ 4236 72 hw_mcu_nordic_nrf52xxx.a
+ 1570 18772 kernel_os.a
+ 2138 12 libc_baselibc.a
+ 2049 260 libs_pinetime_boot.a
+ 297 39 libs_semihosting_console.a
+ 796 128 sys_flash_map.a
+ 2 0 sys_log_modlog.a
+ 632 29 sys_mfg.a
+ 30 5 sys_sysinit.a
+ 48 0 util_mem.a
+ 100 0 nrf52_boot-sysinit-app.a
+Loading compiler pinetime/pinetime-rust-mynewt/pinetime-rust-mynewt/repos/apache-mynewt-core/compiler/arm-none-eabi-m4, buildProfile debug
+
+objsize
+ text data bss dec hex filename
+ 23220 136 25500 48856 bed8 pinetime/pinetime-rust-mynewt/pinetime-rust-mynewt/bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf
+```
+
+This produces the MCUBoot Bootloader that we will flash to PineTime later...
+
+```
+pinetime/pinetime-rust-mynewt/bin/targets/nrf52_boot/app/boot/mynewt/mynewt.bin
+```
+
+## Build Application Firmware
+
+1. Build the Application Firmware...
+
+ __For Linux and macOS:__
+
+ ```bash
+ cd ~/pinetime/pinetime-rust-mynewt
+ scripts/build-app.sh
+ ```
+
+ __For Windows:__
+
+ ```cmd
+ cd \pinetime\pinetime-rust-mynewt
+ scripts\build-app.cmd
+ ```
+
+ If we see the error...
+
+ ```
+ pinetime/pinetime-rust-mynewt/repos/apache-mynewt-core/libc/baselibc/src/start.c:39:
+ undefined reference to `main'
+ ```
+
+ Run `build-app` again. It should fix the error.
+
+ When the Application Firmware build succeds, we should see...
+
+ ```
+ Linking pinetime/pinetime-rust-mynewt/pinetime-rust-mynewt/bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf
+ Target successfully built: targets/nrf52_my_sensor
+ + newt size -v nrf52_my_sensor
+ Warning: 6 02:26:22.562 [WARNING] Transient package @apache-mynewt-core/mgmt/newtmgr/transport/ble used, update configuration to use linked package instead (@apache-mynewt-core/mgmt/smp/transport/ble)
+ Warning: 6 02:26:22.562 [WARNING] Transient package @apache-mynewt-core/mgmt/newtmgr used, update configuration to use linked package instead (@apache-mynewt-core/mgmt/smp)
+ Size of Application Image: app
+ Mem FLASH: 0x8000-0x7bc00
+ Mem RAM: 0x20000000-0x20010000
+ FLASH RAM
+ 655 368 *fill*
+ 4829 2414 apps_my_sensor_app.a
+ 962 4 boot_bootutil.a
+ 181 38 boot_split.a
+ 1814 0 cborattr.a
+ 2371 72 cmd_img_mgmt.a
+ 1113 0 cmd_img_mgmt_port_mynewt.a
+ 723 12 cmd_os_mgmt.a
+ 222 32 cmd_os_mgmt_port_mynewt.a
+ 2408 0 crypto_tinycrypt.a
+ 619 0 encoding_base64.a
+ 3162 0 encoding_tinycbor.a
+ 452 444 hw_bsp_nrf52.a
+ 52 0 hw_cmsis-core.a
+ 1530 92 hw_drivers_flash_spiflash.a
+ 706 1 hw_hal.a
+ 5992 89 hw_mcu_nordic_nrf52xxx.a
+ 2 0 hw_sensor_creator.a
+ 1266 256 hw_sensor.a
+ 9098 27505 kernel_os.a
+ 3302 50 libc_baselibc.a
+ 16 0 libs_mynewt_rust.a
+ 161547 9868 libs_pinetime_lvgl_mynewt.a
+ 33248 105 libs_rust_app.a
+ 405 39 libs_semihosting_console.a
+ 737 212 libs_temp_stub.a
+ 376 12 mgmt_imgmgr.a
+ 413 12 mgmt.a
+ 490 4 mgmt_smp.a
+ 486 126 mgmt_smp_transport_ble.a
+ 35492 2152 nimble_controller.a
+ 4150 1203 nimble_drivers_nrf52.a
+ 44674 2713 nimble_host.a
+ 874 218 nimble_host_services_ans.a
+ 277 112 nimble_host_services_dis.a
+ 468 118 nimble_host_services_gap.a
+ 252 62 nimble_host_services_gatt.a
+ 1818 652 nimble_host_store_config.a
+ 108 0 nimble_host_util.a
+ 788 1096 nimble_transport_ram.a
+ 776 0 smp.a
+ 1357 42 sys_config.a
+ 794 128 sys_flash_map.a
+ 2 0 sys_log_modlog.a
+ 668 29 sys_mfg.a
+ 1395 67 sys_reboot.a
+ 30 5 sys_sysinit.a
+ 1200 0 time_datetime.a
+ 120 0 util_mem.a
+ 500 0 util_scfg.a
+ 124 0 util.a
+ 180 0 nrf52_my_sensor-sysinit-app.a
+ Loading compiler pinetime/pinetime-rust-mynewt/pinetime-rust-mynewt/repos/apache-mynewt-core/compiler/arm-none-eabi-m4, buildProfile debug
+
+ objsize
+ text data bss dec hex filename
+ 335072 1132 48820 385024 5e000 pinetime/pinetime-rust-mynewt/pinetime-rust-mynewt/bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf
+ ```
+
+1. Create the application firmware image...
+
+ __For Linux and macOS:__
+
+ ```bash
+ cd ~/pinetime/pinetime-rust-mynewt
+ scripts/nrf52/image-app.sh
+ ```
+
+ __For Windows:__
+
+ ```cmd
+ cd \pinetime\pinetime-rust-mynewt
+ scripts\nrf52\image-app.cmd
+ ```
+
+ We should see...
+
+ ```
+ App image successfully generated:
+ pinetime/pinetime-rust-mynewt/bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.img
+ ```
+
+1. This produces the application firmware image that we will flash to PineTime later...
+
+ ```
+ pinetime/pinetime-rust-mynewt/bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.img
+ ```
+
+## Select the OpenOCD Interface: ST-Link or Raspberry Pi SPI
+
+Edit [`pinetime/pinetime-rust-mynewt/scripts/config.sh`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/config.sh)
+
+If we're using ST-Link v2 for flashing PineTime, set `swd_device` as follows...
+
+```bash
+# Select ST-Link v2 as SWD Programmer
+swd_device=scripts/nrf52/swd-stlink.ocd
+```
+
+If we're using [Raspberry Pi SPI](https://medium.com/@ly.lee/openocd-on-raspberry-pi-better-with-swd-on-spi-7dea9caeb590?source=friends_link&sk=df399bfd913d3e262447d28aa5af6b63) for flashing PineTime, set `swd_device` as follows...
+
+```bash
+# Select Raspberry Pi as SWD Programmer
+swd_device=scripts/nrf52-pi/swd-pi.ocd
+```
+
+__For Windows:__ We don't need to edit `config.sh`
+
+## Flash MCUBoot Bootloader
+
+1. __For Linux and macOS:__ Edit [`pinetime/pinetime-rust-mynewt/scripts/nrf52/flash-boot.sh`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/nrf52/flash-boot.sh)
+
+ __For Windows:__ Edit [`pinetime/pinetime-rust-mynewt/scripts/nrf52/flash-boot.cmd`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/nrf52/flash-boot.cmd)
+
+1. Change `openocd/bin/openocd` to the path of our installed `openocd` (for ST-Link) or `openocd-spi` (for Raspberry Pi)...
+
+ ```bash
+ # Flash the device
+ openocd/bin/openocd \
+ -f $swd_device \
+ -f scripts/nrf52/flash-boot.ocd
+ ```
+
+1. The path of the built firmware file is defined in [`pinetime/pinetime-rust-mynewt/scripts/nrf52/flash-boot.ocd`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/nrf52/flash-boot.ocd). We shouldn't need to change this.
+
+ ```
+ # For MCUBoot (debugging not supported):
+ program bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf.bin verify 0x00000000
+ ```
+
+1. Flash the bootloader...
+
+ __For Linux and macOS:__
+
+ ```bash
+ cd ~/pinetime/pinetime-rust-mynewt
+ scripts/nrf52/flash-boot.sh
+ ```
+
+ __For Windows:__
+
+ ```cmd
+ cd \pinetime\pinetime-rust-mynewt
+ scripts\nrf52\flash-boot.cmd
+ ```
+
+1. We should see...
+
+ ```
+ > Executing task in folder pinetime-rust-mynewt: bash -c -l ' scripts/nrf52/flash-boot.sh && echo ✅ ◾ ️Done! ' <
+
+ + source scripts/config.sh
+ ++ swd_device=scripts/nrf52/swd-stlink.ocd
+ + openocd/bin/openocd -f scripts/nrf52/swd-stlink.ocd -f scripts/nrf52/flash-boot.ocd
+ GNU MCU Eclipse 64-bit Open On-Chip Debugger 0.10.0+dev-00462-gdd1d90111 (2019-01-15-13:49)
+ Licensed under GNU GPL v2
+ For bug reports, read
+ http://openocd.org/doc/doxygen/bugs.html
+ debug_level: 0
+ adapter speed: 1000 kHz
+ force hard breakpoints
+ Stopping...
+ target halted due to breakpoint, current mode: Thread
+ xPSR: 0x21000000 pc: 0x000023a4 msp: 0x2000ff9c
+
+ Flashing Bootloader...
+ target halted due to debug-request, current mode: Thread
+ xPSR: 0x01000000 pc: 0x000000d8 msp: 0x20010000
+ Enabled ARM Semihosting to show debug output
+ semihosting is enabled
+ ** Programming Started **
+ auto erase enabled
+ target halted due to breakpoint, current mode: Thread
+ xPSR: 0x61000000 pc: 0x2000001e msp: 0x20010000, semihosting
+ wrote 24576 bytes from file bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf.bin in 0.729124s (32.916 KiB/s)
+ ** Programming Finished **
+ ** Verify Started **
+ target halted due to breakpoint, current mode: Thread
+ xPSR: 0x61000000 pc: 0x2000002e msp: 0x20010000, semihosting
+ verified 22876 bytes in 0.114145s (195.715 KiB/s)
+ ** Verified OK **
+
+ Restarting...
+ target halted due to debug-request, current mode: Thread
+ xPSR: 0x01000000 pc: 0x000000d8 msp: 0x20010000, semihosting
+
+ **** Done!
+ ```
+
+1. For ST-Link, check that the Adapter Speed is set to 1000 kHz. OpenOCD won't work at higher speeds.
+
+ ```
+ adapter speed: 1000 kHz
+ ```
+
+1. If the flashing fails, check whether any `openocd` processes are running in the background, and kill them.
+
+## Flash Application Firmware
+
+1. __For Linux and macOS:__ Edit [`pinetime/pinetime-rust-mynewt/scripts/nrf52/flash-app.sh`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/nrf52/flash-app.sh)
+
+ __For Windows:__ Edit [`pinetime/pinetime-rust-mynewt/scripts/nrf52/flash-app.cmd`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/nrf52/flash-app.cmd)
+
+1. Change `openocd/bin/openocd` to the path of our installed `openocd` (for ST-Link) or `openocd-spi` (for Raspberry Pi)...
+
+ ```bash
+ # Flash the device
+ openocd/bin/openocd \
+ -f $swd_device \
+ -f scripts/nrf52/flash-app.ocd
+ ```
+
+1. The path of the built firmware file is defined in [`pinetime/pinetime-rust-mynewt/scripts/nrf52/flash-app.ocd`](https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/nrf52/flash-app.ocd). We shouldn't need to change this.
+
+ ```
+ program bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.img verify 0x00008000
+ ```
+
+1. Flash the application...
+
+ __For Linux and macOS:__
+
+ ```bash
+ cd ~/pinetime/pinetime-rust-mynewt
+ scripts/nrf52/flash-app.sh
+ ```
+
+ __For Windows:__
+
+ ```cmd
+ cd \pinetime\pinetime-rust-mynewt
+ scripts\nrf52\flash-app.cmd
+ ```
+
+1. We should see...
+
+ ```
+ > Executing task in folder pinetime-rust-mynewt: bash -c -l ' scripts/nrf52/flash-app.sh && echo ✅ ◾ ️Done! ' <
+
+ + source scripts/config.sh
+ ++ swd_device=scripts/nrf52/swd-stlink.ocd
+ + openocd/bin/openocd -f scripts/nrf52/swd-stlink.ocd -f scripts/nrf52/flash-app.ocd
+ GNU MCU Eclipse 64-bit Open On-Chip Debugger 0.10.0+dev-00462-gdd1d90111 (2019-01-15-13:49)
+ Licensed under GNU GPL v2
+ For bug reports, read
+ http://openocd.org/doc/doxygen/bugs.html
+ debug_level: 0
+ adapter speed: 1000 kHz
+ force hard breakpoints
+ Stopping...
+ target halted due to debug-request, current mode: Thread
+ xPSR: 0x61000000 pc: 0x000001ca msp: 0x2000ffd8
+
+ Flashing Application...
+ target halted due to debug-request, current mode: Thread
+ xPSR: 0x01000000 pc: 0x000000d8 msp: 0x20010000
+ Enabled ARM Semihosting to show debug output
+ semihosting is enabled
+ ** Programming Started **
+ auto erase enabled
+ target halted due to breakpoint, current mode: Thread
+ xPSR: 0x61000000 pc: 0x2000001e msp: 0x20010000, semihosting
+ wrote 143360 bytes from file bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.img in 3.606276s (38.821 KiB/s)
+ ** Programming Finished **
+ ** Verify Started **
+ target halted due to breakpoint, current mode: Thread
+ xPSR: 0x61000000 pc: 0x2000002e msp: 0x20010000, semihosting
+ verified 139268 bytes in 0.363909s (373.731 KiB/s)
+ ** Verified OK **
+ ```
+
+1. For ST-Link, check that the Adapter Speed is set to 1000 kHz. OpenOCD won't work at higher speeds.
+
+ ```
+ adapter speed: 1000 kHz
+ ```
+
+1. If the flashing fails, check whether any `openocd` processes are running in the background, and kill them.
+
+1. PineTime reboots (with the `reset init` OpenOCD Command)...
+
+ ```
+ Restarting...
+ target halted due to debug-request, current mode: Thread
+ xPSR: 0x01000000 pc: 0x000000d8 msp: 0x20010000, semihosting
+ Enabled ARM Semihosting to show debug output
+ semihosting is enabled
+ ```
+
+1. PineTime starts MCUBoot Bootloader...
+
+ ```
+ **** Done! Press Ctrl-C to exit...
+ Starting Bootloader...
+ Displaying image...
+ Image displayed
+ Check button: 0
+ [INF] Primary image: magic=good, swap_type=0x4, copy_done=0x1, image_ok=0x1
+ [INF] Scratch: magic=bad, swap_type=0x1, copy_done=0x2, image_ok=0x2
+ [INF] Boot source: none
+ [INF] Swap type: none
+ Waiting 5 seconds for button...
+ Waited for button: 0
+ Bootloader done
+ ```
+
+1. Finally PineTime starts the Application Firmware...
+
+ ```
+ TMP create temp_stub_0
+ NET hwid 4a f8 cf 95 6a be c1 f6 89 ba 12 1a
+ NET standalone node
+ ```
+
+Logging of debug messages is disabled by default. To enable debug logging, see the section "Semihosting Logging" below.
+
+# PineTime Updater
+
+Alternatively (for Linux and macOS only), flash the following two files to PineTime with [__PineTime Updater__](https://github.com/lupyuen/pinetime-updater)...
+
+1. __MCUBoot Bootloader__
+
+ File: `bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf`
+
+ Address: `0x0`
+
+1. __Rust + Mynewt Firmware__
+
+ File: `bin/targets/nrf52_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf`
+
+ Address: `0x8000`
+
+# Remote PineTime
+
+If you don't have a PineTime, try flashing and testing on [__Remote PineTime__](https://github.com/lupyuen/remote-pinetime-bot/blob/master/README.md) instead. Remote PineTime is a real PineTime watch that's connected 24x7 to the internet... For anyone to flash and test firmware from anywhere in the world.
+
+Upload the built firmware file `my_sensor_app.img` as a GitHub Release and flash to Remote PineTime...
+
+1. In you GitHub repo, click `Releases`
+
+1. Click `Draft A New Release`
+
+1. Fill in the `Tag Version` and `Release Title`
+
+1. Attach the firmware file `my_sensor_app.img`
+
+1. Click `Publish Release`
+
+1. Under `Assets`, copy the URL of the firmware file `my_sensor_app.img`
+
+1. Follow the steps here to flash the MCUBoot Bootloader and our firmware URL to Remote PineTime...
+
+ [Remote PineTime](https://github.com/lupyuen/remote-pinetime-bot/blob/master/README.md)
+
+# Installation, Build, Flash and Debug Logs
+
+Sample logs for Linux, macOS and Windows may be found in the [logs folder](logs)
+
+Also check the [GitHub Actions build logs](https://github.com/lupyuen/pinetime-rust-mynewt/actions)
+
+# Semihosting Logging
+
+Logging of debug messages is disabled by default. To enable Semihosting Logging, comment out this line (by inserting `#` at the start of the line)...
+
+```
+- -DDISABLE_SEMIHOSTING # Uncomment to disable Arm Semihosting. Must be uncommented for production.
+```
+
+For Bootloader: [`targets/nrf52_boot/pkg.yml`](targets/nrf52_boot/pkg.yml)
+
+For Application Firmware: [`targets/nrf52_my_sensor/pkg.yml`](targets/nrf52_my_sensor/pkg.yml)
+
+Rebuild the Bootloader and Application Firmware and flash to PineTime. Debug messages will now appear in the OpenOCD log.
+
+[More about Arm Semihosting](https://github.com/lupyuen/remote-pinetime-bot/blob/master/README.md#what-is-arm-semihosting)
+
+# VSCode Workspace
+
+Open the workspace file `workspace.code-workspace` in VSCode.
+
+The VSCode Workspace contains VSCode Tasks for building and flashing the Bootloader and Application Firmware.
+
+The Cortex-Debug Debugger in VSCode has also been configured for debugging PineTime with GDB and OpenOCD.
+
+# Contents
+
+This repository contains...
+
+- [`rust`](rust): Mynewt Application in Rust
+
+- [`Cargo.toml`](Cargo.toml): Rust Build Settings
+
+- [`.cargo`](.cargo): Rust Target Settings
+
+- [`apps/my_sensor_app`](apps/my_sensor_app): Mynewt Application in C
+
+- [`apps/boot_stub`](apps/boot_stub): Mynewt Bootloader Stub. For development use only.
+
+- [`targets/nrf52_boot`](targets/nrf52_boot): Mynewt Application Firmware Configuration
+
+- [`targets/nrf52_my_sensor`](targets/nrf52_my_sensor): MCUBoot Bootloader Configuration
+
+- [`hw/bsp/nrf52`](hw/bsp/nrf52): Mynewt Board Support Package for PineTime
+
+- [`scripts`](scripts): Build and flash scripts
+
+- [`workspace.code-workspace`](workspace.code-workspace): VSCode Workspace
+
+- [`.vscode`](.vscode): VSCode Tasks for build and flash, and debugger configuration
+
+Library modules for Mynewt...
+
+- [`libs/mynewt_rust`](libs/mynewt_rust): Helper functions for hosting Rust on Mynewt
+
+- [`libs/pinetime_boot`](libs/pinetime_boot): PineTime Bootloader Extensions for MCUBoot Bootloader
+
+- [`libs/pinetime_lvgl_mynewt`](libs/pinetime_lvgl_mynewt): LVGL UI Library for Mynewt. Links to the [`pinetime_lvgl_mynewt`](https://gitlab.com/lupyuen/pinetime_lvgl_mynewt) repo.
+
+- [`libs/rust_app`](libs/rust_app): Stub library that will be replaced by the compiled Rust application and Rust crates
+
+- [`libs/rust_libcore`](libs/rust_libcore): (Not Used) Stub library that will be replaced by the Rust Core Library
+
+- [`libs/semihosting_console`](libs/semihosting_console): Mynewt Console for Arm Semihosting
+
+Legacy modules for Mynewt that are not used...
+
+- [`libs/adc_stm32f1`](libs/adc_stm32f1): Mynewt Driver for ADC on STM32 F103 (Blue Pill). Used by `temp_stm32` internal temperature sensor.
+
+- [`libs/adc_stm32l4`](libs/adc_stm32l4): Mynewt Driver for ADC on STM32 L476. Used by `temp_stm32` internal temperature sensor.
+
+- [`libs/bc95g`](libs/bc95g): Mynewt Driver for Quectel BC95 NB-IoT module
+
+- [`libs/buffered_serial`](libs/buffered_serial): Buffered Serial Library used by `bc95g` NB-IoT driver and `gps_l70r` GPS driver
+
+- [`libs/custom_sensor`](libs/custom_sensor): Custom Sensor Definitions for Raw Temperature and Geolocation
+
+- [`libs/esp8266`](libs/esp8266): Mynewt Driver for ESP8266 WiFi module
+
+- [`libs/gps_l70r`](libs/gps_l70r): Mynewt Driver for Quectel L70-R GPS module
+
+- [`libs/hmac_prng`](libs/hmac_prng): HMAC pseudorandom number generator with entropy based on internal temperature sensor
+
+- [`libs/low_power`](libs/low_power): Low Power functions for STM32 F103 (Blue Pill)
+
+- [`libs/nrf24l01`](libs/nrf24l01): Mynewt Driver for nRF24L01
+
+- [`libs/remote_sensor`](libs/remote_sensor): Mynewt Driver for Remote Sensor
+
+- [`libs/sensor_coap`](libs/sensor_coap): Sensor CoAP Library
+
+- [`libs/sensor_network`](libs/sensor_network): Sensor Network Library
+
+- [`libs/temp_stm32`](libs/temp_stm32): Mynewt Driver for Internal Temperature Sensor on STM32
+
+- [`libs/temp_stub`](libs/temp_stub): Mynewt Driver for Stub Temperature Sensor that returns a fixed value
+
+- [`libs/tiny_gps_plus`](libs/tiny_gps_plus): TinyGPS++ Library ported from Arduino. Used by `gps_l70r` GPS driver.
diff --git a/bootloader.md b/bootloader.md
new file mode 100644
index 0000000..aa195e3
--- /dev/null
+++ b/bootloader.md
@@ -0,0 +1,53 @@
+# Bootloader for PineTime based on MyNEWT and MCUBoot
+
+## Features
+
+- Start the **application** firmware
+- Provide a safe and efficient way to **swap firmwares** from the secondary slot (in external flash memory) and the primary slot (in internal flash memory), thanks to MCUBoot
+- **Revert** to the previous version of the firmware
+- Load and run a **recovery** firmware
+- Basic UI (logo, progress bar, button)
+
+## Memory map
+
+![Memory Map](docs/pictures/memoryMap.png "Memory map")
+
+The PineTime is based on 2 flash memories:
+ - **The internal flash** (512KB) : this flash is integrated into the MCU. The MCU runs the code from this memory. It cannot run codes directly from the external SPI flash memory. This internal memory contains the bootloader code as well as the application firmware. The scratch area is used by MCUBoot to swap firmwares from internal and external memories.
+ - **The external** flash (4MB) : this memory is external to the MCU and is connected to the MCU using an SPI bus. It contains the recovery firmware (in the section *Bootloader Assets*) and the secondary slot for MCUBoot (*OTA section*). The *FS* part is available for the application firmware.
+
+## Boot flow
+
+The bootloader is the first piece of software that is running on the PineTime. It's main goal is to load the application firmware. It is also responsible to swap the firmware from the secondary and primary slot if a newer version of the firmware is present in the secondary slot. It also provides the possibility to revert to the previous version of the firmware and to restore a recovery firmware that supports OTA.
+
+![Boot flow](docs/pictures/workflow.png "Boot flow")
+
+
+At startup, the bootloader displays a **logo and its version**:
+
+![Bootloader start](docs/pictures/bootloader_start.png "Bootloader start")
+
+Then, it waits for ~5s in case the user presses the button. The **progress** is shown by the color of the logo.
+
+When the user just wants to **run the current firmware**, they won't touch the button, and the logo will be filled in **green**:
+
+![Bootloader normal boot](docs/pictures/bootloader_normal_boot.png "Bootloader normal boot")
+
+When the timeout is elapsed, **MCUBoot** will be run. It'll swap the firmware if needed and then run the firmware from the primary slot.
+
+If the user presses the button until the logo is drawn in **blue**, the previous version of the firmware will be **reverted**:
+
+![Bootloader revert](docs/pictures/bootloader_revert.png "Bootloader revert")
+
+If the user presses the button longer, until the logo is drawn in **red**, the **recovery** firmware will be loaded into the primary slot and will be run after the next reset:
+
+![Bootloader recovery](docs/pictures/bootloader_recovery.png "Bootloader recovery")
+
+## Recovery firmware
+
+The recovery firmware is a "lightweight" version of InfiniTime. It is stripped of most of its functionalities : it only provides **basic UI, BLE connectivity and OTA**.
+
+The goal of this firmware is to provide a mean for the user to OTA a new firmware in case the current firmware does not work properly or does not provide OTA.
+
+![Bootloader recovery OTA](docs/pictures/bootloader_recovery_ota.png "Bootloader recovery OTA")
+
diff --git a/docs/pictures/bootloader_normal_boot.png b/docs/pictures/bootloader_normal_boot.png
new file mode 100644
index 0000000..8248feb
Binary files /dev/null and b/docs/pictures/bootloader_normal_boot.png differ
diff --git a/docs/pictures/bootloader_recovery.png b/docs/pictures/bootloader_recovery.png
new file mode 100644
index 0000000..67bf4d3
Binary files /dev/null and b/docs/pictures/bootloader_recovery.png differ
diff --git a/docs/pictures/bootloader_recovery_ota.png b/docs/pictures/bootloader_recovery_ota.png
new file mode 100644
index 0000000..3570b3f
Binary files /dev/null and b/docs/pictures/bootloader_recovery_ota.png differ
diff --git a/docs/pictures/bootloader_revert.png b/docs/pictures/bootloader_revert.png
new file mode 100644
index 0000000..7ae08b7
Binary files /dev/null and b/docs/pictures/bootloader_revert.png differ
diff --git a/docs/pictures/bootloader_start.png b/docs/pictures/bootloader_start.png
new file mode 100644
index 0000000..ecd43f8
Binary files /dev/null and b/docs/pictures/bootloader_start.png differ
diff --git a/docs/pictures/memoryMap.odg b/docs/pictures/memoryMap.odg
new file mode 100644
index 0000000..88fab08
Binary files /dev/null and b/docs/pictures/memoryMap.odg differ
diff --git a/docs/pictures/memoryMap.png b/docs/pictures/memoryMap.png
new file mode 100644
index 0000000..f8ef10e
Binary files /dev/null and b/docs/pictures/memoryMap.png differ
diff --git a/docs/pictures/workflow.png b/docs/pictures/workflow.png
new file mode 100644
index 0000000..56b9fb0
Binary files /dev/null and b/docs/pictures/workflow.png differ
diff --git a/docs/pictures/workflow.puml b/docs/pictures/workflow.puml
new file mode 100644
index 0000000..7a6c4bd
--- /dev/null
+++ b/docs/pictures/workflow.puml
@@ -0,0 +1,46 @@
+@startuml
+start
+partition Custom {
+:Check button for 5s;
+note right
+ Display is updated to show when
+ //revert firmware// and //factory reset//
+ are taken into account
+end note
+if (Pushed >50% of the time) then (yes)
+ :Mark previous firmware \n(in secondary slot) __pending__.\nIt'll be swapped in primary\nafter reset;
+ #pink:Reset;
+ detach
+elseif (Pushed > 25% of the time) then (yes)
+ :Copy factory firmware in\nsecondary slot and\nmark it __pending__.\nIt'll be swapped in primary\nafter reset;
+ #pink:Reset;
+ detach
+else (not pushed)
+ partition MCUBoot {
+ :Inspect swap status region;
+ if (is an interrupted swap being resumed?) then (yes)
+ :Complete the partial swap operation;
+ :Boot into image in primary slot;
+ stop
+ else(no)
+ endif
+
+ :Inspect image trailers;
+ if(s a swap requested?) then(yes)
+ if(Is the requested image valid (integrity and security check)?) then (yes)
+ :Perform swap operation;
+ :Persist completion of swap procedure to image trailers;
+ else (no)
+ :Erase invalid image;
+ :Persist failure of swap procedure to image trailers;
+ endif
+ else(no)
+ endif
+
+ :Boot into image in primary slot;
+ }
+endif
+}
+
+stop
+@enduml
\ No newline at end of file
diff --git a/hw/bsp/nrf52/README.md b/hw/bsp/nrf52/README.md
new file mode 100644
index 0000000..8f397c5
--- /dev/null
+++ b/hw/bsp/nrf52/README.md
@@ -0,0 +1,5 @@
+# nrf52
+
+Board Support Package for EBYTE E73-TBB Development Boards based on Nordic nRF52832 Microcontroller.
+
+Derived from `ada_feather_nrf52` BSP.
\ No newline at end of file
diff --git a/hw/bsp/nrf52/boot-nrf52xxaa.ld b/hw/bsp/nrf52/boot-nrf52xxaa.ld
new file mode 100644
index 0000000..7df5e87
--- /dev/null
+++ b/hw/bsp/nrf52/boot-nrf52xxaa.ld
@@ -0,0 +1,26 @@
+/* Linker script for Nordic Semiconductor nRF5 devices
+ *
+ * Version: Sourcery G++ 4.5-1
+ * Support: https://support.codesourcery.com/GNUToolchain/
+ *
+ * Copyright (c) 2007, 2008, 2009, 2010 CodeSourcery, Inc.
+ *
+ * The authors hereby grant permission to use, copy, modify, distribute,
+ * and license this software and its documentation for any purpose, provided
+ * that existing copyright notices are retained in all copies and that this
+ * notice is included verbatim in any distributions. No written agreement,
+ * license, or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their authors
+ * and need not follow the licensing terms described here, provided that
+ * the new terms are clearly indicated on the first page of each file where
+ * they apply.
+ */
+/* TODO: Sync with hw/bsp/nrf52/bsp.yml */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x7000
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
+}
+
+/* The bootloader does not contain an image header */
+_imghdr_size = 0x0;
diff --git a/hw/bsp/nrf52/bsp.yml b/hw/bsp/nrf52/bsp.yml
new file mode 100644
index 0000000..ece501d
--- /dev/null
+++ b/hw/bsp/nrf52/bsp.yml
@@ -0,0 +1,74 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+bsp.name: "Generic"
+bsp.url: https://www.adafruit.com/product/3574
+bsp.maker: "Generic"
+bsp.arch: cortex_m4
+bsp.compiler: "@apache-mynewt-core/compiler/arm-none-eabi-m4"
+bsp.linkerscript:
+ - "hw/bsp/nrf52/nrf52xxaa.ld"
+ - "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx/nrf52.ld"
+bsp.linkerscript.BOOT_LOADER.OVERWRITE:
+ - "hw/bsp/nrf52/boot-nrf52xxaa.ld"
+ - "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx/nrf52.ld"
+bsp.part2linkerscript: "hw/bsp/nrf52/split_nrf52.ld"
+bsp.downloadscript: "hw/bsp/nrf52/nrf52_download.sh"
+bsp.debugscript: "hw/bsp/nrf52/nrf52_debug.sh"
+bsp.downloadscript.WINDOWS.OVERWRITE: "hw/bsp/nrf52/nrf52_download.cmd"
+bsp.debugscript.WINDOWS.OVERWRITE: "hw/bsp/nrf52/nrf52_debug.cmd"
+
+# Flash Memory Map for PineTime: Internal Flash ROM and External SPI Flash
+# TODO: These values must sync with scripts/nrf52/flash-boot.ocd, scripts/nrf52/flash-app.ocd, hw/bsp/nrf52/boot-nrf52xxaa.ld, hw/bsp/nrf52/nrf52xxaa.ld
+bsp.flash_map:
+ areas:
+ # System areas.
+ FLASH_AREA_BOOTLOADER: # MCUBoot
+ device: 0 # Internal Flash ROM
+ offset: 0x00000000 # Start of Internal Flash ROM
+ size: 28kB
+ FLASH_AREA_IMAGE_0: # Active Firmware Image
+ device: 0 # Internal Flash ROM
+ offset: 0x00008000
+ size: 464kB # Max size of Firmware Image
+ FLASH_AREA_IMAGE_1: # Standby Firmware Image
+ device: 1 # External SPI Flash
+ offset: 0x00040000
+ size: 464kB # Max size of Firmware Image
+ FLASH_AREA_IMAGE_SCRATCH: # Used by MCUBoot for swapping Active and Standby Firmware
+ device: 0 # Internal Flash ROM
+ offset: 0x0007c000
+ size: 4kB
+
+ # User areas.
+ FLASH_AREA_REBOOT_LOG: # For logging debug messages during startup
+ user_id: 0
+ device: 0 # Internal Flash ROM
+ offset: 0x00007000 # Note: 0x7f00-0x7fff contains the relocated vector table
+ size: 4kB
+ # FLASH_AREA_BOOTLOADER_ASSET: # Bootloader Assets, like Boot Graphic
+ # user_id: 1
+ # device: 1 # External SPI Flash
+ # offset: 0x00000000 # Start of External SPI Flash
+ # size: 256kB
+ FLASH_AREA_NFFS: # For user files
+ user_id: 1
+ device: 1 # External SPI Flash
+ offset: 0x000b4000
+ size: 3376kB
diff --git a/hw/bsp/nrf52/include/bsp/bsp.h b/hw/bsp/nrf52/include/bsp/bsp.h
new file mode 100644
index 0000000..597e50f
--- /dev/null
+++ b/hw/bsp/nrf52/include/bsp/bsp.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BSP_H
+#define H_BSP_H
+
+#include
+
+#include "os/mynewt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Define special stackos sections */
+#define sec_data_core __attribute__((section(".data.core")))
+#define sec_bss_core __attribute__((section(".bss.core")))
+#define sec_bss_nz_core __attribute__((section(".bss.core.nz")))
+
+/* More convenient section placement macros. */
+#define bssnz_t sec_bss_nz_core
+
+extern uint8_t _ram_start;
+#define RAM_SIZE 0x10000
+
+/* LED pins */
+#define LED_1 (17)
+#define LED_2 (18)
+#define LED_BLINK_PIN (LED_1)
+
+/* Buttons */
+#define BUTTON_1 (14) /* Labelled SW1 on the board */
+#define BUTTON_2 (13) /* Labelled SW2 on the board */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BSP_H */
diff --git a/hw/bsp/nrf52/nrf52_debug.cmd b/hw/bsp/nrf52/nrf52_debug.cmd
new file mode 100644
index 0000000..3444fd3
--- /dev/null
+++ b/hw/bsp/nrf52/nrf52_debug.cmd
@@ -0,0 +1,22 @@
+@rem
+@rem Licensed to the Apache Software Foundation (ASF) under one
+@rem or more contributor license agreements. See the NOTICE file
+@rem distributed with this work for additional information
+@rem regarding copyright ownership. The ASF licenses this file
+@rem to you under the Apache License, Version 2.0 (the
+@rem "License"); you may not use this file except in compliance
+@rem with the License. You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing,
+@rem software distributed under the License is distributed on an
+@rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@rem KIND, either express or implied. See the License for the
+@rem specific language governing permissions and limitations
+@rem under the License.
+@rem
+
+@rem Execute a shell with a script of the same name and .sh extension
+
+@bash "%~dp0%~n0.sh"
diff --git a/hw/bsp/nrf52/nrf52_debug.sh b/hw/bsp/nrf52/nrf52_debug.sh
new file mode 100644
index 0000000..17b980d
--- /dev/null
+++ b/hw/bsp/nrf52/nrf52_debug.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Called with following variables set:
+# - CORE_PATH is absolute path to @apache-mynewt-core
+# - BSP_PATH is absolute path to hw/bsp/bsp_name
+# - BIN_BASENAME is the path to prefix to target binary,
+# .elf appended to name is the ELF file
+# - FEATURES holds the target features string
+# - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
+# - RESET set if target should be reset when attaching
+# - NO_GDB set if we should not start gdb to debug
+#
+
+. $CORE_PATH/hw/scripts/jlink.sh
+
+FILE_NAME=$BIN_BASENAME.elf
+
+if [ $# -gt 2 ]; then
+ SPLIT_ELF_NAME=$3.elf
+ # TODO -- this magic number 0x42000 is the location of the second image
+ # slot. we should either get this from a flash map file or somehow learn
+ # this from the image itself
+ EXTRA_GDB_CMDS="add-symbol-file $SPLIT_ELF_NAME 0x8000 -readnow"
+fi
+
+JLINK_DEV="nRF52"
+
+jlink_debug
+
diff --git a/hw/bsp/nrf52/nrf52_download.cmd b/hw/bsp/nrf52/nrf52_download.cmd
new file mode 100644
index 0000000..3444fd3
--- /dev/null
+++ b/hw/bsp/nrf52/nrf52_download.cmd
@@ -0,0 +1,22 @@
+@rem
+@rem Licensed to the Apache Software Foundation (ASF) under one
+@rem or more contributor license agreements. See the NOTICE file
+@rem distributed with this work for additional information
+@rem regarding copyright ownership. The ASF licenses this file
+@rem to you under the Apache License, Version 2.0 (the
+@rem "License"); you may not use this file except in compliance
+@rem with the License. You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing,
+@rem software distributed under the License is distributed on an
+@rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@rem KIND, either express or implied. See the License for the
+@rem specific language governing permissions and limitations
+@rem under the License.
+@rem
+
+@rem Execute a shell with a script of the same name and .sh extension
+
+@bash "%~dp0%~n0.sh"
diff --git a/hw/bsp/nrf52/nrf52_download.sh b/hw/bsp/nrf52/nrf52_download.sh
new file mode 100644
index 0000000..08d45b4
--- /dev/null
+++ b/hw/bsp/nrf52/nrf52_download.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Called with following variables set:
+# - CORE_PATH is absolute path to @apache-mynewt-core
+# - BSP_PATH is absolute path to hw/bsp/bsp_name
+# - BIN_BASENAME is the path to prefix to target binary,
+# .elf appended to name is the ELF file
+# - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
+# - FEATURES holds the target features string
+# - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
+# - MFG_IMAGE is "1" if this is a manufacturing image
+# - FLASH_OFFSET contains the flash offset to download to
+# - BOOT_LOADER is set if downloading a bootloader
+
+. $CORE_PATH/hw/scripts/jlink.sh
+
+if [ "$MFG_IMAGE" ]; then
+ FLASH_OFFSET=0x0
+fi
+
+JLINK_DEV="nRF52"
+
+common_file_to_load
+jlink_load
diff --git a/hw/bsp/nrf52/nrf52_no_boot.ld b/hw/bsp/nrf52/nrf52_no_boot.ld
new file mode 100644
index 0000000..3d8cf22
--- /dev/null
+++ b/hw/bsp/nrf52/nrf52_no_boot.ld
@@ -0,0 +1,194 @@
+/* Linker script for Nordic Semiconductor nRF5 devices
+ *
+ * Version: Sourcery G++ 4.5-1
+ * Support: https://support.codesourcery.com/GNUToolchain/
+ *
+ * Copyright (c) 2007, 2008, 2009, 2010 CodeSourcery, Inc.
+ *
+ * The authors hereby grant permission to use, copy, modify, distribute,
+ * and license this software and its documentation for any purpose, provided
+ * that existing copyright notices are retained in all copies and that this
+ * notice is included verbatim in any distributions. No written agreement,
+ * license, or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their authors
+ * and need not follow the licensing terms described here, provided that
+ * the new terms are clearly indicated on the first page of each file where
+ * they apply.
+ */
+OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __HeapBase
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ * __bssnz_start__
+ * __bssnz_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ __text = .;
+
+ .text :
+ {
+ __isr_vector_start = .;
+ KEEP(*(.isr_vector))
+ __isr_vector_end = .;
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ *(.eh_frame*)
+ . = ALIGN(4);
+ } > FLASH
+
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ . = ALIGN(4);
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ . = ALIGN(4);
+ } > FLASH
+ __exidx_end = .;
+
+ __etext = .;
+
+ .vector_relocation :
+ {
+ . = ALIGN(4);
+ __vector_tbl_reloc__ = .;
+ . = . + (__isr_vector_end - __isr_vector_start);
+ . = ALIGN(4);
+ } > RAM
+
+ .data : AT (__etext)
+ {
+ __data_start__ = .;
+ *(vtable)
+ *(.data*)
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ *(.preinit_array)
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ *(SORT(.init_array.*))
+ *(.init_array)
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ *(SORT(.fini_array.*))
+ *(.fini_array)
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ *(.jcr)
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+ } > RAM
+
+ /* Non-zeroed BSS. This section is similar to BSS, with the following
+ * caveat:
+ * 1. It does not get zeroed at init-time.
+ */
+ .bssnz :
+ {
+ . = ALIGN(4);
+ __bssnz_start__ = .;
+ *(.bss.core.nz*)
+ . = ALIGN(4);
+ __bssnz_end__ = .;
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM
+
+ /* Heap starts after BSS */
+ . = ALIGN(8);
+ __HeapBase = .;
+
+ /* .stack_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later */
+ .stack_dummy (COPY):
+ {
+ *(.stack*)
+ } > RAM
+
+ /* Set stack top to end of RAM, and stack limit move down by
+ * size of stack_dummy section */
+ __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+ PROVIDE(__stack = __StackTop);
+
+ /* Top of head is the bottom of the stack */
+ __HeapLimit = __StackLimit;
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ ASSERT(__HeapBase <= __HeapLimit, "region RAM overflowed with stack")
+}
+
diff --git a/hw/bsp/nrf52/nrf52xxaa.ld b/hw/bsp/nrf52/nrf52xxaa.ld
new file mode 100644
index 0000000..b45a284
--- /dev/null
+++ b/hw/bsp/nrf52/nrf52xxaa.ld
@@ -0,0 +1,25 @@
+/* Linker script for Nordic Semiconductor nRF5 devices
+ *
+ * Version: Sourcery G++ 4.5-1
+ * Support: https://support.codesourcery.com/GNUToolchain/
+ *
+ * Copyright (c) 2007, 2008, 2009, 2010 CodeSourcery, Inc.
+ *
+ * The authors hereby grant permission to use, copy, modify, distribute,
+ * and license this software and its documentation for any purpose, provided
+ * that existing copyright notices are retained in all copies and that this
+ * notice is included verbatim in any distributions. No written agreement,
+ * license, or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their authors
+ * and need not follow the licensing terms described here, provided that
+ * the new terms are clearly indicated on the first page of each file where
+ * they apply.
+ */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00008000, LENGTH = 463K /* Previously 0x3a000 */
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
+}
+
+/* This linker script is used for images and thus contains an image header */
+_imghdr_size = 0x20;
diff --git a/hw/bsp/nrf52/pkg.yml b/hw/bsp/nrf52/pkg.yml
new file mode 100644
index 0000000..8937e00
--- /dev/null
+++ b/hw/bsp/nrf52/pkg.yml
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: hw/bsp/nrf52
+pkg.type: bsp
+pkg.description: BSP definition for Pine64 PineTime Smart Watch.
+pkg.author: "Lee Lup Yuen "
+pkg.homepage: "https://github.com/lupyuen"
+pkg.keywords:
+ - nrf52
+
+pkg.cflags:
+ - -DNRF52
+
+pkg.cflags.HARDFLOAT:
+ - -mfloat-abi=hard -mfpu=fpv4-sp-d16
+
+pkg.deps:
+ - "@apache-mynewt-core/hw/mcu/nordic/nrf52xxx"
+ - "@apache-mynewt-core/libc/baselibc"
+ - "@apache-mynewt-core/hw/drivers/flash/spiflash" # SPI Flash Driver
+
+pkg.deps.SOFT_PWM:
+ - "@apache-mynewt-core/hw/drivers/pwm/soft_pwm"
+
+pkg.deps.UARTBB_0:
+ - "@apache-mynewt-core/hw/drivers/uart/uart_bitbang"
diff --git a/hw/bsp/nrf52/split_nrf52.ld b/hw/bsp/nrf52/split_nrf52.ld
new file mode 100644
index 0000000..696b6c4
--- /dev/null
+++ b/hw/bsp/nrf52/split_nrf52.ld
@@ -0,0 +1,209 @@
+/* Linker script for Nordic Semiconductor nRF5 devices
+ *
+ * Version: Sourcery G++ 4.5-1
+ * Support: https://support.codesourcery.com/GNUToolchain/
+ *
+ * Copyright (c) 2007, 2008, 2009, 2010 CodeSourcery, Inc.
+ *
+ * The authors hereby grant permission to use, copy, modify, distribute,
+ * and license this software and its documentation for any purpose, provided
+ * that existing copyright notices are retained in all copies and that this
+ * notice is included verbatim in any distributions. No written agreement,
+ * license, or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their authors
+ * and need not follow the licensing terms described here, provided that
+ * the new terms are clearly indicated on the first page of each file where
+ * they apply.
+ */
+OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00042000, LENGTH = 0x3a000
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __HeapBase
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ * __bssnz_start__
+ * __bssnz_end__
+ */
+ENTRY(Reset_Handler_split)
+
+SECTIONS
+{
+ .imghdr (NOLOAD):
+ {
+ . = . + 0x20;
+ } > FLASH
+
+ .text :
+ {
+ __split_isr_vector_start = .;
+ KEEP(*(.isr_vector_split))
+ __split_isr_vector_end = .;
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ *(.eh_frame*)
+ . = ALIGN(4);
+ } > FLASH
+
+
+ .ARM.extab : ALIGN(4)
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ . = ALIGN(4);
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ . = ALIGN(4);
+ } > FLASH
+ __exidx_end = .;
+
+ __etext = .;
+
+ /* save RAM used by the split image. This assumes that
+ * the loader uses all the RAM up to its HeapBase */
+ .loader_ram_contents :
+ {
+ _loader_ram_start = .;
+
+ /* this symbol comes from the loader linker */
+ . = . + (ABSOLUTE(__HeapBase_loader) - _loader_ram_start);
+ _loader_ram_end = .;
+ } > RAM
+
+ .data :
+ {
+ __data_start__ = .;
+ *(.data*)
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ *(.preinit_array)
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ *(SORT(.init_array.*))
+ *(.init_array)
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ *(SORT(.fini_array.*))
+ *(.fini_array)
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ *(.jcr)
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+ } > RAM AT > FLASH
+
+ /* Non-zeroed BSS. This section is similar to BSS, with the following two
+ * caveats:
+ * 1. It does not get zeroed at init-time.
+ * 2. You cannot use it as source memory for EasyDMA.
+ *
+ * This section exists because of a hardware defect; see errata 33 and 34
+ * in nrf52 errata sheet.
+ */
+ .bssnz :
+ {
+ . = ALIGN(4);
+ __bssnz_start__ = .;
+ *(.bss.core.nz*)
+ . = ALIGN(4);
+ __bssnz_end__ = .;
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM
+
+ /* Heap starts after BSS */
+ . = ALIGN(8);
+ __HeapBase = .;
+
+ /* .stack_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later */
+ .stack_dummy (COPY):
+ {
+ *(.stack*)
+ } > RAM
+
+ _ram_start = ORIGIN(RAM);
+
+ /* Set stack top to end of RAM, and stack limit move down by
+ * size of stack_dummy section */
+ __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+ PROVIDE(__stack = __StackTop);
+
+ /* Top of head is the bottom of the stack */
+ __HeapLimit = __StackLimit;
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ ASSERT(__HeapBase <= __HeapLimit, "region RAM overflowed with stack")
+}
+
diff --git a/hw/bsp/nrf52/src/arch/cortex_m4/gcc_startup_nrf52.s b/hw/bsp/nrf52/src/arch/cortex_m4/gcc_startup_nrf52.s
new file mode 100644
index 0000000..ece6db1
--- /dev/null
+++ b/hw/bsp/nrf52/src/arch/cortex_m4/gcc_startup_nrf52.s
@@ -0,0 +1,301 @@
+/*
+Copyright (c) 2015, Nordic Semiconductor ASA
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of Nordic Semiconductor ASA nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+NOTE: Template files (including this one) are application specific and therefore
+expected to be copied into the application project folder prior to its use!
+*/
+
+ .syntax unified
+ .arch armv7-m
+
+ .section .stack
+ .align 3
+ .equ Stack_Size, 432
+ .globl __StackTop
+ .globl __StackLimit
+__StackLimit:
+ .space Stack_Size
+ .size __StackLimit, . - __StackLimit
+__StackTop:
+ .size __StackTop, . - __StackTop
+
+ .section .heap
+ .align 3
+#ifdef __HEAP_SIZE
+ .equ Heap_Size, __HEAP_SIZE
+#else
+ .equ Heap_Size, 0
+#endif
+ .globl __HeapBase
+ .globl __HeapLimit
+__HeapBase:
+ .if Heap_Size
+ .space Heap_Size
+ .endif
+ .size __HeapBase, . - __HeapBase
+__HeapLimit:
+ .size __HeapLimit, . - __HeapLimit
+
+ .section .isr_vector
+ .align 2
+ .globl __isr_vector
+__isr_vector:
+ .long __StackTop /* Top of Stack */
+ .long Reset_Handler /* Reset Handler */
+ .long NMI_Handler /* NMI Handler */
+ .long HardFault_Handler /* Hard Fault Handler */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long SVC_Handler /* SVCall Handler */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long PendSV_Handler /* PendSV Handler */
+ .long SysTick_Handler /* SysTick Handler */
+
+ /* External Interrupts */
+ .long POWER_CLOCK_IRQHandler
+ .long RADIO_IRQHandler
+ .long UARTE0_UART0_IRQHandler
+ .long SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler
+ .long SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler
+ .long NFCT_IRQHandler
+ .long GPIOTE_IRQHandler
+ .long SAADC_IRQHandler
+ .long TIMER0_IRQHandler
+ .long TIMER1_IRQHandler
+ .long TIMER2_IRQHandler
+ .long RTC0_IRQHandler
+ .long TEMP_IRQHandler
+ .long RNG_IRQHandler
+ .long ECB_IRQHandler
+ .long CCM_AAR_IRQHandler
+ .long WDT_IRQHandler
+ .long RTC1_IRQHandler
+ .long QDEC_IRQHandler
+ .long COMP_LPCOMP_IRQHandler
+ .long SWI0_EGU0_IRQHandler
+ .long SWI1_EGU1_IRQHandler
+ .long SWI2_EGU2_IRQHandler
+ .long SWI3_EGU3_IRQHandler
+ .long SWI4_EGU4_IRQHandler
+ .long SWI5_EGU5_IRQHandler
+ .long TIMER3_IRQHandler
+ .long TIMER4_IRQHandler
+ .long PWM0_IRQHandler
+ .long PDM_IRQHandler
+ .long 0 /*Reserved */
+ .long 0 /*Reserved */
+ .long MWU_IRQHandler
+ .long PWM1_IRQHandler
+ .long PWM2_IRQHandler
+ .long SPIM2_SPIS2_SPI2_IRQHandler
+ .long RTC2_IRQHandler
+ .long I2S_IRQHandler
+
+ .size __isr_vector, . - __isr_vector
+
+/* Reset Handler */
+
+ .text
+ .thumb
+ .thumb_func
+ .align 1
+ .globl Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+ .fnstart
+
+ /* Clear BSS */
+ mov r0, #0
+ ldr r2, =__bss_start__
+ ldr r3, =__bss_end__
+.bss_zero_loop:
+ cmp r2, r3
+ itt lt
+ strlt r0, [r2], #4
+ blt .bss_zero_loop
+
+
+/* Loop to copy data from read only memory to RAM. The ranges
+ * of copy from/to are specified by following symbols evaluated in
+ * linker script.
+ * __etext: End of code section, i.e., begin of data sections to copy from.
+ * __data_start__/__data_end__: RAM address range that data should be
+ * copied to. Both must be aligned to 4 bytes boundary. */
+ ldr r1, =__etext
+ ldr r2, =__data_start__
+ ldr r3, =__data_end__
+
+ subs r3, r2
+ ble .LC0
+
+.LC1:
+ subs r3, 4
+ ldr r0, [r1,r3]
+ str r0, [r2,r3]
+ bgt .LC1
+
+.LC0:
+
+ LDR R0, =__HeapBase
+ LDR R1, =__HeapLimit
+ BL _sbrkInit
+
+ LDR R0, =SystemInit
+ BLX R0
+
+ BL hal_system_init
+
+ LDR R0, =_start
+ BX R0
+
+ .pool
+ .cantunwind
+ .fnend
+ .size Reset_Handler,.-Reset_Handler
+
+ .section ".text"
+
+
+/* Dummy Exception Handlers (infinite loops which can be modified) */
+
+ .weak NMI_Handler
+ .type NMI_Handler, %function
+NMI_Handler:
+ B .
+ .size NMI_Handler, . - NMI_Handler
+
+
+ .weak HardFault_Handler
+ .type HardFault_Handler, %function
+HardFault_Handler:
+ B .
+ .size HardFault_Handler, . - HardFault_Handler
+
+
+ .weak MemoryManagement_Handler
+ .type MemoryManagement_Handler, %function
+MemoryManagement_Handler:
+ B .
+ .size MemoryManagement_Handler, . - MemoryManagement_Handler
+
+
+ .weak BusFault_Handler
+ .type BusFault_Handler, %function
+BusFault_Handler:
+ B .
+ .size BusFault_Handler, . - BusFault_Handler
+
+
+ .weak UsageFault_Handler
+ .type UsageFault_Handler, %function
+UsageFault_Handler:
+ B .
+ .size UsageFault_Handler, . - UsageFault_Handler
+
+
+ .weak SVC_Handler
+ .type SVC_Handler, %function
+SVC_Handler:
+ B .
+ .size SVC_Handler, . - SVC_Handler
+
+
+ .weak PendSV_Handler
+ .type PendSV_Handler, %function
+PendSV_Handler:
+ B .
+ .size PendSV_Handler, . - PendSV_Handler
+
+
+ .weak SysTick_Handler
+ .type SysTick_Handler, %function
+SysTick_Handler:
+ B .
+ .size SysTick_Handler, . - SysTick_Handler
+
+
+/* IRQ Handlers */
+
+ .globl Default_Handler
+ .type Default_Handler, %function
+Default_Handler:
+ B .
+ .size Default_Handler, . - Default_Handler
+
+ .macro IRQ handler
+ .weak \handler
+ .set \handler, Default_Handler
+ .endm
+
+ IRQ POWER_CLOCK_IRQHandler
+ IRQ RADIO_IRQHandler
+ IRQ UARTE0_UART0_IRQHandler
+ IRQ SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler
+ IRQ SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler
+ IRQ NFCT_IRQHandler
+ IRQ GPIOTE_IRQHandler
+ IRQ SAADC_IRQHandler
+ IRQ TIMER0_IRQHandler
+ IRQ TIMER1_IRQHandler
+ IRQ TIMER2_IRQHandler
+ IRQ RTC0_IRQHandler
+ IRQ TEMP_IRQHandler
+ IRQ RNG_IRQHandler
+ IRQ ECB_IRQHandler
+ IRQ CCM_AAR_IRQHandler
+ IRQ WDT_IRQHandler
+ IRQ RTC1_IRQHandler
+ IRQ QDEC_IRQHandler
+ IRQ COMP_LPCOMP_IRQHandler
+ IRQ SWI0_EGU0_IRQHandler
+ IRQ SWI1_EGU1_IRQHandler
+ IRQ SWI2_EGU2_IRQHandler
+ IRQ SWI3_EGU3_IRQHandler
+ IRQ SWI4_EGU4_IRQHandler
+ IRQ SWI5_EGU5_IRQHandler
+ IRQ TIMER3_IRQHandler
+ IRQ TIMER4_IRQHandler
+ IRQ PWM0_IRQHandler
+ IRQ PDM_IRQHandler
+ IRQ MWU_IRQHandler
+ IRQ PWM1_IRQHandler
+ IRQ PWM2_IRQHandler
+ IRQ SPIM2_SPIS2_SPI2_IRQHandler
+ IRQ RTC2_IRQHandler
+ IRQ I2S_IRQHandler
+
+ .end
diff --git a/hw/bsp/nrf52/src/arch/cortex_m4/gcc_startup_nrf52_split.s b/hw/bsp/nrf52/src/arch/cortex_m4/gcc_startup_nrf52_split.s
new file mode 100644
index 0000000..6f000ec
--- /dev/null
+++ b/hw/bsp/nrf52/src/arch/cortex_m4/gcc_startup_nrf52_split.s
@@ -0,0 +1,166 @@
+/*
+Copyright (c) 2015, Nordic Semiconductor ASA
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of Nordic Semiconductor ASA nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+NOTE: Template files (including this one) are application specific and therefore
+expected to be copied into the application project folder prior to its use!
+*/
+
+ .syntax unified
+ .arch armv7-m
+ .section .stack
+ .align 3
+ .equ Stack_Size, 432
+ .globl __StackTop
+ .globl __StackLimit
+__StackLimit:
+ .space Stack_Size
+ .size __StackLimit, . - __StackLimit
+__StackTop:
+ .size __StackTop, . - __StackTop
+
+ .section .heap
+ .align 3
+#ifdef __HEAP_SIZE
+ .equ Heap_Size, __HEAP_SIZE
+#else
+ .equ Heap_Size, 0
+#endif
+ .globl __HeapBase
+ .globl __HeapLimit
+__HeapBase:
+ .if Heap_Size
+ .space Heap_Size
+ .endif
+ .size __HeapBase, . - __HeapBase
+__HeapLimit:
+ .size __HeapLimit, . - __HeapLimit
+
+ .section .isr_vector_split
+ .align 2
+ .globl __isr_vector_split
+__isr_vector_split:
+ .long __StackTop /* Top of Stack */
+ .long Reset_Handler_split /* Reset Handler */
+
+ .size __isr_vector_split, . - __isr_vector_split
+
+/* Reset Handler */
+
+ .text
+ .thumb
+ .thumb_func
+ .align 1
+ .globl Reset_Handler_split
+ .type Reset_Handler_split, %function
+Reset_Handler_split:
+ .fnstart
+
+ /* Clear CPU state before proceeding */
+ mov r0, #0
+ msr control, r0
+ msr primask, r0
+ /* Clear BSS */
+ ldr r2, =__bss_start__
+ ldr r3, =__bss_end__
+.bss_zero_loop:
+ cmp r2, r3
+ itt lt
+ strlt r0, [r2], #4
+ blt .bss_zero_loop
+
+
+/* Loop to copy data from read only memory to RAM. The ranges
+ * of copy from/to are specified by following symbols evaluated in
+ * linker script.
+ * __etext: End of code section, i.e., begin of data sections to copy from.
+ * __data_start__/__data_end__: RAM address range that data should be
+ * copied to. Both must be aligned to 4 bytes boundary. */
+
+ ldr r1, =__etext
+ ldr r2, =__data_start__
+ ldr r3, =__data_end__
+
+ subs r3, r2
+ ble .LC0
+
+.LC1:
+ subs r3, 4
+ ldr r0, [r1,r3]
+ str r0, [r2,r3]
+ bgt .LC1
+
+.LC0:
+ ldr r1, =__etext_loader
+ ldr r2, =__data_start___loader
+ ldr r3, =__data_end___loader
+
+ subs r3, r2
+ ble .LC2
+
+.LC3:
+ subs r3, 4
+ ldr r0, [r1,r3]
+ str r0, [r2,r3]
+ bgt .LC3
+.LC2:
+
+ subs r0, r0
+ ldr r2, =__bss_start___loader
+ ldr r3, =__bss_end___loader
+
+ subs r3, r2
+ ble .LC4
+
+.LC5:
+ subs r3, 4
+ str r0, [r2,r3]
+ bgt .LC5
+.LC4:
+
+ LDR R0, =__HeapBase
+ LDR R1, =__HeapLimit
+ BL _sbrkInit
+
+ LDR R0, =SystemInit
+ BLX R0
+
+ BL hal_system_init
+
+ LDR R0, =_start_split
+ BX R0
+
+ .pool
+ .cantunwind
+ .fnend
+ .size Reset_Handler_split,.-Reset_Handler_split
+
+ .section ".text"
+ .end
diff --git a/hw/bsp/nrf52/src/hal_bsp.c b/hw/bsp/nrf52/src/hal_bsp.c
new file mode 100644
index 0000000..71f71e9
--- /dev/null
+++ b/hw/bsp/nrf52/src/hal_bsp.c
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include
+#include
+#include
+#include "os/mynewt.h"
+#include "nrfx.h"
+#include "flash_map/flash_map.h"
+#include "hal/hal_bsp.h"
+#include "hal/hal_flash.h"
+#include "hal/hal_system.h"
+#include "mcu/nrf52_hal.h"
+#include "mcu/nrf52_periph.h"
+#include "bsp/bsp.h"
+#include "defs/sections.h"
+
+#if MYNEWT_VAL(SPIFLASH) // If External SPI Flash exists...
+#include
+#endif // MYNEWT_VAL(SPIFLASH)
+
+/*
+ * What memory to include in coredump.
+ */
+static const struct hal_bsp_mem_dump dump_cfg[] = {
+ [0] = {
+ .hbmd_start = &_ram_start,
+ .hbmd_size = RAM_SIZE
+ }
+};
+
+/// Array of Flash Devices
+static const struct hal_flash *flash_devs[] = {
+ [0] = &nrf52k_flash_dev, // Internal Flash ROM
+#if MYNEWT_VAL(SPIFLASH) // If External SPI Flash exists...
+ [1] = &spiflash_dev.hal, // External SPI Flash
+#endif // MYNEWT_VAL(SPIFLASH)
+};
+
+/// Return the Flash Device for the ID. 0 for Internal Flash ROM, 1 for External SPI Flash
+const struct hal_flash *
+hal_bsp_flash_dev(uint8_t id)
+{
+ if (id >= ARRAY_SIZE(flash_devs)) {
+ return NULL;
+ }
+ return flash_devs[id];
+}
+
+const struct hal_bsp_mem_dump *
+hal_bsp_core_dump(int *area_cnt)
+{
+ *area_cnt = sizeof(dump_cfg) / sizeof(dump_cfg[0]);
+ return dump_cfg;
+}
+
+int
+hal_bsp_power_state(int state)
+{
+ return (0);
+}
+
+/**
+ * Returns the configured priority for the given interrupt. If no priority
+ * configured, return the priority passed in
+ *
+ * @param irq_num
+ * @param pri
+ *
+ * @return uint32_t
+ */
+uint32_t
+hal_bsp_get_nvic_priority(int irq_num, uint32_t pri)
+{
+ uint32_t cfg_pri;
+
+ switch (irq_num) {
+ /* Radio gets highest priority */
+ case RADIO_IRQn:
+ cfg_pri = 0;
+ break;
+ default:
+ cfg_pri = pri;
+ }
+ return cfg_pri;
+}
+
+void
+hal_bsp_init(void)
+{
+ /* Make sure system clocks have started */
+ hal_system_clock_start();
+
+ /* Create all available nRF52840 peripherals */
+ nrf52_periph_create();
+}
diff --git a/hw/bsp/nrf52/src/sbrk.c b/hw/bsp/nrf52/src/sbrk.c
new file mode 100644
index 0000000..5df43c9
--- /dev/null
+++ b/hw/bsp/nrf52/src/sbrk.c
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include
+
+/* put these in the data section so they are not cleared by _start */
+static char *sbrkBase __attribute__ ((section (".data")));
+static char *sbrkLimit __attribute__ ((section (".data")));
+static char *brk __attribute__ ((section (".data")));
+
+void
+_sbrkInit(char *base, char *limit) {
+ sbrkBase = base;
+ sbrkLimit = limit;
+ brk = base;
+}
+
+void *
+_sbrk(int incr)
+{
+ void *prev_brk;
+
+ if (incr < 0) {
+ /* Returning memory to the heap. */
+ incr = -incr;
+ if (brk - incr < sbrkBase) {
+ prev_brk = (void *)-1;
+ } else {
+ prev_brk = brk;
+ brk -= incr;
+ }
+ } else {
+ /* Allocating memory from the heap. */
+ if (sbrkLimit - brk >= incr) {
+ prev_brk = brk;
+ brk += incr;
+ } else {
+ prev_brk = (void *)-1;
+ }
+ }
+
+ return prev_brk;
+}
diff --git a/hw/bsp/nrf52/syscfg.yml b/hw/bsp/nrf52/syscfg.yml
new file mode 100644
index 0000000..bd48895
--- /dev/null
+++ b/hw/bsp/nrf52/syscfg.yml
@@ -0,0 +1,110 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.defs:
+ BSP_NRF52:
+ description: 'Set to indicate that BSP has NRF52'
+ value: 1
+
+ SOFT_PWM:
+ description: 'Enable soft PWM'
+ value: 0
+
+ UARTBB_0:
+ description: 'Enable bit-banger UART 0'
+ value: 0
+
+syscfg.vals:
+ # Enable nRF52832 MCU
+ MCU_TARGET: nRF52832
+
+ ###########################################################################
+ # Default Pins for Peripherals
+ # Defined in http://files.pine64.org/doc/PineTime/PineTime%20Port%20Assignment%20rev1.0.pdf
+
+ # SPI port 0 connected to ST7789 display and XT25F32B flash
+ SPI_0_MASTER_PIN_SCK: 2 # P0.02/AIN0: SPI-SCK, LCD_SCK SPI clock for display and flash
+ SPI_0_MASTER_PIN_MOSI: 3 # P0.03/AIN1: SPI-MOSI, LCD_SDI SPI MOSI for display and flash
+ SPI_0_MASTER_PIN_MISO: 4 # P0.04/AIN2: SPI-MISO SPI MISO for flash only
+
+ # I2C port 1 connected to CST816S touch controller, BMA421 accelerometer, HRS3300 heart rate sensor
+ I2C_1_PIN_SCL: 7 # P0.07: BMA421-SCL, HRS3300-SCL, TP-SCLOUT
+ I2C_1_PIN_SDA: 6 # P0.06: BMA421-SDA, HRS3300-SDA, TP-SDAI/O
+
+ # UART port 0 is disabled
+ UART_0: 0
+
+ # Configure NFC pins as GPIO P0.09, P0.10
+ NFC_PINS_AS_GPIO: 1
+
+ ###########################################################################
+ # SPI Flash
+ # XTX XT25F32B 32 Mb (4 MB) SPI NOR Flash (similar to QuadSPI SPI NOR Flash like Macronix 32 Mb (4 MB) MX25L3233F)
+ # manufacturer (0x0b), device (0x15), memory type (0x40), density (0x16)
+ # Settings below are documented at https://github.com/apache/mynewt-core/blob/master/hw/drivers/flash/spiflash/syscfg.yml
+
+ SPIFLASH: 1 # Enable SPI Flash
+ SPIFLASH_SPI_NUM: 0 # SPI Interface 0
+ SPIFLASH_SPI_CS_PIN: 5 # SPI interface CS pin: P0.05/AIN3, SPI-CE# (SPI-NOR)
+ SPIFLASH_BAUDRATE: 8000 # Requested baudrate, 8000 is the fastest baudrate supported by nRF52832
+ SPIFLASH_MANUFACTURER: 0x0B # Expected SpiFlash manufacturer as read by Read JEDEC ID command 9FH
+ SPIFLASH_MEMORY_TYPE: 0x40 # Expected SpiFlash memory type as read by Read JEDEC ID command 9FH
+ SPIFLASH_MEMORY_CAPACITY: 0x16 # Expected SpiFlash memory capactity as read by Read JEDEC ID command 9FH (2 ^ 0x16 = 32 Mb)
+ SPIFLASH_SECTOR_COUNT: 1024 # Number of sectors: 1024 sectors of 4 KB each
+ SPIFLASH_SECTOR_SIZE: 4096 # TODO Number of bytes that can be erased at a time: 4 KB sector size
+ SPIFLASH_PAGE_SIZE: 256 # TODO Number of bytes that can be written at a time
+
+ # Copied from https://github.com/apache/mynewt-core/blob/master/hw/bsp/black_vet6/syscfg.yml
+ SPIFLASH_TBP1_TYPICAL: 20 # Byte program time (first byte) (us)
+ SPIFLASH_TBP1_MAXIMUM: 50 # Maximum byte program time (first byte) (us)
+ SPIFLASH_TPP_TYPICAL: 700 # Page program time (us)
+ SPIFLASH_TPP_MAXIMUM: 3000 # Maximum page program time (us)
+ SPIFLASH_TSE_TYPICAL: 30000 # Sector erase time (4KB) (us)
+ SPIFLASH_TSE_MAXIMUM: 400000 # Maximum sector erase time (us)
+ SPIFLASH_TBE1_TYPICAL: 120000 # Block erase time (32KB) (us)
+ SPIFLASH_TBE1_MAXIMUM: 800000 # Maximum block erase time (32KB) (us)
+ SPIFLASH_TBE2_TYPICAL: 150000 # Block erase time (64KB) (us)
+ SPIFLASH_TBE2_MAXIMUM: 1000000 # Maximum block erase time (64KB) (us)
+ SPIFLASH_TCE_TYPICAL: 3000000 # Chip erase time (us)
+ SPIFLASH_TCE_MAXIMUM: 10000000 # Maximum chip erase time (us)
+
+ ###########################################################################
+ # Flash Regions
+
+ CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS
+ REBOOT_LOG_FLASH_AREA: FLASH_AREA_REBOOT_LOG
+ NFFS_FLASH_AREA: FLASH_AREA_NFFS
+ COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1
+
+ MCU_DCDC_ENABLED: 1
+ MCU_LFCLK_SOURCE: LFXO
+ BOOT_SERIAL_DETECT_PIN: 20
+
+ ###########################################################################
+ # Bluetooth
+
+ # The module on the board has +/- 40 ppm crystal. A value of 5 is
+ # for crystals in the range of 31 to 50 ppm.
+ BLE_LL_SCA: 5
+
+syscfg.vals.BLE_CONTROLLER:
+ TIMER_0: 0
+ TIMER_5: 1
+ OS_CPUTIME_FREQ: 32768
+ OS_CPUTIME_TIMER_NUM: 5
+ BLE_LL_RFMGMT_ENABLE_TIME: 1500
diff --git a/libs/README.md b/libs/README.md
new file mode 100644
index 0000000..e1bbee1
--- /dev/null
+++ b/libs/README.md
@@ -0,0 +1,62 @@
+
+
+# `libs`: Custom Libraries and Drivers for Mynewt
+
+1. [`adc_stm32f1`](adc_stm32f1): Mynewt Driver for ADC on STM32 F103 (Blue Pill). Used by `temp_stm32` internal temperature sensor.
+
+1. [`adc_stm32l4`](adc_stm32l4): Mynewt Driver for ADC on STM32 L476. Used by `temp_stm32` internal temperature sensor.
+
+1. [`bc95g`](bc95g): Mynewt Driver for Quectel BC95 NB-IoT module
+
+1. [`buffered_serial`](buffered_serial): Buffered Serial Library used by `bc95g` NB-IoT driver and `gps_l70r` GPS driver
+
+1. [`custom_sensor`](custom_sensor): Custom Sensor Definitions for Raw Temperature and Geolocation
+
+1. [`esp8266`](esp8266): Mynewt Driver for ESP8266 WiFi module
+
+1. [`gps_l70r`](gps_l70r): Mynewt Driver for Quectel L70-R GPS module
+
+1. [`hmac_prng`](hmac_prng): HMAC pseudorandom number generator with entropy based on internal temperature sensor
+
+1. [`low_power`](low_power): Low Power functions for STM32 F103 (Blue Pill)
+
+1. [`mynewt_rust`](mynewt_rust): Helper functions for hosting Rust on Mynewt
+
+1. [`nrf24l01`](nrf24l01): Mynewt Driver for nRF24L01
+
+1. [`remote_sensor`](remote_sensor): Mynewt Driver for Remote Sensor
+
+1. [`rust_app`](rust_app): Stub library that will be replaced by the compiled Rust application and Rust crates
+
+1. [`rust_libcore`](rust_libcore): Stub library that will be replaced by the Rust Core Library
+
+1. [`semihosting_console`](semihosting_console): Mynewt Console for Arm Semihosting
+
+1. [`sensor_coap`](sensor_coap): Sensor CoAP Library
+
+1. [`sensor_network`](sensor_network): Sensor Network Library
+
+1. [`temp_stm32`](temp_stm32): Mynewt Driver for Internal Temperature Sensor on STM32
+
+1. [`temp_stub`](temp_stub): Mynewt Driver for Stub Temperature Sensor that returns a fixed value
+
+1. [`tiny_gps_plus`](tiny_gps_plus): TinyGPS++ Library ported from Arduino. Used by `gps_l70r` GPS driver.
\ No newline at end of file
diff --git a/libs/pinetime_boot/README.md b/libs/pinetime_boot/README.md
new file mode 100644
index 0000000..b2075e0
--- /dev/null
+++ b/libs/pinetime_boot/README.md
@@ -0,0 +1,3 @@
+# `pinetime_boot`
+
+Mynewt Library for rendering boot graphic and checking for manual rollback
diff --git a/libs/pinetime_boot/include/pinetime_boot/pinetime_boot.h b/libs/pinetime_boot/include/pinetime_boot/pinetime_boot.h
new file mode 100644
index 0000000..4187f22
--- /dev/null
+++ b/libs/pinetime_boot/include/pinetime_boot/pinetime_boot.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// Render boot graphic and check for manual rollback
+#ifndef __PINETIME_BOOT_H__
+#define __PINETIME_BOOT_H__
+#include
+
+#ifdef __cplusplus
+extern "C" { // Expose the types and functions below to C functions.
+#endif
+
+/// Init the display and render the boot graphic. Called by sysinit() during startup, defined in pkg.yml.
+void pinetime_boot_init(void);
+
+/// Write a converted graphic file to SPI Flash
+int pinetime_boot_write_image(void);
+
+/// Display the image in SPI Flash to ST7789 display controller
+int pinetime_boot_display_image(void);
+int pinetime_version_image(void);
+void pinetime_clear_screen(void);
+
+/// Check whether the watch button is pressed
+void pinetime_boot_check_button(void);
+
+int pinetime_boot_display_image_colors(uint16_t color1, uint16_t color2, uint8_t colorLine);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __PINETIME_BOOT_H__
diff --git a/libs/pinetime_boot/include/pinetime_boot/pinetime_delay.h b/libs/pinetime_boot/include/pinetime_boot/pinetime_delay.h
new file mode 100644
index 0000000..c7a048b
--- /dev/null
+++ b/libs/pinetime_boot/include/pinetime_boot/pinetime_delay.h
@@ -0,0 +1,7 @@
+#ifndef PINETIME_RUST_MYNEWT_PINETIME_DELAY_H
+#define PINETIME_RUST_MYNEWT_PINETIME_DELAY_H
+
+void pinetime_delay_us(uint32_t time_us);
+void pinetime_delay_ms(uint32_t ms);
+
+#endif //PINETIME_RUST_MYNEWT_PINETIME_DELAY_H
diff --git a/libs/pinetime_boot/include/pinetime_boot/pinetime_factory.h b/libs/pinetime_boot/include/pinetime_boot/pinetime_factory.h
new file mode 100644
index 0000000..5dfe95b
--- /dev/null
+++ b/libs/pinetime_boot/include/pinetime_boot/pinetime_factory.h
@@ -0,0 +1,7 @@
+#ifndef __PINETIME_FACTORY_H__
+#define __PINETIME_FACTORY_H__
+
+void restore_factory(void);
+
+
+#endif
\ No newline at end of file
diff --git a/libs/pinetime_boot/pkg.yml b/libs/pinetime_boot/pkg.yml
new file mode 100644
index 0000000..a6752bd
--- /dev/null
+++ b/libs/pinetime_boot/pkg.yml
@@ -0,0 +1,40 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Dependencies for this package
+
+pkg.name: libs/pinetime_boot
+pkg.description: Render boot graphic and check for manual rollback
+pkg.author: "Lee Lup Yuen "
+pkg.homepage: "https://github.com/lupyuen"
+pkg.keywords:
+ - prng
+
+pkg.deps:
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/hw/hal"
+
+# Initialisation functions to be called by sysinit() during startup.
+# Mynewt consolidates the initialisation functions into sysinit()
+# and calls them according to the Stage number, highest number first.
+# Stage 500 is used by Sensor Creator so we use Stage 600 onwards.
+# Generated sysinit() for Bootloader: bin/targets/nrf52_boot/generated/src/nrf52_boot-sysinit-app.c
+
+pkg.init:
+ # pinetime_boot should be initialised last, when SPI and Semihosting Console are up
+ pinetime_boot_init: 900 # Call pinetime_boot_init() to initialise and render boot graphic
diff --git a/libs/pinetime_boot/src/blink.c b/libs/pinetime_boot/src/blink.c
new file mode 100644
index 0000000..68a2c48
--- /dev/null
+++ b/libs/pinetime_boot/src/blink.c
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// Blink the backlight for showing bootloader status
+#include
+#include
+#include
+
+#define PUSH_BUTTON_IN 13 // GPIO Pin P0.13: PUSH BUTTON_IN
+
+/// GPIO settings for the backlight: LCD_BACKLIGHT_{LOW,MID,HIGH} (P0.14, 22, 23)
+static const uint8_t backlights[] = {
+ 14, // Low Backlight
+ 22, // Mid Backlight
+ 23, // High Backlight
+};
+
+/// Define pulse patterns from slow to fast: From Low (0) to Mid (1) to High (2) and back
+static const uint8_t slower_pulse[] = {
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2,
+}; // Slower pulse
+static const uint8_t slow_pulse[] = {
+ 1, 1, 1,
+ 0, 0, 0,
+ 1, 1, 1,
+ 2, 2, 2,
+ 2, 2, 2,
+ 2, 2, 2,
+}; // Slow pulse
+static const uint8_t fast_pulse[] = {
+ 1, 1,
+ 0, 0,
+ 1, 1,
+ 2, 2,
+ 2, 2,
+ 2, 2,
+}; // Fast pulse
+static const uint8_t faster_pulse[] = {1, 0, 1, 2, 2, 2}; // Faster pulse
+static const uint8_t fastest_pulse[] = {0, 2, 2}; // Fastest pulse
+
+static void blink_pattern(const uint8_t pattern[], int length);
+static void delay_ms(uint32_t ms);
+
+/// Init the backlights
+static void init_backlight(void) {
+ for (int b = 0; b < sizeof(backlights); b++) {
+ uint8_t gpio = backlights[b];
+ // If High backlight...
+ if (b == 2) {
+ // Switch to on
+ hal_gpio_init_out(gpio, 0);
+ } else {
+ // Switch to off
+ hal_gpio_init_out(gpio, 1);
+ }
+ }
+}
+
+/// Blink the backlight with a pattern for the number of repetitions
+void blink_backlight(int pattern_id, int repetitions) {
+ // Init the backlight the first time
+ static int first_blink = 1;
+ if (first_blink) {
+ first_blink = 0;
+ init_backlight();
+ }
+ for (int i = 0; i < repetitions; i++) {
+ switch (pattern_id) {
+ case 0: blink_pattern(slower_pulse, sizeof(slower_pulse)); break;
+ case 1: blink_pattern(slow_pulse, sizeof(slow_pulse)); break;
+ case 2: blink_pattern(fast_pulse, sizeof(fast_pulse)); break;
+ case 3: blink_pattern(faster_pulse, sizeof(faster_pulse)); break;
+ default: blink_pattern(fastest_pulse, sizeof(fastest_pulse)); break;
+ }
+ }
+}
+
+/// Blink backlight according to the pattern: 0=Low, 1=Mid, 2=High
+static void blink_pattern(const uint8_t pattern[], int length) {
+ for (int i = 0; i < length; i++) {
+ // Switch on the Low, Mid or High backlight. Backlight is active when low
+ uint8_t level = pattern[i];
+ for (int b = 0; b < sizeof(backlights); b++) {
+ uint8_t gpio = backlights[b];
+ // If the Low / Mid / High level matches...
+ if (b == level) {
+ // Switch to on
+ hal_gpio_write(gpio, 0);
+ } else {
+ // Switch to off
+ hal_gpio_write(gpio, 1);
+ }
+ }
+
+ //uint8_t gpio = backlights[level];
+ //hal_gpio_write(gpio, 0);
+
+ // Pause a short while
+ delay_ms(10);
+
+ // Switch off the Low, Mid or High backlight
+ uint8_t gpio = backlights[level];
+ hal_gpio_write(gpio, 1);
+ }
+}
+
+/// Sleep for the specified number of milliseconds
+static void delay_ms(uint32_t ms) {
+ // os_time_delay() doesn't work in MCUBoot because the scheduler has not started
+ uint8_t button_samples = 0;
+ for (int i = 0; i < ms; i++) {
+ for (int delay = 0; delay < 100000; delay++) {}
+ button_samples += hal_gpio_read(PUSH_BUTTON_IN);
+ }
+}
\ No newline at end of file
diff --git a/libs/pinetime_boot/src/display.c b/libs/pinetime_boot/src/display.c
new file mode 100644
index 0000000..b5baa45
--- /dev/null
+++ b/libs/pinetime_boot/src/display.c
@@ -0,0 +1,328 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// Display image on ST7789 display controller (240 x 240)
+#include
+#include "os/mynewt.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "pinetime_boot/pinetime_boot.h"
+#include "pinetime_boot/pinetime_delay.h"
+#include "graphic.h"
+// GPIO Pins. From rust\piet-embedded\piet-embedded-graphics\src\display.rs
+#define DISPLAY_SPI 0 // Mynewt SPI port 0
+#define DISPLAY_CS 25 // LCD_CS (P0.25): Chip select
+#define DISPLAY_DC 18 // LCD_RS (P0.18): Clock/data pin (CD)
+#define DISPLAY_RST 26 // LCD_RESET (P0.26): Display reset
+#define DISPLAY_HIGH 23 // LCD_BACKLIGHT_{LOW,MID,HIGH} (P0.14, 22, 23): Backlight (active low)
+#define BATCH_SIZE 256 // Max number of SPI data bytes to be transmitted
+#define PUSH_BUTTON_IN 13 // GPIO Pin P0.13: PUSH BUTTON_IN
+
+// Screen Size
+#define ROW_COUNT 240
+#define COL_COUNT 240
+#define BYTES_PER_PIXEL 2
+
+// ST7789 Colour Settings
+#define INVERTED 1 // Display colours are inverted
+#define RGB 1 // Display colours are RGB
+
+// Flash Device for Image
+#define FLASH_DEVICE 1 // 0 for Internal Flash ROM, 1 for External SPI Flash
+
+// ST7789 Commands. From https://github.com/lupyuen/st7735-lcd-batch-rs/blob/master/src/instruction.rs
+#define NOP 0x00
+#define SWRESET 0x01
+#define RDDID 0x04
+#define RDDST 0x09
+#define SLPIN 0x10
+#define SLPOUT 0x11
+#define PTLON 0x12
+#define NORON 0x13
+#define INVOFF 0x20
+#define INVON 0x21
+#define DISPOFF 0x28
+#define DISPON 0x29
+#define CASET 0x2A
+#define RASET 0x2B
+#define RAMWR 0x2C
+#define RAMRD 0x2E
+#define PTLAR 0x30
+#define COLMOD 0x3A
+#define MADCTL 0x36
+#define FRMCTR1 0xB1
+#define FRMCTR2 0xB2
+#define FRMCTR3 0xB3
+#define INVCTR 0xB4
+#define DISSET5 0xB6
+#define PWCTR1 0xC0
+#define PWCTR2 0xC1
+#define PWCTR3 0xC2
+#define PWCTR4 0xC3
+#define PWCTR5 0xC4
+#define VMCTR1 0xC5
+#define RDID1 0xDA
+#define RDID2 0xDB
+#define RDID3 0xDC
+#define RDID4 0xDD
+#define PWCTR6 0xFC
+#define GMCTRP1 0xE0
+#define GMCTRN1 0xE1
+
+// ST7789 Orientation. From https://github.com/lupyuen/st7735-lcd-batch-rs/blob/master/src/lib.rs#L52-L58
+#define Portrait 0x00
+#define Landscape 0x60
+#define PortraitSwapped 0xC0
+#define LandscapeSwapped 0xA0
+
+static int init_display(void);
+static int set_window(uint8_t left, uint8_t top, uint8_t right, uint8_t bottom);
+static int hard_reset(void);
+static int set_orientation(uint8_t orientation);
+static int write_command(uint8_t command, const uint8_t *params, uint16_t len);
+static int write_data(const uint8_t *data, uint16_t len);
+static int transmit_spi(const uint8_t *data, uint16_t len);
+
+/// Buffer for reading flash and writing to display
+static uint8_t flash_buffer[240*2];
+
+int pinetime_display_image_colors(struct imgInfo* info, int posx, int posy, uint16_t color1, uint16_t color2, uint8_t colorLine) {
+ int rc;
+ int y = 0;
+ uint16_t bp = 0;
+ uint16_t fg = 0xffff;
+ const uint16_t bg = 0;
+ uint16_t color = bg;
+ uint16_t trueColor = color;
+ for (int i=0; idataSize; i++) {
+ uint8_t rl = info->data[i];
+ while (rl) {
+ flash_buffer[bp] = trueColor >> 8;
+ flash_buffer[bp + 1] = trueColor & 0xff;
+ bp += 2;
+ rl -= 1;
+
+ if (bp >= (info->width*2)) {
+ rc = set_window(posx, y+posy, posx+info->width-1, y+posy); assert(rc == 0);
+
+ // Write Pixels (RAMWR): st7735_lcd::draw() → set_pixel()
+ rc = write_command(RAMWR, NULL, 0); assert(rc == 0);
+ rc = write_data(flash_buffer, info->width*2); assert(rc == 0);
+ bp = 0;
+ y += 1;
+ }
+ }
+
+ if (color == bg) {
+ color = fg;
+ trueColor = (y < colorLine) ? color1 : color2;
+ }
+ else {
+ color = bg;
+ trueColor = color;
+ }
+ if(y >= info->height)
+ break;
+ }
+ return 0;
+}
+
+void pinetime_clear_screen(void) {
+ int rc = 0;
+ for(int i = 0 ; i < 240*2; i++) {
+ flash_buffer[i] = 0;
+ }
+ for(int i = 0; i < 240; i++) {
+ rc = set_window(0, i, 239, i); assert(rc == 0);
+ rc = write_command(RAMWR, NULL, 0); assert(rc == 0);
+ rc = write_data(flash_buffer, 240*2); assert(rc == 0);
+ }
+}
+
+int pinetime_display_image(struct imgInfo* info, int posx, int posy) {
+ return pinetime_display_image_colors(info, posx, posy, 0xffff, 0xffff, 0);
+}
+
+/// Display the image in SPI Flash to ST7789 display controller.
+/// Derived from https://github.com/lupyuen/pinetime-rust-mynewt/blob/main/logs/spi-non-blocking.log
+int pinetime_boot_display_image(void) {
+ console_printf("Displaying boot logo...\n"); console_flush();
+
+ int rc = init_display(); assert(rc == 0);
+ rc = set_orientation(Landscape); assert(rc == 0);
+ pinetime_clear_screen();
+ return pinetime_display_image(&bootLogoInfo, 0, 0);
+}
+
+int pinetime_boot_display_image_colors(uint16_t color1, uint16_t color2, uint8_t colorLine) {
+ return pinetime_display_image_colors(&bootLogoInfo, 0, 0, color1, color2, colorLine);
+}
+
+
+int pinetime_version_image(void) {
+ console_printf("Displaying version image...\n"); console_flush();
+ return pinetime_display_image(&versionInfo, 120 - (versionInfo.width/2), 240 - (versionInfo.height));
+}
+
+/// Set the ST7789 display window to the coordinates (left, top), (right, bottom)
+static int set_window(uint8_t left, uint8_t top, uint8_t right, uint8_t bottom) {
+ assert(left < COL_COUNT && right < COL_COUNT && top < ROW_COUNT && bottom < ROW_COUNT);
+ assert(left <= right);
+ assert(top <= bottom);
+ // Set Address Window Columns (CASET): st7735_lcd::draw() → set_pixel() → set_address_window()
+ int rc = write_command(CASET, NULL, 0); assert(rc == 0);
+ uint8_t col_para[4] = { 0x00, left, 0x00, right };
+ rc = write_data(col_para, 4); assert(rc == 0);
+
+ // Set Address Window Rows (RASET): st7735_lcd::draw() → set_pixel() → set_address_window()
+ rc = write_command(RASET, NULL, 0); assert(rc == 0);
+ uint8_t row_para[4] = { 0x00, top, 0x00, bottom };
+ rc = write_data(row_para, 4); assert(rc == 0);
+ return 0;
+}
+
+/// Runs commands to initialize the display. From https://github.com/lupyuen/st7735-lcd-batch-rs/blob/master/src/lib.rs
+static int init_display(void) {
+ // Assume that SPI port 0 has been initialised by the SPI Flash Driver at startup.
+ int rc;
+ rc = hal_gpio_init_out(DISPLAY_RST, 1); assert(rc == 0);
+ rc = hal_gpio_init_out(DISPLAY_CS, 1); assert(rc == 0);
+ rc = hal_gpio_init_out(DISPLAY_DC, 0); assert(rc == 0);
+ // Switch on backlight
+ rc = hal_gpio_init_out(DISPLAY_HIGH, 0); assert(rc == 0);
+
+ hard_reset();
+ write_command(SWRESET, NULL, 0);
+ pinetime_delay_ms(200);
+ write_command(SLPOUT, NULL, 0);
+ pinetime_delay_ms(200);
+
+ static const uint8_t FRMCTR1_PARA[] = { 0x01, 0x2C, 0x2D };
+ write_command(FRMCTR1, FRMCTR1_PARA, sizeof(FRMCTR1_PARA));
+
+ static const uint8_t FRMCTR2_PARA[] = { 0x01, 0x2C, 0x2D };
+ write_command(FRMCTR2, FRMCTR2_PARA, sizeof(FRMCTR2_PARA));
+
+ static const uint8_t FRMCTR3_PARA[] = { 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D };
+ write_command(FRMCTR3, FRMCTR3_PARA, sizeof(FRMCTR3_PARA));
+
+ static const uint8_t INVCTR_PARA[] = { 0x07 };
+ write_command(INVCTR, INVCTR_PARA, sizeof(INVCTR_PARA));
+
+ static const uint8_t PWCTR1_PARA[] = { 0xA2, 0x02, 0x84 };
+ write_command(PWCTR1, PWCTR1_PARA, sizeof(PWCTR1_PARA));
+
+ static const uint8_t PWCTR2_PARA[] = { 0xC5 };
+ write_command(PWCTR2, PWCTR2_PARA, sizeof(PWCTR2_PARA));
+
+ static const uint8_t PWCTR3_PARA[] = { 0x0A, 0x00 };
+ write_command(PWCTR3, PWCTR3_PARA, sizeof(PWCTR3_PARA));
+
+ static const uint8_t PWCTR4_PARA[] = { 0x8A, 0x2A };
+ write_command(PWCTR4, PWCTR4_PARA, sizeof(PWCTR4_PARA));
+
+ static const uint8_t PWCTR5_PARA[] = { 0x8A, 0xEE };
+ write_command(PWCTR5, PWCTR5_PARA, sizeof(PWCTR5_PARA));
+
+ static const uint8_t VMCTR1_PARA[] = { 0x0E };
+ write_command(VMCTR1, VMCTR1_PARA, sizeof(VMCTR1_PARA));
+
+ if (INVERTED) {
+ write_command(INVON, NULL, 0);
+ } else {
+ write_command(INVOFF, NULL, 0);
+ }
+ if (RGB) {
+ static const uint8_t MADCTL1_PARA[] = { 0x00 };
+ write_command(MADCTL, MADCTL1_PARA, sizeof(MADCTL1_PARA));
+ } else {
+ static const uint8_t MADCTL2_PARA[] = { 0x08 };
+ write_command(MADCTL, MADCTL2_PARA, sizeof(MADCTL2_PARA));
+ }
+ static const uint8_t COLMOD_PARA[] = { 0x05 };
+ write_command(COLMOD, COLMOD_PARA, sizeof(COLMOD_PARA));
+
+ write_command(DISPON, NULL, 0);
+ pinetime_delay_ms(200);
+ return 0;
+}
+
+/// Reset the display controller
+static int hard_reset(void) {
+ hal_gpio_write(DISPLAY_RST, 1);
+ hal_gpio_write(DISPLAY_RST, 0);
+ hal_gpio_write(DISPLAY_RST, 1);
+ return 0;
+}
+
+/// Set the display orientation
+static int set_orientation(uint8_t orientation) {
+ int rc = 0;
+ if (RGB) {
+ uint8_t orientation_para[1] = { orientation };
+ rc = write_command(MADCTL, orientation_para, 1);
+ assert(rc == 0);
+ } else {
+ uint8_t orientation_para[1] = { orientation | 0x08 };
+ rc = write_command(MADCTL, orientation_para, 1);
+ assert(rc == 0);
+ }
+ return rc;
+}
+
+/// Transmit ST7789 command
+static int write_command(uint8_t command, const uint8_t *params, uint16_t len) {
+ hal_gpio_write(DISPLAY_DC, 0);
+ int rc = transmit_spi(&command, 1);
+ assert(rc == 0);
+ if (rc == 0 && (params != NULL && len > 0)) {
+ rc = write_data(params, len);
+ assert(rc == 0);
+ }
+ return 0;
+}
+
+/// Transmit ST7789 data
+static int write_data(const uint8_t *data, uint16_t len) {
+ hal_gpio_write(DISPLAY_DC, 1);
+ transmit_spi(data, len);
+ return 0;
+}
+
+/// Write to the SPI port. From https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/rust/mynewt/src/hal.rs
+static int transmit_spi(const uint8_t *data, uint16_t len) {
+ if (len == 0) { return 0; }
+ // Select the device
+ hal_gpio_write(DISPLAY_CS, 0);
+ // Send the data
+ int rc = hal_spi_txrx(DISPLAY_SPI,
+ (void *) data, // TX Buffer
+ NULL, // RX Buffer (don't receive)
+ len); // Length
+ assert(rc == 0);
+ // De-select the device
+ hal_gpio_write(DISPLAY_CS, 1);
+ return 0;
+}
+
diff --git a/libs/pinetime_boot/src/graphic.h b/libs/pinetime_boot/src/graphic.h
new file mode 100644
index 0000000..2f9e9d5
--- /dev/null
+++ b/libs/pinetime_boot/src/graphic.h
@@ -0,0 +1,150 @@
+#ifndef __GRAPHIC_H__
+#define __GRAPHIC_H__
+
+#include
+struct imgInfo {
+ uint8_t width;
+ uint8_t height;
+ uint16_t dataSize;
+ const uint8_t* data;
+};
+
+static const uint8_t bootLogoRle[] = {
+ 0x78, 0x1, 0xee, 0x3, 0xec, 0x5, 0xea, 0x7, 0xe8, 0x9, 0xe6, 0xb,
+ 0xe5, 0xc, 0xe3, 0xe, 0xe1, 0x10, 0xdf, 0x12, 0xdd, 0x14, 0xdb, 0x16,
+ 0xd9, 0x18, 0xd7, 0x19, 0xd6, 0x1b, 0xd4, 0x1d, 0xd2, 0x1f, 0xd0, 0x21,
+ 0xce, 0x23, 0xcc, 0x25, 0xca, 0x27, 0xc8, 0x29, 0xc6, 0x2b, 0xc4, 0x2d,
+ 0xc2, 0x2f, 0xc0, 0x31, 0xbf, 0x32, 0xbd, 0x34, 0xbb, 0x36, 0xb9, 0x38,
+ 0xb7, 0x39, 0xba, 0x34, 0xbe, 0x2f, 0xc3, 0x2b, 0xc8, 0x25, 0xa7, 0x2,
+ 0x24, 0x21, 0x23, 0x1, 0x85, 0x4, 0x25, 0x1c, 0x22, 0x4, 0x85, 0x6,
+ 0x25, 0x17, 0x23, 0x7, 0x83, 0x9, 0x26, 0x12, 0x23, 0x9, 0x83, 0xc,
+ 0x25, 0xd, 0x24, 0xb, 0x83, 0xe, 0x26, 0x8, 0x24, 0xe, 0x81, 0x11,
+ 0x26, 0x3, 0x24, 0x11, 0x81, 0x13, 0x49, 0x13, 0x81, 0x16, 0x44, 0x16,
+ 0x7f, 0x19, 0x40, 0x18, 0x7f, 0x1b, 0x3b, 0x1b, 0x7f, 0x1d, 0x37, 0x1e,
+ 0x7d, 0x20, 0x33, 0x20, 0x7d, 0x23, 0x2e, 0x23, 0x7b, 0x26, 0x29, 0x26,
+ 0x7b, 0x25, 0x2c, 0x24, 0x7b, 0x23, 0x30, 0x23, 0x79, 0x22, 0x34, 0x21,
+ 0x79, 0x1f, 0x39, 0x1f, 0x79, 0x1d, 0x3d, 0x1e, 0x77, 0x1c, 0x1f, 0x2,
+ 0x20, 0x1c, 0x77, 0x1a, 0x1f, 0x6, 0x20, 0x1a, 0x77, 0x18, 0x1f, 0xa,
+ 0x21, 0x18, 0x75, 0x16, 0x20, 0xf, 0x20, 0x16, 0x75, 0x14, 0x20, 0x13,
+ 0x20, 0x14, 0x75, 0x12, 0x20, 0x17, 0x20, 0x13, 0x73, 0x11, 0x1f, 0x1c,
+ 0x20, 0x11, 0x73, 0xf, 0x1f, 0x20, 0x21, 0xe, 0x73, 0xd, 0x1f, 0x25,
+ 0x20, 0xd, 0x71, 0xc, 0x1f, 0x29, 0x20, 0xb, 0x71, 0x9, 0x1f, 0x2e,
+ 0x20, 0x9, 0x71, 0x7, 0x1f, 0x32, 0x20, 0x8, 0x6f, 0x6, 0x1f, 0x36,
+ 0x20, 0x6, 0x6f, 0x4, 0x1f, 0x3b, 0x1f, 0x4, 0x6f, 0x2, 0x1f, 0x3f,
+ 0x20, 0x2, 0x6d, 0x1, 0x1e, 0x44, 0xaa, 0x48, 0xa6, 0x4c, 0xa2, 0x51,
+ 0x9d, 0x55, 0x99, 0x59, 0x94, 0x5e, 0x90, 0x62, 0x8c, 0x67, 0x87, 0x6b,
+ 0x83, 0x6f, 0x7e, 0x74, 0x7a, 0x78, 0x76, 0x7d, 0x71, 0x81, 0x6d, 0x85,
+ 0x6b, 0x85, 0x6d, 0x81, 0x50, 0x2, 0x1f, 0x7c, 0x21, 0x1, 0x31, 0x4,
+ 0x1f, 0x78, 0x21, 0x3, 0x31, 0x6, 0x20, 0x73, 0x21, 0x5, 0x31, 0x9,
+ 0x1f, 0x6f, 0x20, 0x8, 0x31, 0xb, 0x1f, 0x6b, 0x20, 0xa, 0x31, 0xd,
+ 0x1f, 0x66, 0x21, 0xc, 0x31, 0xf, 0x1f, 0x62, 0x21, 0xe, 0x31, 0x12,
+ 0x1e, 0x5e, 0x20, 0x11, 0x31, 0x14, 0x1f, 0x59, 0x20, 0x13, 0x31, 0x16,
+ 0x1f, 0x55, 0x20, 0x15, 0x31, 0x18, 0x1f, 0x50, 0x20, 0x18, 0x31, 0x1b,
+ 0x1e, 0x4c, 0x20, 0x1a, 0x31, 0x1d, 0x1f, 0x47, 0x20, 0x1c, 0x31, 0x1f,
+ 0x1f, 0x43, 0x20, 0x1e, 0x31, 0x22, 0x1e, 0x3f, 0x1f, 0x21, 0x31, 0x24,
+ 0x1e, 0x3a, 0x20, 0x23, 0x31, 0x26, 0x1e, 0x36, 0x20, 0x25, 0x31, 0x28,
+ 0x1f, 0x31, 0x20, 0x27, 0x31, 0x2b, 0x1e, 0x2d, 0x1f, 0x2a, 0x31, 0x2d,
+ 0x1e, 0x29, 0x1f, 0x2c, 0x31, 0x2f, 0x1e, 0x24, 0x20, 0x2e, 0x31, 0x31,
+ 0x1e, 0x20, 0x1f, 0x31, 0x31, 0x34, 0x1d, 0x1c, 0x1f, 0x33, 0x31, 0x36,
+ 0x1e, 0x17, 0x1f, 0x35, 0x31, 0x38, 0x1e, 0x13, 0x1f, 0x37, 0x31, 0x3b,
+ 0x1d, 0xe, 0x1f, 0x3a, 0x31, 0x3d, 0x1d, 0xa, 0x1f, 0x3c, 0x31, 0x3f,
+ 0x1d, 0x6, 0x1f, 0x3e, 0x31, 0x41, 0x1e, 0x1, 0x1f, 0x40, 0x31, 0x44,
+ 0x38, 0x43, 0x31, 0x46, 0x34, 0x45, 0x31, 0x48, 0x30, 0x47, 0x31, 0x4a,
+ 0x2b, 0x4a, 0x31, 0x4c, 0x28, 0x4b, 0x31, 0x4a, 0x2c, 0x49, 0x31, 0x48,
+ 0x30, 0x47, 0x31, 0x45, 0x36, 0x44, 0x31, 0x43, 0x3a, 0x42, 0x31, 0x41,
+ 0x3e, 0x40, 0x31, 0x3f, 0x20, 0x1, 0x21, 0x3e, 0x31, 0x3c, 0x20, 0x7,
+ 0x21, 0x3b, 0x31, 0x3a, 0x20, 0xb, 0x21, 0x39, 0x31, 0x38, 0x20, 0xf,
+ 0x21, 0x37, 0x31, 0x35, 0x21, 0x13, 0x21, 0x35, 0x31, 0x33, 0x21, 0x17,
+ 0x22, 0x32, 0x31, 0x31, 0x20, 0x1d, 0x21, 0x30, 0x31, 0x2f, 0x20, 0x21,
+ 0x21, 0x2e, 0x31, 0x2c, 0x21, 0x25, 0x22, 0x2b, 0x31, 0x2a, 0x21, 0x29,
+ 0x22, 0x29, 0x31, 0x28, 0x21, 0x2d, 0x22, 0x27, 0x31, 0x26, 0x20, 0x33,
+ 0x21, 0x25, 0x31, 0x23, 0x21, 0x37, 0x22, 0x22, 0x31, 0x21, 0x21, 0x3b,
+ 0x22, 0x20, 0x31, 0x1f, 0x21, 0x3f, 0x22, 0x1e, 0x31, 0x1c, 0x22, 0x43,
+ 0x22, 0x1c, 0x31, 0x1a, 0x22, 0x48, 0x22, 0x19, 0x31, 0x18, 0x21, 0x4d,
+ 0x22, 0x17, 0x31, 0x16, 0x21, 0x51, 0x22, 0x15, 0x31, 0x13, 0x22, 0x55,
+ 0x23, 0x12, 0x31, 0x11, 0x22, 0x59, 0x23, 0x10, 0x31, 0xf, 0x22, 0x5e,
+ 0x22, 0xe, 0x31, 0xd, 0x21, 0x63, 0x22, 0xc, 0x31, 0xa, 0x22, 0x67,
+ 0x23, 0x9, 0x31, 0x8, 0x22, 0x6b, 0x23, 0x7, 0x31, 0x6, 0x22, 0x6f,
+ 0x23, 0x5, 0x31, 0x4, 0x22, 0x74, 0x22, 0x3, 0x31, 0x1, 0x22, 0x79,
+ 0x75, 0x7d, 0x71, 0x81, 0x6d, 0x85, 0x69, 0x8a, 0x63, 0x8f, 0x5f, 0x93,
+ 0x5b, 0x97, 0x58, 0x99, 0x5a, 0x93, 0x26, 0x1, 0x11, 0x3, 0x24, 0x8f,
+ 0x25, 0x3, 0x12, 0x5, 0x24, 0x8b, 0x25, 0x5, 0x13, 0x6, 0x24, 0x87,
+ 0x25, 0x6, 0x14, 0x9, 0x23, 0x83, 0x24, 0x9, 0x15, 0xa, 0x24, 0x7d,
+ 0x25, 0xa, 0x16, 0xd, 0x23, 0x79, 0x24, 0xd, 0x17, 0xe, 0x23, 0x75,
+ 0x24, 0xe, 0x18, 0x10, 0x23, 0x71, 0x24, 0x10, 0x18, 0x13, 0x22, 0x6d,
+ 0x23, 0x13, 0x19, 0x14, 0x23, 0x68, 0x23, 0x14, 0x1a, 0x17, 0x22, 0x63,
+ 0x23, 0x17, 0x1b, 0x18, 0x22, 0x5f, 0x23, 0x18, 0x1c, 0x1a, 0x22, 0x5b,
+ 0x23, 0x1a, 0x1d, 0x1c, 0x21, 0x57, 0x22, 0x1c, 0x1e, 0x1e, 0x22, 0x51,
+ 0x23, 0x1e, 0x1e, 0x20, 0x22, 0x4d, 0x23, 0x20, 0x1f, 0x22, 0x21, 0x49,
+ 0x22, 0x22, 0x20, 0x24, 0x21, 0x45, 0x22, 0x24, 0x21, 0x26, 0x20, 0x41,
+ 0x21, 0x26, 0x22, 0x28, 0x21, 0x3c, 0x21, 0x28, 0x23, 0x29, 0x21, 0x37,
+ 0x22, 0x29, 0x24, 0x2c, 0x20, 0x33, 0x21, 0x2c, 0x25, 0x2d, 0x20, 0x2f,
+ 0x21, 0x2d, 0x26, 0x30, 0x1f, 0x2b, 0x21, 0x2f, 0x26, 0x32, 0x1f, 0x27,
+ 0x20, 0x32, 0x27, 0x33, 0x20, 0x21, 0x21, 0x33, 0x28, 0x36, 0x1f, 0x1d,
+ 0x20, 0x36, 0x29, 0x37, 0x1f, 0x19, 0x20, 0x37, 0x2a, 0x39, 0x1f, 0x15,
+ 0x20, 0x39, 0x2b, 0x3b, 0x1f, 0x10, 0x1f, 0x3b, 0x2c, 0x3d, 0x1f, 0xb,
+ 0x20, 0x3d, 0x2c, 0x40, 0x1e, 0x7, 0x1f, 0x40, 0x2d, 0x41, 0x1e, 0x3,
+ 0x1f, 0x41, 0x2e, 0x43, 0x3c, 0x43, 0x2f, 0x45, 0x36, 0x45, 0x30, 0x47,
+ 0x32, 0x47, 0x31, 0x48, 0x2e, 0x48, 0x32, 0x4b, 0x28, 0x4b, 0x33, 0x49,
+ 0x2a, 0x49, 0x34, 0x47, 0x2e, 0x47, 0x34, 0x45, 0x33, 0x44, 0x35, 0x41,
+ 0x38, 0x41, 0x36, 0x3f, 0x3c, 0x3f, 0x37, 0x3c, 0x40, 0x3c, 0x38, 0x3a,
+ 0x20, 0x2, 0x22, 0x3a, 0x39, 0x36, 0x21, 0x6, 0x23, 0x36, 0x3a, 0x34,
+ 0x21, 0xb, 0x22, 0x34, 0x3b, 0x31, 0x21, 0xf, 0x22, 0x31, 0x3c, 0x2f,
+ 0x21, 0x13, 0x22, 0x2f, 0x3c, 0x2c, 0x21, 0x18, 0x23, 0x2c, 0x3d, 0x29,
+ 0x21, 0x1c, 0x23, 0x29, 0x3e, 0x27, 0x21, 0x21, 0x22, 0x27, 0x3f, 0x24,
+ 0x21, 0x25, 0x22, 0x24, 0x40, 0x21, 0x22, 0x29, 0x23, 0x21, 0x41, 0x1e,
+ 0x21, 0x2e, 0x23, 0x1e, 0x42, 0x1c, 0x21, 0x32, 0x23, 0x1c, 0x42, 0x1a,
+ 0x21, 0x36, 0x23, 0x1a, 0x43, 0x16, 0x22, 0x3b, 0x23, 0x16, 0x44, 0x14,
+ 0x22, 0x3f, 0x23, 0x14, 0x45, 0x11, 0x22, 0x43, 0x23, 0x11, 0x46, 0xf,
+ 0x21, 0x48, 0x23, 0xf, 0x47, 0xb, 0x22, 0x4c, 0x24, 0xb, 0x48, 0x9,
+ 0x22, 0x51, 0x23, 0x9, 0x49, 0x6, 0x22, 0x55, 0x23, 0x6, 0x4a, 0x4,
+ 0x22, 0x59, 0x23, 0x4, 0x4a, 0x1, 0x22, 0x5e, 0x24, 0x1, 0x6b, 0x63,
+ 0x8b, 0x67, 0x87, 0x6b, 0x82, 0x70, 0x7e, 0x74, 0x7a, 0x78, 0x76, 0x7d,
+ 0x71, 0x81, 0x6c, 0x86, 0x6b, 0x84, 0x37,
+};
+
+struct imgInfo bootLogoInfo = {
+ 240,
+ 214,
+ 1086,
+ bootLogoRle
+};
+
+// /home/jf/nrf52/Pinetime/tools/rle_encode.py /home/jf/nrf52/pinetime-rust-mynewt/libs/pinetime_boot/src/version-1.2.3.png --c
+static const uint8_t versionRle[] = {
+ 0x59, 0x56, 0x2, 0x1, 0x3, 0xc, 0x3, 0xa, 0x1, 0x38, 0x2, 0x1,
+ 0x3, 0xc, 0x3, 0x9, 0x2, 0x14, 0x6, 0x13, 0x6, 0x5, 0x2, 0x2,
+ 0x3, 0xb, 0x2, 0xa, 0x2, 0x13, 0x9, 0xf, 0xa, 0x3, 0x2, 0x2,
+ 0x3, 0xa, 0x3, 0x9, 0x3, 0x12, 0x4, 0x3, 0x4, 0xd, 0x5, 0x2,
+ 0x5, 0x2, 0x2, 0x2, 0x3, 0xa, 0x3, 0x6, 0x6, 0x11, 0x3, 0x6,
+ 0x4, 0xc, 0x3, 0x6, 0x3, 0x2, 0x2, 0x3, 0x3, 0x9, 0x2, 0x6,
+ 0x7, 0x11, 0x3, 0x7, 0x3, 0xc, 0x2, 0x8, 0x2, 0x2, 0x2, 0x3,
+ 0x3, 0x8, 0x3, 0x6, 0x7, 0x11, 0x2, 0x9, 0x2, 0xb, 0x3, 0x8,
+ 0x3, 0x1, 0x2, 0x4, 0x2, 0x8, 0x3, 0xb, 0x2, 0x11, 0x2, 0x9,
+ 0x2, 0xb, 0x3, 0x8, 0x2, 0x2, 0x2, 0x4, 0x3, 0x7, 0x2, 0xc,
+ 0x2, 0x1b, 0x3, 0x15, 0x3, 0x2, 0x2, 0x4, 0x3, 0x6, 0x3, 0xc,
+ 0x2, 0x1b, 0x3, 0x14, 0x4, 0x2, 0x2, 0x5, 0x3, 0x5, 0x3, 0xc,
+ 0x2, 0x1a, 0x3, 0x12, 0x5, 0x4, 0x2, 0x5, 0x3, 0x5, 0x2, 0xd,
+ 0x2, 0x19, 0x4, 0x12, 0x6, 0x3, 0x2, 0x5, 0x3, 0x4, 0x3, 0xd,
+ 0x2, 0x17, 0x4, 0x18, 0x3, 0x2, 0x2, 0x6, 0x3, 0x3, 0x3, 0xd,
+ 0x2, 0x15, 0x5, 0x1a, 0x3, 0x1, 0x2, 0x6, 0x3, 0x3, 0x2, 0xe,
+ 0x2, 0x13, 0x5, 0x1c, 0x3, 0x1, 0x2, 0x6, 0x3, 0x2, 0x3, 0xe,
+ 0x2, 0x12, 0x4, 0x13, 0x3, 0x8, 0x3, 0x1, 0x2, 0x7, 0x3, 0x1,
+ 0x3, 0xe, 0x2, 0x12, 0x3, 0x14, 0x3, 0x8, 0x3, 0x1, 0x2, 0x7,
+ 0x3, 0x1, 0x2, 0xf, 0x2, 0x11, 0x3, 0x15, 0x3, 0x8, 0x3, 0x1,
+ 0x2, 0x7, 0x6, 0xf, 0x2, 0x11, 0x2, 0x17, 0x3, 0x6, 0x4, 0x1,
+ 0x2, 0x8, 0x5, 0xf, 0x2, 0xa, 0x3, 0x3, 0xe, 0x5, 0x3, 0x4,
+ 0x5, 0x2, 0x5, 0x2, 0x2, 0x8, 0x4, 0x10, 0x2, 0xa, 0x3, 0x3,
+ 0xe, 0x5, 0x3, 0x5, 0xa, 0x3, 0x2, 0x9, 0x3, 0x10, 0x2, 0xa,
+ 0x3, 0x3, 0xe, 0x5, 0x3, 0x7, 0x6, 0x5, 0x2, 0x56, 0x59,
+
+};
+
+struct imgInfo versionInfo = {
+ 88,
+ 26,
+ 299,
+ versionRle
+};
+
+#endif
\ No newline at end of file
diff --git a/libs/pinetime_boot/src/pinetime_boot.c b/libs/pinetime_boot/src/pinetime_boot.c
new file mode 100644
index 0000000..7eb2dd2
--- /dev/null
+++ b/libs/pinetime_boot/src/pinetime_boot.c
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+// Render boot graphic and check for manual rollback
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bootutil/image.h"
+#include
+#include "pinetime_boot/pinetime_boot.h"
+#include "pinetime_boot/pinetime_factory.h"
+#include "pinetime_boot/pinetime_delay.h"
+
+#define PUSH_BUTTON_IN 13 // GPIO Pin P0.13: PUSH BUTTON_IN
+#define PUSH_BUTTON_OUT 15 // GPIO Pin P0.15/TRACEDATA2: PUSH BUTTON_OUT
+
+/// Vector Table will be relocated here.
+#define RELOCATED_VECTOR_TABLE 0x7F00
+
+/// Number of entries in the Vector Table.
+#define NVIC_NUM_VECTORS (16 + 38)
+
+/// Address of the VTOR Register in the System Control Block.
+#define SCB_VTOR ((uint32_t *) 0xE000ED08)
+
+void blink_backlight(int pattern_id, int repetitions); // Defined in blink.c
+static void relocate_vector_table(void *vector_table, void *relocated_vector_table);
+
+/// Init the display and render the boot graphic. Called by sysinit() during startup, defined in pkg.yml.
+void pinetime_boot_init(void) {
+ console_printf("Starting Bootloader...\n"); console_flush();
+
+ // Init the push button. The button on the side of the PineTime is disabled by default. To enable it, drive the button out pin (P0.15) high.
+ // While enabled, the button in pin (P0.13) will be high when the button is pressed, and low when it is not pressed.
+ hal_gpio_init_in(PUSH_BUTTON_IN, HAL_GPIO_PULL_DOWN);
+ hal_gpio_init_out(PUSH_BUTTON_OUT, 1);
+ hal_gpio_write(PUSH_BUTTON_OUT, 1); // Enable the button
+ // blink_backlight(1, 1);
+
+ // Display the image.
+ pinetime_boot_display_image();
+
+ // Display version image
+ pinetime_version_image();
+
+ // Wait 5 seconds for button press.
+ uint32_t button_samples = 0;
+ console_printf("Waiting 5 seconds for button...\n"); console_flush();
+ for (int i = 0; i < 64 * 5; i++) {
+ for (int delay = 0; delay < 3000; delay++) {
+ button_samples += hal_gpio_read(PUSH_BUTTON_IN);
+ }
+ if(i % 64 == 0) {
+ console_printf("step %d - %d\n", (i / (64)) + 1, (int)button_samples); console_flush();
+ }
+
+ if(i % 8 == 0) {
+ uint16_t color = 0xF800;
+ if (button_samples < 3000 * 64 * 2) {
+ color = 0x07E0;
+ } else if (button_samples < 3000 * 64 * 4) {
+ color = 0x001F;
+ } else {
+ color = 0xF800;
+ }
+
+ pinetime_boot_display_image_colors(0xffff, color, 240 - ((i / 8) * 6) + 1);
+ }
+ }
+ console_printf("Waited 5 seconds (%d)\n", (int)button_samples); console_flush();
+
+ // Check whether button is pressed and held. Sample count must high enough to avoid accidental rollbacks.
+ if(button_samples > (3000 * 64 * 4)) {
+ console_printf("Restoring factory firmware\n"); console_flush();
+ restore_factory();
+ }
+
+ if(button_samples > (3000 * 64 * 2)) {
+ console_printf("Flashing secondary firmware into primary\n"); console_flush();
+
+ // Mark the previous firmware for rollback and blink slowly 4 times.
+ boot_set_pending(0);
+ blink_backlight(2, 4);
+
+ // Restart for MCUBoot to rollback the firmware.
+ hal_system_reset();
+ return;
+ } else {
+ console_printf("MCUBoot processing...\n"); console_flush();
+ }
+}
+
+void setup_watchdog() {
+ NRF_WDT->CONFIG &= ~(WDT_CONFIG_SLEEP_Msk << WDT_CONFIG_SLEEP_Pos);
+ NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Run << WDT_CONFIG_SLEEP_Pos);
+
+ NRF_WDT->CONFIG &= ~(WDT_CONFIG_HALT_Msk << WDT_CONFIG_HALT_Pos);
+ NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos);
+
+ /* timeout (s) = (CRV + 1) / 32768 */
+ const int timeoutSeconds = 7; // 7 seconds
+ uint32_t crv = (((timeoutSeconds*1000u) << 15u) / 1000) - 1;
+ NRF_WDT->CRV = crv;
+
+ /* Enable reload requests */
+ NRF_WDT->RREN = (WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos);
+
+ /* Start */
+ NRF_WDT->TASKS_START = 1;
+}
+
+
+
+/// Called by MCUBoot when it has completed its work.
+void boot_custom_start(
+ uintptr_t flash_base,
+ struct boot_rsp *rsp
+) {
+ // blink_backlight(2, 2);
+ console_printf("Bootloader done\n"); console_flush();
+
+ // vector_table points to the Arm Vector Table for the appplication...
+ // First word contains initial MSP value (estack = end of RAM)
+ // Second word contains address of entry point (Reset_Handler)
+ void *vector_table = (void *) ( // Copied from MCUBoot main()
+ flash_base + // 0
+ rsp->br_image_off + // Offset of FLASH_AREA_IMAGE_0 (application image): 0x8000
+ rsp->br_hdr->ih_hdr_size // Size of MCUBoot image header (0x20)
+ ); // Equals 0x8020 (__isr_vector)
+ // console_printf("vector_table=%lx, flash_base=%lx, image_off=%lx, hdr_size=%lx\n", (uint32_t) vector_table, (uint32_t) flash_base, (uint32_t) rsp->br_image_off, (uint32_t) rsp->br_hdr->ih_hdr_size); console_flush();
+
+ // Relocate the application vector table to a 0x100 page boundary in ROM.
+ relocate_vector_table( // Relocate the vector table...
+ vector_table, // From the non-aligned application address (0x8020)
+ (void *) RELOCATED_VECTOR_TABLE // To the relocated address aligned to 0x100 page boundary
+ );
+ // blink_backlight(3, 4);
+
+ setup_watchdog();
+
+ // Start the Active Firmware Image at the Reset_Handler function.
+ hal_system_start(vector_table);
+}
+
+/// Relocate the Arm Vector Table from vector_table to relocated_vector_table.
+/// relocated_vector_table must be aligned to 0x100 page boundary.
+static void relocate_vector_table(void *vector_table, void *relocated_vector_table) {
+ uint32_t *current_location = (uint32_t *) vector_table;
+ uint32_t *new_location = (uint32_t *) relocated_vector_table;
+ if (new_location == current_location) { return; } // No need to relocate
+ // Check whether we need to copy the vectors.
+ int vector_diff = 0; // Non-zero if a vector is different
+ for (int i = 0; i < NVIC_NUM_VECTORS; i++) {
+ if (new_location[i] != current_location[i]) {
+ vector_diff = 1;
+ break;
+ }
+ }
+ // If we need to copy the vectors, erase the flash ROM and write the vectors.
+ if (vector_diff) {
+ hal_flash_erase( // Erase...
+ 0, // Internal Flash ROM
+ (uint32_t) relocated_vector_table, // At the relocated address
+ 0x100 // Assume that we erase an entire page
+ );
+ hal_flash_write( // Write...
+ 0, // Internal Flash ROM
+ (uint32_t) relocated_vector_table, // To the relocated address
+ vector_table, // From the original address
+ 0x100 // Assume that we copy an entire page
+ );
+ }
+ // Point VTOR Register in the System Control Block to the relocated vector table.
+ *SCB_VTOR = (uint32_t) relocated_vector_table;
+}
+
+/// Blink 4 times and reboot
+static void blink_and_restart() {
+ // Blink the screen quickly 4 times
+ blink_backlight(4, 4);
+ // Then reboot, which fixes the SPI Bus
+ NVIC_SystemReset();
+}
+
+/// In case of Non-Maskable Interrupt (e.g. assertion failure), blink 4 times and reboot.
+/// Assertion failure may be due to SPI Bus corruption, which causes SPI Flash access to fail in spiflash_identify() in repos/apache-mynewt-core/hw/drivers/flash/spiflash/src/spiflash.c
+void NMI_Handler() {
+ // Blink and restart
+ blink_and_restart();
+}
+
+/// In case of Hard Fault, blink 4 times and reboot
+void HardFault_Handler() {
+ // Blink and restart
+ blink_and_restart();
+}
+
+/* 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
+*/
diff --git a/libs/pinetime_boot/src/pinetime_delay.c b/libs/pinetime_boot/src/pinetime_delay.c
new file mode 100644
index 0000000..1db1b46
--- /dev/null
+++ b/libs/pinetime_boot/src/pinetime_delay.c
@@ -0,0 +1,35 @@
+#include
+
+#include "pinetime_boot/pinetime_delay.h"
+
+void pinetime_delay_us(uint32_t time_us) {
+#define NRFX_COREDEP_DELAY_US_LOOP_CYCLES 3
+#define NRFX_DELAY_CPU_FREQ_MHZ 64
+ __ALIGN(16)
+ static const uint16_t delay_machine_code[] = {
+ 0x3800 + NRFX_COREDEP_DELAY_US_LOOP_CYCLES, // SUBS r0, #loop_cycles
+ 0xd8fd, // BHI .-2
+ 0x4770 // BX LR
+ };
+
+ typedef void (* delay_func_t)(uint32_t);
+ const delay_func_t delay_cycles =
+ // Set LSB to 1 to execute the code in the Thumb mode.
+ (delay_func_t)((((uint32_t)delay_machine_code) | 1));
+ uint32_t cycles = time_us * NRFX_DELAY_CPU_FREQ_MHZ;
+ delay_cycles(cycles);
+}
+
+/// Sleep for the specified number of milliseconds
+void pinetime_delay_ms(uint32_t ms) {
+#if MYNEWT_VAL(OS_SCHEDULING) // If Task Scheduler is enabled (i.e. not MCUBoot)...
+ uint32_t delay_ticks = ms * OS_TICKS_PER_SEC / 1000;
+ os_time_delay(delay_ticks);
+#else // If Task Scheduler is disabled (i.e. MCUBoot)...
+
+ do {
+ pinetime_delay_us(1000);
+ } while (--ms);
+
+#endif // MYNEWT_VAL(OS_SCHEDULING)
+}
diff --git a/libs/pinetime_boot/src/pinetime_factory.c b/libs/pinetime_boot/src/pinetime_factory.c
new file mode 100644
index 0000000..f954cf5
--- /dev/null
+++ b/libs/pinetime_boot/src/pinetime_factory.c
@@ -0,0 +1,29 @@
+#include "pinetime_boot/pinetime_factory.h"
+#include
+#include "os/mynewt.h"
+
+// Flash Device for Image
+#define FLASH_DEVICE 1 // 0 for Internal Flash ROM, 1 for External SPI Flash
+
+/// Buffer for reading flash and writing to display
+#define BATCH_SIZE 256 // Max number of SPI data bytes to be transmitted
+static uint8_t flash_buffer[BATCH_SIZE];
+
+#define FACTORY_SIZE 0x40000
+#define FACTORY_OFFSET_SOURCE 0
+#define FACTORY_OFFSET_DESTINATION 0x40000
+
+
+void restore_factory(void) {
+ int rc;
+ for (uint32_t erased = 0; erased < FACTORY_SIZE; erased += 0x1000) {
+ rc = hal_flash_erase_sector(FLASH_DEVICE, FACTORY_OFFSET_DESTINATION + erased);
+ }
+
+ for(uint32_t offset = 0; offset < FACTORY_SIZE; offset += BATCH_SIZE) {
+ rc = hal_flash_read(FLASH_DEVICE, FACTORY_OFFSET_SOURCE + offset, flash_buffer, BATCH_SIZE);
+ assert(rc == 0);
+ rc = hal_flash_write(FLASH_DEVICE, FACTORY_OFFSET_DESTINATION + offset, flash_buffer, BATCH_SIZE);
+ assert(rc == 0);
+ }
+}
diff --git a/libs/pinetime_boot/src/version-1.2.3.png b/libs/pinetime_boot/src/version-1.2.3.png
new file mode 100644
index 0000000..e1ff9e2
Binary files /dev/null and b/libs/pinetime_boot/src/version-1.2.3.png differ
diff --git a/libs/pinetime_boot/src/version-1.2.3.xcf b/libs/pinetime_boot/src/version-1.2.3.xcf
new file mode 100644
index 0000000..5c480ec
Binary files /dev/null and b/libs/pinetime_boot/src/version-1.2.3.xcf differ
diff --git a/libs/pinetime_boot/syscfg.yml b/libs/pinetime_boot/syscfg.yml
new file mode 100644
index 0000000..2520c0d
--- /dev/null
+++ b/libs/pinetime_boot/syscfg.yml
@@ -0,0 +1,5 @@
+# System Configuration Setting Definitions:
+# Below are the settings defined by this package and their default values.
+# Strings must be enclosed by '"..."'
+
+syscfg.defs:
diff --git a/libs/semihosting_console/.gitignore b/libs/semihosting_console/.gitignore
new file mode 100644
index 0000000..ff4c547
--- /dev/null
+++ b/libs/semihosting_console/.gitignore
@@ -0,0 +1,33 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+.app.db
+.app
+bin
+obj
+tags
+.gdb_history
+.gdb_out
+.gdb_cmds
+.gdbinit
+*~
+.DS_Store
+*.swp
+*.swo
+
diff --git a/libs/semihosting_console/README.md b/libs/semihosting_console/README.md
new file mode 100644
index 0000000..b5084da
--- /dev/null
+++ b/libs/semihosting_console/README.md
@@ -0,0 +1,8 @@
+# `semihosting_console`
+
+Mynewt Library that implements the `console` interface for displaying
+messages on the Arm Semihosting console. It works with Blue Pill connected
+via STLink V2 and OpenOCD.
+
+All messages are cached in memory until `console_flush()` is called,
+or when the console enters blocking mode.
diff --git a/libs/semihosting_console/include/console/console.h b/libs/semihosting_console/include/console/console.h
new file mode 100644
index 0000000..4150f61
--- /dev/null
+++ b/libs/semihosting_console/include/console/console.h
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef __SEMIHOSTING_CONSOLE_H__
+#define __SEMIHOSTING_CONSOLE_H__
+
+#include
+#include "os/mynewt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_eventq;
+
+/** @struct console_input
+ * The console_input data structure represents a console input buffer.
+ *
+ * Each event added to the console avail_queue must have the
+ * ev_arg field point to a console_input structure.
+ */
+struct console_input {
+ /** Data buffer that the console uses to save received
+ * characters until a new line is received. */
+ char line[MYNEWT_VAL(CONSOLE_MAX_INPUT_LEN)];
+};
+
+typedef void (*console_rx_cb)(void);
+typedef int (*console_append_char_cb)(char *line, uint8_t byte);
+typedef void (*completion_cb)(char *str, console_append_char_cb cb);
+
+// Implemented only for Semihosting Console.
+void console_buffer(const char *buffer, unsigned int length); // Add the string to the output buffer.
+void console_printhex(uint8_t v); // Write a char in hexadecimal to the output buffer.
+void console_printint(int i); // Write an int i the output buffer.
+void console_printfloat(float f); // Write a float to the output buffer, with 2 decimal places.
+void console_printdouble(double f); // Write a double to the output buffer, with 6 decimal places.
+void console_dump(const uint8_t *buffer, unsigned int len); // Append "length" number of bytes from "buffer" to the output buffer in hex format.
+void console_flush(void); // Flush the output buffer to the console.
+
+void console_deinit(void);
+void console_reinit(void);
+int console_init(console_rx_cb rx_cb);
+int console_is_init(void);
+void console_write(const char *str, int cnt);
+void console_blocking_mode(void);
+void console_non_blocking_mode(void);
+void console_echo(int on);
+
+int console_printf(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));;
+
+void console_set_completion_cb(completion_cb cb);
+int console_handle_char(uint8_t byte);
+
+/* Set queue to send console line events to */
+void console_line_queue_set(struct os_eventq *evq);
+/* Put (handled) line event to console */
+void console_line_event_put(struct os_event *ev);
+/**
+ * Global indicating whether console is silent or not
+ */
+extern bool g_silence_console;
+/**
+ * Global indicating whether console input is disabled or not
+ */
+extern bool g_console_input_ignore;
+
+
+/**
+ * Silences console output, input is still active
+ *
+ * @param silent Let console know if it needs to be silent,
+ * true for silence, false otherwise
+ */
+static void inline
+console_silence(bool silent)
+{
+ g_silence_console = silent;
+}
+
+
+/**
+ * Ignores console input, output is still active
+ *
+ * @param ignore Lets console know if input should be disabled,
+ * true for ignore input, false otherwise
+ */
+static void inline
+console_input_ignore(bool ignore)
+{
+ g_console_input_ignore = ignore;
+}
+
+extern int console_is_midline;
+extern int console_out(int character);
+extern void console_rx_restart(void);
+
+int console_lock(int timeout);
+int console_unlock(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SEMIHOSTING_CONSOLE_H__ */
diff --git a/libs/semihosting_console/include/console/prompt.h b/libs/semihosting_console/include/console/prompt.h
new file mode 100644
index 0000000..ab5518b
--- /dev/null
+++ b/libs/semihosting_console/include/console/prompt.h
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __CONSOLE_PROMPT_H__
+#define __CONSOLE_PROMPT_H__
+
+#include
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* print console prompt */
+static void inline
+console_print_prompt(void)
+{
+}
+
+/* set the console prompt character */
+static void inline
+console_set_prompt(char ch)
+{
+}
+
+static void inline
+console_no_prompt(void)
+{
+}
+
+static void inline
+console_yes_prompt(void)
+{
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONSOLE_PROMPT_H__ */
diff --git a/libs/semihosting_console/include/console/ticks.h b/libs/semihosting_console/include/console/ticks.h
new file mode 100644
index 0000000..eebdac7
--- /dev/null
+++ b/libs/semihosting_console/include/console/ticks.h
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __CONSOLE_TICKS_H__
+#define __CONSOLE_TICKS_H__
+
+#include
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void console_no_ticks(void);
+
+void console_yes_ticks(void);
+
+char console_get_ticks(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONSOLE_PROMPT_H__ */
diff --git a/libs/semihosting_console/pkg.yml b/libs/semihosting_console/pkg.yml
new file mode 100644
index 0000000..f76b22b
--- /dev/null
+++ b/libs/semihosting_console/pkg.yml
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: "libs/semihosting_console"
+pkg.description: "IO interface based on Arm Semihosting"
+pkg.author: "Lee Lup Yuen "
+pkg.homepage: "https://github.com/lupyuen"
+pkg.keywords:
+
+pkg.deps:
+ - "@apache-mynewt-core/hw/hal"
+ - "@apache-mynewt-core/kernel/os"
+pkg.apis: console
+
+pkg.init:
+ console_pkg_init: 'MYNEWT_VAL(CONSOLE_SYSINIT_STAGE)'
diff --git a/libs/semihosting_console/src/console.c b/libs/semihosting_console/src/console.c
new file mode 100644
index 0000000..09c6805
--- /dev/null
+++ b/libs/semihosting_console/src/console.c
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "os/mynewt.h"
+#include "os/os_task.h"
+#include "console/console.h"
+#include "console/ticks.h"
+#include "console_priv.h"
+
+/* Control characters */
+#define ESC 0x1b
+#define DEL 0x7f
+#define BS 0x08
+
+/* ANSI escape sequences */
+#define ANSI_ESC '['
+#define ANSI_UP 'A'
+#define ANSI_DOWN 'B'
+#define ANSI_FORWARD 'C'
+#define ANSI_BACKWARD 'D'
+#define ANSI_END 'F'
+#define ANSI_HOME 'H'
+#define ANSI_DEL '~'
+
+#define ESC_ESC (1 << 0)
+#define ESC_ANSI (1 << 1)
+#define ESC_ANSI_FIRST (1 << 2)
+#define ESC_ANSI_VAL (1 << 3)
+#define ESC_ANSI_VAL_2 (1 << 4)
+
+#define CONSOLE_NLIP_PKT_START1 (6)
+#define CONSOLE_NLIP_PKT_START2 (9)
+#define CONSOLE_NLIP_DATA_START1 (4)
+#define CONSOLE_NLIP_DATA_START2 (20)
+
+#define NLIP_PKT_START1 (1 << 0)
+#define NLIP_PKT_START2 (1 << 1)
+#define NLIP_DATA_START1 (1 << 2)
+#define NLIP_DATA_START2 (1 << 3)
+
+/* Indicates whether the previous line of output was completed. */
+int console_is_midline;
+
+static int echo = MYNEWT_VAL(CONSOLE_ECHO);
+static bool rx_stalled;
+
+static struct os_eventq avail_queue;
+static struct os_eventq *lines_queue;
+static completion_cb completion;
+bool g_silence_console;
+bool g_console_input_ignore;
+static struct os_mutex console_write_lock;
+
+/*
+ * Default implementation in case all consoles are disabled - we just ignore any
+ * output to console.
+ */
+int __attribute__((weak)) console_out_nolock(int c) {
+ return c;
+}
+
+void console_echo(int on) { echo = on; }
+
+int console_lock(int timeout) { return OS_OK; }
+
+int console_unlock(void) { return OS_OK; }
+
+int console_out(int c) { return console_out_nolock(c); }
+
+void console_write(const char *str, int cnt) {
+ int i;
+ for (i = 0; i < cnt; i++) {
+ if (console_out_nolock((int)str[i]) == EOF) { break; }
+ }
+}
+
+void console_blocking_mode(void) {
+ disable_buffer();
+}
+
+void console_non_blocking_mode(void) {
+ enable_buffer();
+}
+
+static inline void cursor_forward(unsigned int count) {
+ console_printf("\x1b[%uC", count);
+}
+
+static inline void cursor_backward(unsigned int count) {
+ console_printf("\x1b[%uD", count);
+}
+
+static inline void cursor_save(void) {
+ console_out(ESC);
+ console_out('[');
+ console_out('s');
+}
+
+static inline void cursor_restore(void) {
+ console_out(ESC);
+ console_out('[');
+ console_out('u');
+}
+
+int console_handle_char(uint8_t byte) { return 0; }
+
+int console_is_init(void) {
+#if MYNEWT_VAL(CONSOLE_SEMIHOSTING)
+ return semihosting_console_is_init();
+#endif
+ return 0;
+}
+
+void console_line_queue_set(struct os_eventq *evq) {
+ lines_queue = evq;
+}
+
+void console_line_event_put(struct os_event *ev) {
+ os_eventq_put(&avail_queue, ev);
+ if (rx_stalled) {
+ rx_stalled = false;
+ console_rx_restart();
+ }
+}
+
+void console_set_completion_cb(completion_cb cb) {
+ completion = cb;
+}
+
+void console_deinit(void) {}
+
+void console_reinit(void) {}
+
+void console_pkg_init(void) {
+ int rc = 0;
+
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ os_eventq_init(&avail_queue);
+ os_mutex_init(&console_write_lock);
+
+#if MYNEWT_VAL(CONSOLE_SEMIHOSTING)
+ rc = semihosting_console_init();
+#endif
+ SYSINIT_PANIC_ASSERT(rc == 0);
+}
diff --git a/libs/semihosting_console/src/console_fmt.c b/libs/semihosting_console/src/console_fmt.c
new file mode 100644
index 0000000..1377e43
--- /dev/null
+++ b/libs/semihosting_console/src/console_fmt.c
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include
+#include "os/mynewt.h"
+#include "console/console.h"
+#include "console/ticks.h"
+
+#define CONS_OUTPUT_MAX_LINE 128
+
+#if MYNEWT_VAL(BASELIBC_PRESENT)
+
+/**
+ * Prints the specified format string to the console.
+ *
+ * @return The number of characters that would have been
+ * printed if the console buffer were
+ * unlimited. This return value is analogous
+ * to that of snprintf.
+ */
+int
+console_printf(const char *fmt, ...)
+{
+ va_list args;
+ int num_chars;
+
+ num_chars = 0;
+
+ if (console_get_ticks()) {
+ /* Prefix each line with a timestamp. */
+ if (!console_is_midline) {
+ num_chars += printf("%06lu ", (unsigned long)os_time_get());
+ }
+ }
+
+ va_start(args, fmt);
+ num_chars += vprintf(fmt, args);
+ va_end(args);
+
+ return num_chars;
+}
+
+
+#else
+
+/**
+ * Prints the specified format string to the console.
+ *
+ * @return The number of characters that would have been
+ * printed if the console buffer were
+ * unlimited. This return value is analogous
+ * to that of snprintf.
+ */
+int
+console_printf(const char *fmt, ...)
+{
+ va_list args;
+ char buf[CONS_OUTPUT_MAX_LINE];
+ int num_chars;
+ int len;
+
+ num_chars = 0;
+
+ if (console_get_ticks()) {
+ /* Prefix each line with a timestamp. */
+ if (!console_is_midline) {
+ len = snprintf(buf, sizeof(buf), "%06lu ",
+ (unsigned long)os_time_get());
+ num_chars += len;
+ console_write(buf, len);
+ }
+ }
+
+ va_start(args, fmt);
+ len = vsnprintf(buf, sizeof(buf), fmt, args);
+ num_chars += len;
+ if (len >= sizeof(buf)) {
+ len = sizeof(buf) - 1;
+ }
+ console_write(buf, len);
+ va_end(args);
+
+ return num_chars;
+}
+#endif
diff --git a/libs/semihosting_console/src/console_priv.h b/libs/semihosting_console/src/console_priv.h
new file mode 100644
index 0000000..9ec0c97
--- /dev/null
+++ b/libs/semihosting_console/src/console_priv.h
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __SEMIHOSTING_CONSOLE_PRIV_H__
+#define __SEMIHOSTING_CONSOLE_PRIV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int semihosting_console_is_init(void);
+int semihosting_console_init(void);
+void enable_buffer(void); // Enable buffering.
+void disable_buffer(void); // Disable buffering.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SEMIHOSTING_CONSOLE_PRIV_H__ */
diff --git a/libs/semihosting_console/src/semihosting_console.c b/libs/semihosting_console/src/semihosting_console.c
new file mode 100644
index 0000000..da3fa84
--- /dev/null
+++ b/libs/semihosting_console/src/semihosting_console.c
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include
+
+#if MYNEWT_VAL(CONSOLE_SEMIHOSTING)
+#include
+#include
+
+#include "console/console.h"
+#include "console_priv.h"
+
+#if MYNEWT_VAL(CONSOLE_INPUT)
+static struct hal_timer semihosting_timer;
+#endif
+
+#define OUTPUT_BUFFER_SIZE 2048 // Use a larger buffer size so that we don't affect interrupt processing.
+static bool log_enabled = true; // Logging is on by default.
+static bool buffer_enabled = true; // Buffering is on by default.
+
+void enable_log(void) { log_enabled = true; }
+void disable_log(void) { log_enabled = false; }
+void enable_buffer(void) { buffer_enabled = true; } // Enable buffering.
+void disable_buffer(void) { buffer_enabled = false; console_flush(); } // Disable buffering.
+static void split_float(float f, bool *neg, int *i, int *d);
+static void split_double(double f, bool *neg, int *i, int *d);
+
+#ifndef DISABLE_SEMIHOSTING // If Arm Semihosting is enabled...
+
+// ARM Semihosting code from
+// http://www.keil.com/support/man/docs/ARMCC/armcc_pge1358787046598.htm
+// http://www.keil.com/support/man/docs/ARMCC/armcc_pge1358787048379.htm
+// http://www.keil.com/support/man/docs/ARMCC/armcc_chr1359125001592.htm
+// https://wiki.dlang.org/Minimal_semihosted_ARM_Cortex-M_%22Hello_World%22
+
+static int __semihost(int command, void* message) {
+ // Send an ARM Semihosting command to the debugger, e.g. to print a message.
+ // To see the message you need to run opencd:
+ // openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -f scripts/debug.ocd
+
+ // Warning: This code will trigger a breakpoint and hang unless a debugger is connected.
+ // That's how ARM Semihosting sends a command to the debugger to print a message.
+ // This code MUST be disabled on production devices.
+ if (!log_enabled) return -1;
+ __asm(
+ "mov r0, %[cmd] \n"
+ "mov r1, %[msg] \n"
+ "bkpt #0xAB \n"
+ : // Output operand list: (nothing)
+ : // Input operand list:
+ [cmd] "r" (command),
+ [msg] "r" (message)
+ : // Clobbered register list:
+ "r0", "r1", "memory"
+ );
+ return 0; // TODO
+}
+
+// ARM Semihosting code from https://github.com/ARMmbed/mbed-os/blob/master/platform/mbed_semihost_api.c
+
+// ARM Semihosting Commands
+// #define SYS_OPEN (0x1)
+// #define SYS_CLOSE (0x2)
+#define SYS_WRITE (0x5)
+// #define SYS_READ (0x6)
+// #define SYS_ISTTY (0x9)
+// #define SYS_SEEK (0xa)
+// #define SYS_ENSURE (0xb)
+// #define SYS_FLEN (0xc)
+// #define SYS_REMOVE (0xe)
+// #define SYS_RENAME (0xf)
+// #define SYS_EXIT (0x18)
+
+static int debugger_connected(void) {
+ // Return non-zero if debugger is connected. From repos/apache-mynewt-core/hw/mcu/ambiq/apollo2/src/hal_system.c
+ return CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk;
+}
+#endif // !DISABLE_SEMIHOSTING
+
+// We normally set the file handle to 2 to write to the debugger's stderr output.
+#define SEMIHOST_HANDLE 2
+
+static int semihost_write(uint32_t fh, const unsigned char *buffer, unsigned int length) {
+ // Write "length" number of bytes from "buffer" to the debugger's file handle fh.
+ // We normally set fh=2 to write to the debugger's stderr output.
+#ifdef DISABLE_SEMIHOSTING // If Arm Semihosting is disabled...
+ return 0; // Don't write debug messages.
+#else // If Arm Semihosting is enabled...
+ if (!debugger_connected()) { return 0; } // If debugger is not connected, quit.
+ if (length == 0) { return 0; }
+ uint32_t args[3];
+ args[0] = (uint32_t)fh;
+ args[1] = (uint32_t)buffer;
+ args[2] = (uint32_t)length;
+ return __semihost(SYS_WRITE, args);
+#endif // DISABLE_SEMIHOSTING
+}
+
+static struct os_mbuf *semihost_mbuf = NULL;
+
+void console_flush(void) {
+ // Flush output buffer to the console log. This will be slow.
+ if (!log_enabled) { return; } // Skip if log not enabled.
+ if (!semihost_mbuf) { return; } // Buffer is empty, nothing to write.
+ if (os_arch_in_isr()) { return; } // Don't flush if we are called during an interrupt.
+
+ // Swap mbufs first to prevent concurrency problems.
+ struct os_mbuf *old = semihost_mbuf;
+ semihost_mbuf = NULL;
+
+ struct os_mbuf *m = old;
+ while (m) { // For each mbuf in the chain...
+ const unsigned char *data = OS_MBUF_DATA(m, const unsigned char *); // Fetch the data.
+ int size = m->om_len; // Fetch the size.
+ semihost_write(SEMIHOST_HANDLE, data, size); // Write the data to Semihosting output.
+ m = m->om_next.sle_next; // Fetch next mbuf in the chain.
+ }
+ if (old) { os_mbuf_free_chain(old); } // Deallocate the old chain.
+}
+
+void console_buffer(const char *buffer, unsigned int length) {
+ // Append "length" number of bytes from "buffer" to the output buffer.
+#ifdef DISABLE_SEMIHOSTING // If Arm Semihosting is disabled...
+ return; // Don't write debug messages.
+#else // If Arm Semihosting is enabled...
+ int rc;
+ if (!log_enabled) { return; } // Skip if log not enabled.
+ if (!debugger_connected()) { return; } // If debugger is not connected, quit.
+ if (!semihost_mbuf) { // Allocate mbuf if not already allocated.
+ semihost_mbuf = os_msys_get_pkthdr(length, 0);
+ if (!semihost_mbuf) { return; } // If out of memory, quit.
+ }
+ // Limit the buffer size. Quit if too big.
+ if (os_mbuf_len(semihost_mbuf) + length >= OUTPUT_BUFFER_SIZE) { return; }
+ // Append the data to the mbuf chain. This may increase the numbere of mbufs in the chain.
+ rc = os_mbuf_append(semihost_mbuf, buffer, length);
+ if (rc) { return; } // If out of memory, quit.
+#endif // DISABLE_SEMIHOSTING
+}
+
+void console_printhex(uint8_t v) {
+ // Write a char in hexadecimal to the output buffer.
+ #define MAX_BYTE_LENGTH 2
+ char buffer[MAX_BYTE_LENGTH + 1];
+ int size = MAX_BYTE_LENGTH + 1;
+ bool prefixByZero = true;
+ int length = 0;
+ for(uint8_t divisor = 16; divisor >= 1; divisor = divisor / 16) {
+ char digit = '0' + (char)(v / divisor);
+ if (digit > '9') { digit = digit - 10 - '0' + 'a'; }
+ if (digit > '0' || length > 0 || prefixByZero) {
+ if (length < size) {
+ buffer[length++] = digit;
+ }
+ }
+ v = v % divisor;
+ }
+ if (length == 0) { buffer[length++] = '0'; };
+ if (length < size) buffer[length] = 0;
+ buffer[size - 1] = 0; // Terminate in case of overflow.
+ console_buffer(buffer, strlen(buffer));
+}
+
+void console_printint(int i) {
+ // Write an int i the output buffer.
+ console_printf("%d", i);
+}
+
+void console_printfloat(float f) {
+ // Write a float to the output buffer, with 2 decimal places.
+ bool neg; int i, d;
+ split_float(f, &neg, &i, &d); // Split the float into neg, integer and decimal parts to 2 decimal places
+ console_printf("%s%d.%02d", neg ? "-" : "", i, d); // Combine the sign, integer and decimal parts
+}
+
+void console_printdouble(double f) {
+ // Write a double to the output buffer, with 6 decimal places.
+ bool neg; int i, d;
+ split_double(f, &neg, &i, &d); // Split the double into neg, integer and decimal parts to 6 decimal places
+ console_printf("%s%d.%06d", neg ? "-" : "", i, d); // Combine the sign, integer and decimal parts
+}
+
+void console_dump(const uint8_t *buffer, unsigned int len) {
+ // Append "length" number of bytes from "buffer" to the output buffer in hex format.
+ if (buffer == NULL || len == 0) { return; }
+ for (int i = 0; i < len; i++) { console_printhex(buffer[i]); console_buffer(" ", 1); }
+}
+
+static void split_float(float f, bool *neg, int *i, int *d) {
+ // Split the float f into 3 parts: neg is true if negative, the absolute integer part i, and the decimal part d, with 2 decimal places.
+ *neg = (f < 0.0f); // True if f is negative
+ float f_abs = *neg ? -f : f; // Absolute value of f
+ *i = (int) f_abs; // Integer part
+ *d = ((int) (100.0f * f_abs)) % 100; // Two decimal places
+}
+
+static void split_double(double f, bool *neg, int *i, int *d) {
+ // Split the double f into 3 parts: neg is true if negative, the absolute integer part i, and the decimal part d, with 6 decimal places.
+ *neg = (f < 0.0f); // True if f is negative
+ float f_abs = *neg ? -f : f; // Absolute value of f
+ *i = (int) f_abs; // Integer part
+ *d = ((int) (1000000.0f * f_abs)) % 1000000; // 6 decimal places
+}
+
+static void semihosting_console_write_ch(char c) {
+ if (c == '\r') { return; } // Don't display \r.
+ console_buffer(&c, 1); // Append the char to the output buffer.
+ // if (c == '\n') { console_flush(); } // If we see a newline, flush the buffer.
+}
+
+int console_out_nolock(int character) {
+ char c = (char)character;
+ if (g_silence_console) { return c; }
+ if ('\n' == c) {
+ semihosting_console_write_ch('\r');
+ console_is_midline = 0;
+ } else {
+ console_is_midline = 1;
+ }
+ semihosting_console_write_ch(c);
+ return character;
+}
+
+void console_rx_restart(void) {}
+
+int semihosting_console_is_init(void) { return 1; }
+
+int semihosting_console_init(void) { return 0; }
+
+#endif /* MYNEWT_VAL(CONSOLE_SEMIHOSTING) */
diff --git a/libs/semihosting_console/src/ticks.c b/libs/semihosting_console/src/ticks.c
new file mode 100644
index 0000000..3d59b94
--- /dev/null
+++ b/libs/semihosting_console/src/ticks.c
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/mynewt.h"
+#include "console/console.h"
+#include "console/prompt.h"
+
+static char do_ticks = MYNEWT_VAL(CONSOLE_TICKS);
+
+/* Turn OS Ticks off */
+void
+console_no_ticks(void)
+{
+ do_ticks = 0;
+}
+
+/* Turn OS Ticks on */
+void
+console_yes_ticks(void)
+{
+ do_ticks = 1;
+}
+
+/* return value of CONSOLE_TICKS */
+char console_get_ticks(void)
+{
+ return do_ticks;
+}
+
diff --git a/libs/semihosting_console/syscfg.yml b/libs/semihosting_console/syscfg.yml
new file mode 100644
index 0000000..3edd899
--- /dev/null
+++ b/libs/semihosting_console/syscfg.yml
@@ -0,0 +1,74 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.defs:
+ CONSOLE_SEMIHOSTING:
+ description: 'Set console output to Semihosting'
+ value: 1
+ CONSOLE_INPUT:
+ description: 'Enable console input'
+ value: 0
+ CONSOLE_TICKS:
+ description: 'Print OS Ticks'
+ value: 0
+ CONSOLE_ECHO:
+ description: 'Default console echo'
+ value: 0
+ CONSOLE_COMPAT:
+ description: 'Console backward compatibility'
+ value: 1
+ CONSOLE_MAX_INPUT_LEN:
+ description: 'Maximum input line length'
+ value: 256
+ CONSOLE_HISTORY_SIZE:
+ description: >
+ Number of lines to be stored in console history.
+ Set to "0" to disable console history.
+ value: 0
+
+ CONSOLE_SEMIHOSTING_RETRY_COUNT:
+ description: >
+ Number of retries to write data in case buffer is full. This allows
+ to wait for host to read data from buffer in case there's a lot of
+ data to write which do not fit in buffer.
+ value: 2
+ CONSOLE_SEMIHOSTING_RETRY_DELAY_MS:
+ description: >
+ Delay (in miliseconds) between each write retry.
+ value: 2
+ CONSOLE_SEMIHOSTING_RETRY_IN_ISR:
+ description: >
+ Set to non-zero to enable write retries also in ISR.
+ value: 0
+ CONSOLE_SEMIHOSTING_INPUT_POLL_INTERVAL_MAX:
+ description: >
+ Maximum interval (milliseconds) to poll for RTT input.
+ With no new data on RTT input, interval to poll for new data will
+ be gradually increased up to specified value. Using high interval
+ value may affect RTT console responsiveness, using small value may
+ affect device performance due to more frequent polling.
+ value: 250
+
+ CONSOLE_DEFAULT_LOCK_TIMEOUT:
+ description: 'Default timeout (in ms) for console_lock() function used in console_write.'
+ value: 1000
+
+ CONSOLE_SYSINIT_STAGE:
+ description: >
+ Sysinit stage for console functionality.
+ value: 20
diff --git a/project.yml b/project.yml
new file mode 100644
index 0000000..6cc29e7
--- /dev/null
+++ b/project.yml
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+project.name: "my_project"
+
+project.repositories:
+ - apache-mynewt-core
+ - mcuboot
+
+# Use github's distribution mechanism for core ASF libraries.
+# This provides mirroring automatically for us.
+#
+repository.apache-mynewt-core:
+ type: github
+ vers: 1.8.0
+ user: apache
+ repo: mynewt-core
+
+repository.mcuboot:
+ type: github
+ vers: 1.5.0
+ user: JuulLabs-OSS
+ repo: mcuboot
diff --git a/scripts/nrf52/build-boot.cmd b/scripts/nrf52/build-boot.cmd
new file mode 100644
index 0000000..ce11cac
--- /dev/null
+++ b/scripts/nrf52/build-boot.cmd
@@ -0,0 +1,7 @@
+:: Build Mynewt bootloader on Windows
+
+:: Build the bootloader.
+newt\newt.exe build nrf52_boot
+
+:: Show the size.
+newt\newt.exe size -v nrf52_boot
diff --git a/scripts/nrf52/build-boot.sh b/scripts/nrf52/build-boot.sh
new file mode 100755
index 0000000..5922623
--- /dev/null
+++ b/scripts/nrf52/build-boot.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Build Mynewt bootloader on macOS and Linux
+
+set -e # Exit when any command fails.
+set -x # Echo all commands.
+
+# Show the Arm Toolchain version.
+arm-none-eabi-gcc --version
+
+# Build the bootloader.
+newt build nrf52_boot
+
+# Show the size.
+newt size -v nrf52_boot
+
+# Copy the disassembler and linker map to the logs folder. For Stub Bootloader, select "bin/targets/nrf52_boot/app/apps/boot_stub/boot_stub.elf.*"
+cp bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf.lst logs
+cp bin/targets/nrf52_boot/app/boot/mynewt/mynewt.elf.map logs
diff --git a/targets/nrf52_boot/pkg.yml b/targets/nrf52_boot/pkg.yml
new file mode 100644
index 0000000..86f1e29
--- /dev/null
+++ b/targets/nrf52_boot/pkg.yml
@@ -0,0 +1,35 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# MCUBoot Package Settings
+pkg.name: targets/nrf52_boot
+pkg.type: target
+pkg.description:
+pkg.author:
+pkg.homepage:
+
+# Package Dependencies: MCUBoot is dependent on these drivers and libraries.
+pkg.deps:
+ - "libs/semihosting_console" # Semihosting Console
+ - "libs/pinetime_boot" # Render boot graphic and check for rollback. Comment out for Stub Bootloader.
+
+# C compiler flags
+pkg.cflags:
+ - -DMCUBOOT_HAVE_LOGGING=1 # So that sysinit() will be run, needed for displaying boot graphic
+ - -DDISABLE_SEMIHOSTING # Uncomment to disable Arm Semihosting. Must be uncommented for production.
+ # - -Os # Optimise for smallest size
diff --git a/targets/nrf52_boot/syscfg.yml b/targets/nrf52_boot/syscfg.yml
new file mode 100644
index 0000000..cb4a9d5
--- /dev/null
+++ b/targets/nrf52_boot/syscfg.yml
@@ -0,0 +1,52 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# MCUBoot Bootloader Settings
+
+syscfg.vals:
+ BOOT_CUSTOM_START: 1 # Use custom boot function boot_custom_start()
+ OS_MAIN_STACK_SIZE: 1024 # Small stack size: 4 KB
+ MSYS_1_BLOCK_COUNT: 64 # Allocate MSYS buffers for Semihosting Console
+ HAL_ENABLE_SOFTWARE_BREAKPOINTS: 0 # In case of assertion failure, don't breakpoint. Must be set to 0 so that bootloader will reboot and won't hang in case of assertion failures.
+ MCU_DEBUG_IGNORE_BKPT: 1
+
+ ###########################################################################
+ # Hardware Settings
+
+ SPIFLASH: 1 # Enable SPI Flash
+ SPI_0_MASTER: 1 # Enable SPI port 0 for ST7789 display and SPI Flash
+ I2C_1: 0 # Disable I2C port 1 for CST816S touch controller, BMA421 accelerometer, HRS3300 heart rate sensor
+ UART_0: 0 # Disable UART port to reduce ROM size
+
+ ###########################################################################
+ # Common Settings for minimal ROM size
+
+ CONSOLE_COMPAT: 0 # Disable console input
+ CONSOLE_RTT: 0 # Disable RTT Console
+ CONSOLE_UART: 0 # Disable UART Console
+ LOG_CLI: 0 # Disable logging command-line interface
+ LOG_LEVEL: 255 # Disable logs
+ SENSOR_CLI: 0 # Disable sensor command-line interface
+ SENSOR_OIC: 0 # Disable sensor OIC functions
+ SHELL_CMD_HELP: 0 # Disable shell help
+ SHELL_OS_MODULE: 0 # Disable shell module
+ SHELL_TASK: 0 # Disable shell task
+ STATS_CLI: 0 # Disable statistics command-line interface
+ OS_SYSVIEW_TRACE_CALLOUT: 0 # Disable trace of callouts
+ OS_SYSVIEW_TRACE_EVENTQ: 0 # Disable trace of event queues
+ OS_SYSVIEW_TRACE_MUTEX: 0 # Disable trace of mutex
+ OS_SYSVIEW_TRACE_SEM: 0 # Disable trace of semaphores
\ No newline at end of file
diff --git a/targets/nrf52_boot/target.yml b/targets/nrf52_boot/target.yml
new file mode 100644
index 0000000..a0952e9
--- /dev/null
+++ b/targets/nrf52_boot/target.yml
@@ -0,0 +1,12 @@
+# Bootloader Target Settings
+
+# Bootloader will be based on MCUBoot. Select "apps/boot_stub" for the Stub Bootloader.
+target.app: "@mcuboot/boot/mynewt" # Use MCUBoot, which doesn't support debugging
+# target.app: "apps/boot_stub" # Use Stub Bootloader, which supports debugging
+
+# Board Support Package (BSP) for the target
+target.bsp: "hw/bsp/nrf52"
+
+# Build with debug support. Or select "optimized" to remove debug support.
+#target.build_profile: debug # For debugging
+target.build_profile: optimized # For production