Fix markdown format with autoformatter (#1284)
This commit is contained in:
parent
c495db8a71
commit
c2b6a8de3e
|
@ -1,7 +1,6 @@
|
|||
# VS Code Dev Container
|
||||
This is a docker-based interactive development environment using VS Code and Docker Dev Containers removing the need to install any tools locally*
|
||||
|
||||
|
||||
This is a docker-based interactive development environment using VS Code and Docker Dev Containers removing the need to install any tools locally\*
|
||||
|
||||
## Requirements
|
||||
|
||||
|
@ -16,45 +15,41 @@ This is a docker-based interactive development environment using VS Code and Doc
|
|||
|
||||
1. Clone InfiniTime and update submodules
|
||||
2. Launch VS Code
|
||||
3. Open InfiniTime directory,
|
||||
4. Allow VS Code to open folder with devcontainer.
|
||||
3. Open InfiniTime directory,
|
||||
4. Allow VS Code to open folder with devcontainer.
|
||||
|
||||
After this the environment will be built if you do not currently have a container setup, it will install all the necessary tools and extra VSCode extensions.
|
||||
After this the environment will be built if you do not currently have a container setup, it will install all the necessary tools and extra VSCode extensions.
|
||||
|
||||
In order to build InfiniTime we need to run the initial submodule init and CMake commands.
|
||||
|
||||
#### Manually
|
||||
#### Manually
|
||||
|
||||
You can use the VS Code terminal to run the CMake commands as outlined in the [build instructions](blob/develop/doc/buildAndProgram.md)
|
||||
You can use the VS Code terminal to run the CMake commands as outlined in the [build instructions](blob/develop/doc/buildAndProgram.md)
|
||||
|
||||
#### Script
|
||||
|
||||
The dev environment comes with some scripts to make this easier, They are located in /opt/.
|
||||
|
||||
There are also VS Code tasks provided should you desire to use those.
|
||||
There are also VS Code tasks provided should you desire to use those.
|
||||
|
||||
The task "update submodules" will update the git submodules
|
||||
|
||||
|
||||
|
||||
### Build
|
||||
|
||||
You can use the build.sh script located in /opt/
|
||||
|
||||
CMake is also configured and controls for the CMake plugin are available in VS Code
|
||||
|
||||
|
||||
|
||||
### Debugging
|
||||
|
||||
Docker on windows does not support passing USB devices to the underlying WSL2 subsystem, To get around this we use OpenOCD in server mode running on the host.
|
||||
|
||||
`openocd -f <yourinterface> -f <nrf52.cfg target file>`
|
||||
|
||||
This will launch OpenOCD in server mode and attach it to the MCU.
|
||||
This will launch OpenOCD in server mode and attach it to the MCU.
|
||||
|
||||
The default launch.json file expects OpenOCD to be listening on port 3333, edit if needed
|
||||
|
||||
|
||||
## Current Issues
|
||||
Currently WSL2 Has some real performance issues with IO on a windows host. Accessing files on the virtualized filesystem is much faster. Using VS Codes "clone in container" feature of the Remote - Containers will get around this. After the container is built you will need to update the submodules and follow the build instructions like normal
|
||||
|
||||
Currently WSL2 Has some real performance issues with IO on a windows host. Accessing files on the virtualized filesystem is much faster. Using VS Codes "clone in container" feature of the Remote - Containers will get around this. After the container is built you will need to update the submodules and follow the build instructions like normal
|
||||
|
|
75
README.md
75
README.md
|
@ -8,64 +8,65 @@ Fast open-source firmware for the [PineTime smartwatch](https://www.pine64.org/p
|
|||
|
||||
## New to InfiniTime?
|
||||
|
||||
- [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md)
|
||||
- [Updating the software](doc/gettingStarted/updating-software.md)
|
||||
- [About the firmware and bootloader](doc/gettingStarted/about-software.md)
|
||||
- [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md)
|
||||
- [Updating the software](doc/gettingStarted/updating-software.md)
|
||||
- [About the firmware and bootloader](doc/gettingStarted/about-software.md)
|
||||
|
||||
### Companion apps
|
||||
|
||||
- [Gadgetbridge](https://gadgetbridge.org/) (Android)
|
||||
- [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS)
|
||||
- [Siglo](https://github.com/alexr4535/siglo) (Linux)
|
||||
- [InfiniLink](https://github.com/InfiniTimeOrg/InfiniLink) (iOS) **[Looking for a new maintainer]**
|
||||
- [ITD](https://gitea.arsenm.dev/Arsen6331/itd) (Linux)
|
||||
- [Gadgetbridge](https://gadgetbridge.org/) (Android)
|
||||
- [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS)
|
||||
- [Siglo](https://github.com/alexr4535/siglo) (Linux)
|
||||
- [InfiniLink](https://github.com/InfiniTimeOrg/InfiniLink) (iOS) **[Looking for a new maintainer]**
|
||||
- [ITD](https://gitea.arsenm.dev/Arsen6331/itd) (Linux)
|
||||
|
||||
## Development
|
||||
|
||||
- [InfiniTime Vision](doc/InfiniTimeVision.md)
|
||||
- [Rough structure of the code](doc/code/Intro.md)
|
||||
- [How to implement an application](doc/code/Apps.md)
|
||||
- [Generate the fonts and symbols](src/displayapp/fonts/README.md)
|
||||
- [Tips on designing an app UI](doc/ui_guidelines.md)
|
||||
- [Bootloader, OTA and DFU](bootloader/README.md)
|
||||
- [Versioning](doc/versioning.md)
|
||||
- [Project branches](doc/branches.md)
|
||||
- [Files included in the release notes](doc/filesInReleaseNotes.md)
|
||||
- [InfiniTime Vision](doc/InfiniTimeVision.md)
|
||||
- [Rough structure of the code](doc/code/Intro.md)
|
||||
- [How to implement an application](doc/code/Apps.md)
|
||||
- [Generate the fonts and symbols](src/displayapp/fonts/README.md)
|
||||
- [Tips on designing an app UI](doc/ui_guidelines.md)
|
||||
- [Bootloader, OTA and DFU](bootloader/README.md)
|
||||
- [Versioning](doc/versioning.md)
|
||||
- [Project branches](doc/branches.md)
|
||||
- [Files included in the release notes](doc/filesInReleaseNotes.md)
|
||||
|
||||
### Contributing
|
||||
|
||||
- [How to contribute?](doc/contribute.md)
|
||||
- [Coding conventions](doc/coding-convention.md)
|
||||
- [How to contribute?](doc/contribute.md)
|
||||
- [Coding conventions](doc/coding-convention.md)
|
||||
|
||||
### Build, flash and debug
|
||||
|
||||
- [InfiniTime simulator](https://github.com/InfiniTimeOrg/InfiniSim)
|
||||
- [Build the project](doc/buildAndProgram.md)
|
||||
- [Build the project with Docker](doc/buildWithDocker.md)
|
||||
- [Build the project with VSCode](doc/buildWithVScode.md)
|
||||
- [Flash the firmware using OpenOCD and STLinkV2](doc/openOCD.md)
|
||||
- [Flash the firmware using SWD interface](doc/SWD.md)
|
||||
- [Flash the firmware using JLink](doc/jlink.md)
|
||||
- [Flash the firmware using GDB](doc/gdb.md)
|
||||
- [Stub using NRF52-DK](doc/PinetimeStubWithNrf52DK.md)
|
||||
- [InfiniTime simulator](https://github.com/InfiniTimeOrg/InfiniSim)
|
||||
- [Build the project](doc/buildAndProgram.md)
|
||||
- [Build the project with Docker](doc/buildWithDocker.md)
|
||||
- [Build the project with VSCode](doc/buildWithVScode.md)
|
||||
- [Flash the firmware using OpenOCD and STLinkV2](doc/openOCD.md)
|
||||
- [Flash the firmware using SWD interface](doc/SWD.md)
|
||||
- [Flash the firmware using JLink](doc/jlink.md)
|
||||
- [Flash the firmware using GDB](doc/gdb.md)
|
||||
- [Stub using NRF52-DK](doc/PinetimeStubWithNrf52DK.md)
|
||||
|
||||
### API
|
||||
|
||||
- [BLE implementation and API](doc/ble.md)
|
||||
- [BLE implementation and API](doc/ble.md)
|
||||
|
||||
### Architecture and technical topics
|
||||
|
||||
- [Memory analysis](doc/MemoryAnalysis.md)
|
||||
- [Memory analysis](doc/MemoryAnalysis.md)
|
||||
|
||||
## Licenses
|
||||
|
||||
This project is released under the GNU General Public License version 3 or, at your option, any later version.
|
||||
|
||||
It integrates the following projects:
|
||||
- RTOS : **[FreeRTOS](https://freertos.org)** under the MIT license
|
||||
- UI : **[LittleVGL/LVGL](https://lvgl.io/)** under the MIT license
|
||||
- BLE stack : **[NimBLE](https://github.com/apache/mynewt-nimble)** under the Apache 2.0 license
|
||||
- Font : **[Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)** under the Apache 2.0 license
|
||||
|
||||
- RTOS : **[FreeRTOS](https://freertos.org)** under the MIT license
|
||||
- UI : **[LittleVGL/LVGL](https://lvgl.io/)** under the MIT license
|
||||
- BLE stack : **[NimBLE](https://github.com/apache/mynewt-nimble)** under the Apache 2.0 license
|
||||
- Font : **[Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)** under the Apache 2.0 license
|
||||
|
||||
## Credits
|
||||
|
||||
|
@ -73,6 +74,6 @@ I’m not working alone on this project. First, many people create PR for this p
|
|||
|
||||
Here are some people I would like to highlight:
|
||||
|
||||
- [Atc1441](https://github.com/atc1441/) : He works on an Arduino based firmware for the Pinetime and many other smartwatches based on similar hardware. He was of great help when I was implementing support for the BMA421 motion sensor and I²C driver.
|
||||
- [Koen](https://github.com/bosmoment) : He’s working on a firmware based on RiotOS. He integrated similar libs as me : NimBLE, LittleVGL,… His help was invaluable too!
|
||||
- [Lup Yuen Lee](https://github.com/lupyuen) : He is everywhere: he works on a Rust firmware, builds a MCUBoot based bootloader for the Pinetime, designs a Flutter based companion app for smartphones and writes a lot of articles about the Pinetime!
|
||||
- [Atc1441](https://github.com/atc1441/) : He works on an Arduino based firmware for the Pinetime and many other smartwatches based on similar hardware. He was of great help when I was implementing support for the BMA421 motion sensor and I²C driver.
|
||||
- [Koen](https://github.com/bosmoment) : He’s working on a firmware based on RiotOS. He integrated similar libs as me : NimBLE, LittleVGL,… His help was invaluable too!
|
||||
- [Lup Yuen Lee](https://github.com/lupyuen) : He is everywhere: he works on a Rust firmware, builds a MCUBoot based bootloader for the Pinetime, designs a Flutter based companion app for smartphones and writes a lot of articles about the Pinetime!
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# About this bootloader
|
||||
|
||||
The [bootloader](https://github.com/lupyuen/pinetime-rust-mynewt/tree/master/libs/pinetime_boot/src) is mostly developed by [Lup Yuen](https://github.com/lupyuen). It is based on [MCUBoot](https://www.mcuboot.com) and [Mynewt](https://mynewt.apache.org/).
|
||||
|
||||
The goal of this project is to provide a common bootloader for multiple (all?) Pinetime projects. It allows to upgrade the current bootloader and even replace the current application by another one that supports the same bootloader.
|
||||
|
@ -12,6 +13,7 @@ When it is run, this bootloader looks in the SPI flash memory if a new firmware
|
|||
As this bootloader does not provide any OTA capability, it is not able to actually download a new version of the application. Providing OTA functionality is thus the responsibility of the application firmware.
|
||||
|
||||
# About MCUBoot
|
||||
|
||||
MCUBoot is run at boot time. In normal operation, it just jumps to the reset handler of the application firmware to run it. Once the application firmware is running, MCUBoot does not run at all.
|
||||
|
||||
![MCUBoot boot sequence diagram](../doc/bootloader/boot.png "MCUBoot boot sequence diagram")
|
||||
|
@ -19,8 +21,9 @@ MCUBoot is run at boot time. In normal operation, it just jumps to the reset han
|
|||
But MCUBoot does much more than that : it can upgrade the firmware that is currently running by a new one, and it is also able to revert to the previous version of the firmware in case the new one does not run properly.
|
||||
|
||||
To do this, it uses 2 memory 'slots' :
|
||||
- **The primary slot** : it contains the current firmware, the one that will be executed by MCUBoot
|
||||
- **The secondary slot** : it is used to store the upgraded version of the firmware, when available.
|
||||
|
||||
- **The primary slot** : it contains the current firmware, the one that will be executed by MCUBoot
|
||||
- **The secondary slot** : it is used to store the upgraded version of the firmware, when available.
|
||||
|
||||
At boot time, MCUBoot detects that a new version of the firmware is available in the secondary slot and swaps them : the current version of the firmware is copied from the primary to the secondary slot and vice-versa.
|
||||
|
||||
|
@ -35,6 +38,7 @@ The next time MCUBoot will be run (after a MCU reset), MCUBoot will check if the
|
|||
Note than MCUBoot **does not** provide any means to download and store the new version of the firmware into the secondary slot. This must be implemented by the application firmware.
|
||||
|
||||
# Degraded cases
|
||||
|
||||
This chapter describes degraded cases that are handled by our bootloader and those that are not supported.
|
||||
|
||||
Case | Current bootloader | Solution
|
||||
|
@ -50,72 +54,73 @@ New firmware does not run properly but sets the valid bit and refreshes the watc
|
|||
# Using the bootloader
|
||||
|
||||
## Bootloader graphic
|
||||
|
||||
The bootloader loads a graphic (Pinetime logo) from the SPI Flash memory. If this graphic is not loaded in the memory, the LCD will display garbage (the content of the SPI flash memory).
|
||||
|
||||
The SPI Flash memory is not accessible via the SWD debugger. Use the firmware 'pinetime-graphics' to load the graphic into memory. All you have to do is build it and program it at address 0x00 :
|
||||
|
||||
- Build:
|
||||
```
|
||||
$ make pinetime-graphics
|
||||
- Build:
|
||||
|
||||
```sh
|
||||
make pinetime-graphics
|
||||
```
|
||||
|
||||
- Program (using OpenOCD for example) :
|
||||
- Program (using OpenOCD for example) :
|
||||
|
||||
```
|
||||
program pinetime-graphics.bin 0
|
||||
```
|
||||
|
||||
- Let it run for ~10s (it does nothing for 5 seconds, then write the logo into the SPI memory, then (slowly) displays it on the LCD).
|
||||
- Let it run for ~10s (it does nothing for 5 seconds, then write the logo into the SPI memory, then (slowly) displays it on the LCD).
|
||||
|
||||
## Bootloader binary
|
||||
|
||||
The binary comes from https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v5.0.4
|
||||
|
||||
It must be flash at address **0x00** in the internal flash memory.
|
||||
|
||||
Using OpenOCD:
|
||||
|
||||
`
|
||||
program bootloader-5.0.4.bin 0
|
||||
`
|
||||
`program bootloader-5.0.4.bin 0`
|
||||
|
||||
## Application firmware image
|
||||
|
||||
Build the binary compatible with the booloader:
|
||||
|
||||
`
|
||||
make pinetime-mcuboot-app
|
||||
`
|
||||
`make pinetime-mcuboot-app`
|
||||
|
||||
The binary is located in *<build directory>/src/pinetime-mcuboot-app.bin*.
|
||||
|
||||
It must me converted into a MCUBoot image using *imgtool.py* from [MCUBoot](https://github.com/mcu-tools/mcuboot/tree/master/scripts). Simply checkout the project and run the script <mcuboot root>/scripts/imgtool.py with the following command line:
|
||||
|
||||
`
|
||||
imgtool.py create --align 4 --version 1.0.0 --header-size 32 --slot-size 475136 --pad-header <build directory>/src/pinetime-mcuboot-app.bin image.bin
|
||||
`
|
||||
```sh
|
||||
imgtool.py create --align 4 --version 1.0.0 --header-size 32 --slot-size 475136 --pad-header <build directory>/src/pinetime-mcuboot-app.bin image.bin
|
||||
```
|
||||
|
||||
The image must be then flashed at address **0x8000** in the internal flash memory.
|
||||
|
||||
Using OpenOCD:
|
||||
|
||||
`
|
||||
program image.bin 0x8000
|
||||
`
|
||||
`program image.bin 0x8000`
|
||||
|
||||
## OTA and DFU
|
||||
|
||||
Pack the image into a .zip file for the NRF DFU protocol:
|
||||
|
||||
`
|
||||
```sh
|
||||
adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application image.bin dfu.zip
|
||||
`
|
||||
```
|
||||
|
||||
Use NRFConnect or dfu.py (in <project root>/bootloader/ota-dfu-python) to upload the zip file to the device:
|
||||
|
||||
`
|
||||
```sh
|
||||
sudo dfu.py -z /home/jf/nrf52/bootloader/dfu.zip -a <pinetime MAC address> --legacy
|
||||
`
|
||||
```
|
||||
|
||||
**Note** : dfu.py is a slightly modified version of [this repo](https://github.com/daniel-thompson/ota-dfu-python).
|
||||
|
||||
### Firmware validation
|
||||
|
||||
Once the OTA is done, InfiniTime will reset the watch to apply the update. When the watch reboots, the new firmware is running.
|
||||
|
||||
One last step is needed to finalize the upgrade : the new firmware must be manually validated. If the watch resets while the image is not validated, the bootloader will automatically revert to the previous version of the firmware.
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# Python nRF5 OTA DFU Controller
|
||||
|
||||
So... this is my fork of dingara's fork of astronomer80's fork of
|
||||
foldedtoad's Python OTA DFU utility.
|
||||
foldedtoad's Python OTA DFU utility.
|
||||
|
||||
My own contribution is little more than a brute force conversion to
|
||||
python3. It is sparsely tested so there are likely to be a few
|
||||
My own contribution is little more than a brute force conversion to
|
||||
python3. It is sparsely tested so there are likely to be a few
|
||||
remaining bytes versus string bugs remaining in the places I didn't test
|
||||
. I used it primarily as part of
|
||||
[wasp-os](https://github.com/daniel-thompson/wasp-os) as a way to
|
||||
[wasp-os](https://github.com/daniel-thompson/wasp-os) as a way to
|
||||
deliver OTA updates to nRF52-based smart watches, especially the
|
||||
[Pine64 PineTime](https://www.pine64.org/pinetime/).
|
||||
|
||||
|
@ -17,24 +17,24 @@ This is a Python program that uses `gatttool` (provided with the Linux BlueZ dri
|
|||
|
||||
### Main features:
|
||||
|
||||
* Perform OTA DFU to an nRF5 peripheral without an external USB BLE dongle.
|
||||
* Ability to detect if the peripheral is running in application mode or bootloader, and automatically switch if needed (buttonless).
|
||||
* Support for both Legacy (SDK <= 11) and Secure (SDK >= 12) bootloader.
|
||||
- Perform OTA DFU to an nRF5 peripheral without an external USB BLE dongle.
|
||||
- Ability to detect if the peripheral is running in application mode or bootloader, and automatically switch if needed (buttonless).
|
||||
- Support for both Legacy (SDK <= 11) and Secure (SDK >= 12) bootloader.
|
||||
|
||||
Before using this utility the nRF5 peripheral device needs to be programmed with a DFU bootloader (see Nordic Semiconductor documentation/examples for instructions on that).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* BlueZ 5.4 or above
|
||||
* Python 3.6
|
||||
* Python `pexpect` module (available via pip)
|
||||
* Python `intelhex` module (available via pip)
|
||||
- BlueZ 5.4 or above
|
||||
- Python 3.6
|
||||
- Python `pexpect` module (available via pip)
|
||||
- Python `intelhex` module (available via pip)
|
||||
|
||||
## Firmware Build Requirement
|
||||
|
||||
* Your nRF5 peripheral firmware build method will produce a firmware file ending with either `*.hex` or `*.bin`.
|
||||
* Your nRF5 firmware build method will produce an Init file ending with `.dat`.
|
||||
* The typical naming convention is `application.bin` and `application.dat`, but this utility will accept other names.
|
||||
- Your nRF5 peripheral firmware build method will produce a firmware file ending with either `*.hex` or `*.bin`.
|
||||
- Your nRF5 firmware build method will produce an Init file ending with `.dat`.
|
||||
- The typical naming convention is `application.bin` and `application.dat`, but this utility will accept other names.
|
||||
|
||||
## Generating init files
|
||||
|
||||
|
@ -75,14 +75,13 @@ You can use the `hcitool lescan` to figure out the address of a DFU target, for
|
|||
CD:E3:4A:47:1C:E4 <TARGET_NAME>
|
||||
CD:E3:4A:47:1C:E4 (unknown)
|
||||
|
||||
|
||||
## Example Output
|
||||
|
||||
================================
|
||||
== ==
|
||||
== DFU Server ==
|
||||
== ==
|
||||
================================
|
||||
================================
|
||||
|
||||
Sending file application.bin to CD:E3:4A:47:1C:E4
|
||||
bin array size: 60788
|
||||
|
@ -105,14 +104,14 @@ You can use the `hcitool lescan` to figure out the address of a DFU target, for
|
|||
|
||||
## TODO:
|
||||
|
||||
* Implement link-loss procedure for Legacy Controller.
|
||||
* Update example output in readme.
|
||||
* Add makefile examples.
|
||||
* More code cleanup.
|
||||
- Implement link-loss procedure for Legacy Controller.
|
||||
- Update example output in readme.
|
||||
- Add makefile examples.
|
||||
- More code cleanup.
|
||||
|
||||
## Info & References
|
||||
|
||||
* [Nordic Legacy DFU Service](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/bledfu_transport_bleservice.html?cp=4_0_3_4_3_1_4_1)
|
||||
* [Nordic Legacy DFU sequence diagrams](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/bledfu_transport_bleprofile.html?cp=4_0_3_4_3_1_4_0_1_6#ota_profile_pkt_rcpt_notif)
|
||||
* [Nordic Secure DFU bootloader](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v12.2.0/lib_dfu_transport_ble.html?cp=4_0_1_3_5_2_2)
|
||||
* [nrfutil](https://github.com/NordicSemiconductor/pc-nrfutil)
|
||||
- [Nordic Legacy DFU Service](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/bledfu_transport_bleservice.html?cp=4_0_3_4_3_1_4_1)
|
||||
- [Nordic Legacy DFU sequence diagrams](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/bledfu_transport_bleprofile.html?cp=4_0_3_4_3_1_4_0_1_6#ota_profile_pkt_rcpt_notif)
|
||||
- [Nordic Secure DFU bootloader](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v12.2.0/lib_dfu_transport_ble.html?cp=4_0_1_3_5_2_2)
|
||||
- [nrfutil](https://github.com/NordicSemiconductor/pc-nrfutil)
|
||||
|
|
13
doc/BLEFS.md
13
doc/BLEFS.md
|
@ -1,4 +1,5 @@
|
|||
# BLE FS
|
||||
|
||||
---
|
||||
|
||||
The BLE FS protocol in InfiniTime is mostly Adafruit's BLE file transfer protocol, as described in [adafruit/Adafruit_CircuitPython_BLE_File_Transfer](https://github.com/adafruit/Adafruit_CircuitPython_BLE_File_Transfer). There are some deviations, such as the status codes. These will be described later in the document.
|
||||
|
@ -13,7 +14,7 @@ There are two relevant UUIDs in this protocol: the version characteristic, and t
|
|||
|
||||
UUID: `adaf0100-4669-6c65-5472-616e73666572`
|
||||
|
||||
The version characteristic returns the version of the protocol to which the sender adheres. It returns a single unsigned 32-bit integer. The latest version at the time of writing this is 4.
|
||||
The version characteristic returns the version of the protocol to which the sender adheres. It returns a single unsigned 32-bit integer. The latest version at the time of writing this is 4.
|
||||
|
||||
### Transfer
|
||||
|
||||
|
@ -125,7 +126,7 @@ Paths returned by this command are relative to the path given in the request
|
|||
- Unsigned 16-bit integer encoding the length of the file path.
|
||||
- File path: UTF-8 encoded string that is _not_ null terminated.
|
||||
|
||||
The response to this packet will be as follows. Responses will be sent until the final entry, which will have entry number == total entries
|
||||
The response to this packet will be as follows. Responses will be sent until the final entry, which will have entry number == total entries
|
||||
|
||||
- Command (single byte): `0x51`
|
||||
- Status (signed 8-bit integer)
|
||||
|
@ -133,9 +134,9 @@ The response to this packet will be as follows. Responses will be sent until the
|
|||
- Unsigned 32-bit integer encoding the entry number
|
||||
- Unsigned 32-bit integer encoding the total amount of entries
|
||||
- Flags: unsigned 32-bit integer
|
||||
+ Bit 0: Set when entry is a directory
|
||||
+ Bits 1-7: Reserved
|
||||
- Unsigned 64-bit integer encoding the unix timestamp of the modification time with nanosecond resolution
|
||||
- Bit 0: Set when entry is a directory
|
||||
- Bits 1-7: Reserved
|
||||
- Unsigned 64-bit integer encoding the unix timestamp of the modification time with nanosecond resolution
|
||||
- Unsigned 32-bit integer encoding the size of the file
|
||||
- Path: UTF-8 encoded string that is _not_ null terminated.
|
||||
|
||||
|
@ -164,4 +165,4 @@ This section describes the differences between Adafruit's spec and InfiniTime's
|
|||
|
||||
The status codes returned by InfiniTime are a signed 8-bit integer, rather than an unsigned one as described in the spec.
|
||||
|
||||
InfiniTime uses LittleFS error codes rather than the ones described in the spec. Those codes can be found in [lfs.h](https://github.com/littlefs-project/littlefs/blob/master/lfs.h#L70).
|
||||
InfiniTime uses LittleFS error codes rather than the ones described in the spec. Those codes can be found in [lfs.h](https://github.com/littlefs-project/littlefs/blob/master/lfs.h#L70).
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
# Memory analysis
|
||||
|
||||
The PineTime is equipped with the following memories:
|
||||
- The internal RAM : **64KB**
|
||||
- The internal Flash : **512KB**
|
||||
- The external (SPI) Flash : **4MB**
|
||||
|
||||
- The internal RAM : **64KB**
|
||||
- The internal Flash : **512KB**
|
||||
- The external (SPI) Flash : **4MB**
|
||||
|
||||
Note that the NRF52832 cannot execute code stored in the external flash : we need to store the whole firmware in the internal flash memory, and use the external one to store graphicals assets, fonts...
|
||||
|
||||
This document describes how the RAM and Flash memories are used in InfiniTime and how to analyze and monitor their usage. It was written in the context of [this memory analysis effort](https://github.com/InfiniTimeOrg/InfiniTime/issues/313).
|
||||
|
||||
## Code sections
|
||||
|
||||
A binary is composed of multiple sections. Most of the time, these sections are : .text, .rodata, .data and .bss but more sections can be defined in the linker script.
|
||||
|
||||
Here is a small description of these sections and where they end up in memory:
|
||||
|
||||
- **TEXT** = code (FLASH)
|
||||
- **RODATA** = constants (FLASH)
|
||||
- **DATA** = initialized variables (FLASH + RAM)
|
||||
- **BSS** = uninitialized variables (RAM)
|
||||
|
||||
- **TEXT** = code (FLASH)
|
||||
- **RODATA** = constants (FLASH)
|
||||
- **DATA** = initialized variables (FLASH + RAM)
|
||||
- **BSS** = uninitialized variables (RAM)
|
||||
|
||||
## Internal FLASH
|
||||
|
||||
The internal flash memory stores the whole firmware: code, variable that are not default-initialized, constants...
|
||||
|
||||
The content of the flash memory can be easily analyzed thanks to the MAP file generated by the compiler. This file lists all the symbols from the program along with their size and location (section and addresses) in RAM and FLASH.
|
||||
|
@ -41,62 +44,71 @@ Using this tool, you can compare the relative size of symbols. This can be helpf
|
|||
Also, as Linkermapviz is written in Python, you can easily modify and adapt it to your firmware or export data in another format. For example, [here it is modified to parse the contents of the MAP file and export it in a CSV file](https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-842338620). This file could later be opened in LibreOffice Calc where sort/filter functionality could be used to search for specific symbols in specific files...
|
||||
|
||||
### Puncover
|
||||
|
||||
[Puncover](https://github.com/HBehrens/puncover) is another useful tools that analyses the binary file generated by the compiler (the .out file that contains all debug information). It provides valuable information about the symbols (data and code): name, position, size, max stack of each functions, callers, callees...
|
||||
![Puncover](./memoryAnalysis/puncover.png)
|
||||
|
||||
Puncover is really easy to install:
|
||||
|
||||
- Clone the repo and cd into the cloned directory
|
||||
- Setup a venv
|
||||
- `python -m virtualenv venv`
|
||||
- `source venv/bin/activate`
|
||||
- Install : `pip install .`
|
||||
- Run : `puncover --gcc_tools_base=/path/to/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi- --elf_file /path/to/build/directory/src/pinetime-app-1.1.0.out --src_root /path/to/sources --build_dir /path/to/build/directory`
|
||||
- Replace
|
||||
* `/path/to/gcc-arm-none-eabi-10.3-2021.10/bin` with the path to your gcc-arm-none-eabi toolchain
|
||||
* `/path/to/build/directory/src/pinetime-app-1.1.0.out` with the path to the binary generated by GCC (.out file)
|
||||
* `/path/to/sources` with the path to the root folder of the sources (checkout directory)
|
||||
* `/path/to/build/directory` with the path to the build directory
|
||||
- Launch a browser at http://localhost:5000/
|
||||
- Clone the repo and cd into the cloned directory
|
||||
- Setup a venv
|
||||
- `python -m virtualenv venv`
|
||||
- `source venv/bin/activate`
|
||||
- Install : `pip install .`
|
||||
- Run : `puncover --gcc_tools_base=/path/to/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi- --elf_file /path/to/build/directory/src/pinetime-app-1.1.0.out --src_root /path/to/sources --build_dir /path/to/build/directory`
|
||||
- Replace
|
||||
- `/path/to/gcc-arm-none-eabi-10.3-2021.10/bin` with the path to your gcc-arm-none-eabi toolchain
|
||||
- `/path/to/build/directory/src/pinetime-app-1.1.0.out` with the path to the binary generated by GCC (.out file)
|
||||
- `/path/to/sources` with the path to the root folder of the sources (checkout directory)
|
||||
- `/path/to/build/directory` with the path to the build directory
|
||||
- Launch a browser at http://localhost:5000/
|
||||
|
||||
### Analysis
|
||||
|
||||
Using the MAP file and tools, we can easily see what symbols are using most of the flash memory. In this case, unsurprisingly, fonts and graphics are the largest use of flash memory.
|
||||
|
||||
![Puncover](./memoryAnalysis/puncover-all-symbols.png)
|
||||
|
||||
This way, you can easily check what needs to be optimized. We should find a way to store big static data (like fonts and graphics) in the external flash memory, for example.
|
||||
|
||||
It's always a good idea to check the flash memory space when working on the project. This way, you can easily check that your developments are using a reasonable amount of space.
|
||||
It's always a good idea to check the flash memory space when working on the project. This way, you can easily check that your developments are using a reasonable amount of space.
|
||||
|
||||
### Links
|
||||
- Analysis with linkermapviz : https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-842338620
|
||||
- Analysis with Puncover : https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-847311392
|
||||
|
||||
- Analysis with linkermapviz : https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-842338620
|
||||
- Analysis with Puncover : https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-847311392
|
||||
|
||||
## RAM
|
||||
|
||||
RAM memory contains all the data that can be modified at run-time: variables, stack, heap...
|
||||
|
||||
### Data
|
||||
|
||||
RAM memory can be *statically* allocated, meaning that the size and position of the data are known at compile-time:
|
||||
|
||||
You can easily analyze the memory used by variables declared in the global scope using the MAP. You'll find them in the .BSS or .DATA sections. Linkermapviz and Puncover can be used to analyze their memory usage.
|
||||
|
||||
Variables declared in the scope of a function will be allocated on the stack. It means that the stack usage will vary according to the state of the program, and cannot be easily analyzed at compile time.
|
||||
|
||||
```
|
||||
uint8_t buffer[1024]
|
||||
uint8_t buffer[1024]
|
||||
|
||||
int main() {
|
||||
int a;
|
||||
int a;
|
||||
}
|
||||
```
|
||||
|
||||
#### Analysis
|
||||
In Infinitime 1.1, the biggest buffers are the buffers allocated for LVGL (14KB) and the one for FreeRTOS (16KB). Nimble also allocated 9KB of RAM.
|
||||
|
||||
In Infinitime 1.1, the biggest buffers are the buffers allocated for LVGL (14KB) and the one for FreeRTOS (16KB). Nimble also allocated 9KB of RAM.
|
||||
|
||||
### Stack
|
||||
|
||||
The stack will be used for everything except tasks, which have their own stack allocated by FreeRTOS. The stack is 8192B and is allocated in the [linker script](https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/nrf_common.ld#L148).
|
||||
An easy way to monitor its usage is by filling the section with a known pattern at boot time, then use the firmware and dump the memory. You can then check the maximum stack usage by checking the address from the beginning of the stack that were overwritten.
|
||||
|
||||
#### Fill the stack section by a known pattern:
|
||||
|
||||
Edit <NRFSDK>/modules/nrfx/mdk/gcc_startup_nrf52.S and add the following code after the copy of the data from read only memory to RAM at around line 243:
|
||||
|
||||
```
|
||||
|
@ -138,6 +150,7 @@ bne .L_fill
|
|||
```
|
||||
|
||||
#### Dump RAM memory and check usage
|
||||
|
||||
Dumping the content of the ram is easy using JLink debugger and `nrfjprog`:
|
||||
|
||||
```
|
||||
|
@ -193,13 +206,16 @@ On the following dump, the maximum stack usage is 520 bytes (0xFFFF - 0xFDF8):
|
|||
000fff0 7fc0 2000 4217 0001 3f0a 0001 0000 6100
|
||||
```
|
||||
|
||||
#### Analysis
|
||||
#### Analysis
|
||||
|
||||
According to my experimentations, we don't use the stack that much, and 8192 bytes is probably way too big for InfiniTime!
|
||||
|
||||
#### Links
|
||||
- https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-851035070
|
||||
|
||||
- https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-851035070
|
||||
|
||||
### Heap
|
||||
|
||||
The heap is declared in the [linker script](https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/nrf_common.ld#L136) and its current size is 8192 bytes. The heap is used for dynamic memory allocation(`malloc()`, `new`...).
|
||||
|
||||
Heap monitoring is not easy, but it seems that we can use the following code to know the current usage of the heap:
|
||||
|
@ -210,6 +226,7 @@ NRF_LOG_INFO("heap : %d", m.uordblks);
|
|||
```
|
||||
|
||||
#### Analysis
|
||||
|
||||
According to my experimentation, InfiniTime uses ~6000bytes of heap most of the time. Except when the Navigation app is launched, where the heap usage exceeds 9500 bytes (meaning that the heap overflows and could potentially corrupt the stack). This is a bug that should be fixed in #362.
|
||||
|
||||
To know exactly what's consuming heap memory, you can `wrap` functions like `malloc()` into your own functions. In this wrapper, you can add logging code or put breakpoints:
|
||||
|
@ -225,6 +242,7 @@ void* __wrap_malloc(size_t size) {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now, your function `__wrap_malloc()` will be called instead of `malloc()`. You can call the actual malloc from the stdlib by calling `__real_malloc()`.
|
||||
|
||||
Using this technique, I was able to trace all malloc calls at boot (boot -> digital watchface):
|
||||
|
@ -239,12 +257,14 @@ Using this technique, I was able to trace all malloc calls at boot (boot -> digi
|
|||
- hr task = 304
|
||||
|
||||
#### Links
|
||||
- https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-851035625
|
||||
- https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-1-calculating-stack-size/
|
||||
- https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-2-properly-allocating-stacks/
|
||||
- https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-3-avoiding-heap-errors/
|
||||
|
||||
- https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-851035625
|
||||
- https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-1-calculating-stack-size/
|
||||
- https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-2-properly-allocating-stacks/
|
||||
- https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-3-avoiding-heap-errors/
|
||||
|
||||
## LVGL
|
||||
|
||||
I did a deep analysis of the usage of the buffer dedicated to lvgl (managed by lv_mem).
|
||||
This buffer is used by lvgl to allocated memory for drivers (display/touch), screens, themes, and all widgets created by the apps.
|
||||
|
||||
|
@ -262,11 +282,13 @@ Then, initializing the digital clock face costs **1541 bytes**.
|
|||
For example a simple lv_label needs **~140 bytes** of memory.
|
||||
|
||||
I tried to monitor this max value while going through all the apps of InfiniTime 1.1 : the max value I've seen is **5660 bytes**. It means that we could probably **reduce the size of the buffer from 14KB to 6 - 10 KB** (we have to take the fragmentation of the memory into account).
|
||||
### Links
|
||||
- https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-850890064
|
||||
|
||||
### Links
|
||||
|
||||
- https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-850890064
|
||||
|
||||
## FreeRTOS heap and task stack
|
||||
|
||||
FreeRTOS statically allocate its own heap buffer in a global variable named `ucHeap`. This is an array of *uint8_t*. Its size is specified by the definition `configTOTAL_HEAP_SIZE` in *FreeRTOSConfig.h*
|
||||
FreeRTOS uses this buffer to allocate memory for tasks stack and all the RTOS object created during runtime (timers, mutexes...).
|
||||
|
||||
|
@ -276,7 +298,6 @@ The function `xPortGetFreeHeapSize()` returns the amount of memory available in
|
|||
NRF_LOG_INFO("Free heap : %d", xPortGetFreeHeapSize());
|
||||
```
|
||||
|
||||
|
||||
The function `uxTaskGetSystemState()` fetches some information about the running tasks like its name and the minimum amount of stack space that has remained for the task since the task was created:
|
||||
|
||||
```
|
||||
|
@ -285,5 +306,3 @@ auto nb = uxTaskGetSystemState(tasksStatus, 10, NULL);
|
|||
for (int i = 0; i < nb; i++) {
|
||||
NRF_LOG_INFO("Task [%s] - %d", tasksStatus[i].pcTaskName, tasksStatus[i].usStackHighWaterMark);
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
# Motion Service
|
||||
|
||||
## Introduction
|
||||
|
||||
The motion service exposes step count and raw X/Y/Z motion value as READ and NOTIFY characteristics.
|
||||
|
||||
## Service
|
||||
|
||||
The service UUID is **00030000-78fc-48fe-8e23-433b3a1942d0**
|
||||
|
||||
## Characteristics
|
||||
|
||||
### Step count (UUID 00030001-78fc-48fe-8e23-433b3a1942d0)
|
||||
|
||||
The current number of steps represented as a single `uint32_t` (4 bytes) value.
|
||||
|
||||
### Raw motion values (UUID 00030002-78fc-48fe-8e23-433b3a1942d0)
|
||||
|
||||
The current raw motion values. This is a 3 `int16_t` array:
|
||||
|
||||
- [0] : X
|
||||
- [1] : Y
|
||||
- [2] : Z
|
||||
- [0] : X
|
||||
- [1] : Y
|
||||
- [2] : Z
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Navigation Service
|
||||
|
||||
## Introduction
|
||||
|
||||
The navigation ble service provides 4 characteristics to allow the watch to display navigation instructions from a companion application. This service is intended to be used when performing some outdoor activities, for example running or cycling.
|
||||
|
||||
The 4 characteristics are:
|
||||
|
@ -9,110 +11,117 @@ manDist (string) - Manouvre Distance, the distance to the upcoming change
|
|||
progress (uint8) - Percent complete of total route, value 0-100
|
||||
|
||||
## Service
|
||||
|
||||
The service UUID is 00010000-78fc-48fe-8e23-433b3a1942d0
|
||||
|
||||
## Characteristics
|
||||
|
||||
## Flags (UUID 00010001-78fc-48fe-8e23-433b3a1942d0)
|
||||
|
||||
All included icons are from pure-maps, which provides the actual routing from the client. The icon names ultimately come from the mapbox project "direction-icons", See https://github.com/rinigus/pure-maps/tree/master/qml/icons/navigation See the end of this document for the full list of supported icon names.
|
||||
|
||||
## Narrative (UUID 00010002-78fc-48fe-8e23-433b3a1942d0)
|
||||
|
||||
This is a client supplied string describing the upcoming instruction such as "At the roundabout take the first exit".
|
||||
|
||||
## Man Dist (UUID 00010003-78fc-48fe-8e23-433b3a1942d0)
|
||||
|
||||
This is a short string describing the distance to the upcoming instruction such as "50 m".
|
||||
|
||||
## Progress (UUID 00010004-78fc-48fe-8e23-433b3a1942d0)
|
||||
|
||||
The percent complete in a uint8. The watch displays this as an overall progress in a progress bar.
|
||||
|
||||
## Full icon list
|
||||
* arrive
|
||||
* arrive-left
|
||||
* arrive-right
|
||||
* arrive-straight
|
||||
* close
|
||||
* continue
|
||||
* continue-left
|
||||
* continue-right
|
||||
* continue-slight-left
|
||||
* continue-slight-right
|
||||
* continue-straight
|
||||
* continue-uturn
|
||||
* depart
|
||||
* depart-left
|
||||
* depart-right
|
||||
* depart-straight
|
||||
* end-of-road-left
|
||||
* end-of-road-right
|
||||
* ferry
|
||||
* flag
|
||||
* fork
|
||||
* fork-left
|
||||
* fork-right
|
||||
* fork-slight-left
|
||||
* fork-slight-right
|
||||
* fork-straight
|
||||
* invalid
|
||||
* invalid-left
|
||||
* invalid-right
|
||||
* invalid-slight-left
|
||||
* invalid-slight-right
|
||||
* invalid-straight
|
||||
* invalid-uturn
|
||||
* merge-left
|
||||
* merge-right
|
||||
* merge-slight-left
|
||||
* merge-slight-right
|
||||
* merge-straight
|
||||
* new-name-left
|
||||
* new-name-right
|
||||
* new-name-sharp-left
|
||||
* new-name-sharp-right
|
||||
* new-name-slight-left
|
||||
* new-name-slight-right
|
||||
* new-name-straight
|
||||
* notification-left
|
||||
* notification-right
|
||||
* notification-sharp-left
|
||||
* notification-sharp-right
|
||||
* notification-slight-left
|
||||
* notification-slight-right
|
||||
* notification-straight
|
||||
* off-ramp-left
|
||||
* off-ramp-right
|
||||
* off-ramp-sharp-left
|
||||
* off-ramp-sharp-right
|
||||
* off-ramp-slight-left
|
||||
* off-ramp-slight-right
|
||||
* off-ramp-straight
|
||||
* on-ramp-left
|
||||
* on-ramp-right
|
||||
* on-ramp-sharp-left
|
||||
* on-ramp-sharp-right
|
||||
* on-ramp-slight-left
|
||||
* on-ramp-slight-right
|
||||
* on-ramp-straight
|
||||
* rotary
|
||||
* rotary-left
|
||||
* rotary-right
|
||||
* rotary-sharp-left
|
||||
* rotary-sharp-right
|
||||
* rotary-slight-left
|
||||
* rotary-slight-right
|
||||
* rotary-straight
|
||||
* roundabout
|
||||
* roundabout-left
|
||||
* roundabout-right
|
||||
* roundabout-sharp-left
|
||||
* roundabout-sharp-right
|
||||
* roundabout-slight-left
|
||||
* roundabout-slight-right
|
||||
* roundabout-straight
|
||||
* turn-left
|
||||
* turn-right
|
||||
* turn-sharp-left
|
||||
* turn-sharp-right
|
||||
* turn-slight-left
|
||||
* turn-slight-right
|
||||
* turn-stright
|
||||
* updown
|
||||
* uturn
|
||||
|
||||
- arrive
|
||||
- arrive-left
|
||||
- arrive-right
|
||||
- arrive-straight
|
||||
- close
|
||||
- continue
|
||||
- continue-left
|
||||
- continue-right
|
||||
- continue-slight-left
|
||||
- continue-slight-right
|
||||
- continue-straight
|
||||
- continue-uturn
|
||||
- depart
|
||||
- depart-left
|
||||
- depart-right
|
||||
- depart-straight
|
||||
- end-of-road-left
|
||||
- end-of-road-right
|
||||
- ferry
|
||||
- flag
|
||||
- fork
|
||||
- fork-left
|
||||
- fork-right
|
||||
- fork-slight-left
|
||||
- fork-slight-right
|
||||
- fork-straight
|
||||
- invalid
|
||||
- invalid-left
|
||||
- invalid-right
|
||||
- invalid-slight-left
|
||||
- invalid-slight-right
|
||||
- invalid-straight
|
||||
- invalid-uturn
|
||||
- merge-left
|
||||
- merge-right
|
||||
- merge-slight-left
|
||||
- merge-slight-right
|
||||
- merge-straight
|
||||
- new-name-left
|
||||
- new-name-right
|
||||
- new-name-sharp-left
|
||||
- new-name-sharp-right
|
||||
- new-name-slight-left
|
||||
- new-name-slight-right
|
||||
- new-name-straight
|
||||
- notification-left
|
||||
- notification-right
|
||||
- notification-sharp-left
|
||||
- notification-sharp-right
|
||||
- notification-slight-left
|
||||
- notification-slight-right
|
||||
- notification-straight
|
||||
- off-ramp-left
|
||||
- off-ramp-right
|
||||
- off-ramp-sharp-left
|
||||
- off-ramp-sharp-right
|
||||
- off-ramp-slight-left
|
||||
- off-ramp-slight-right
|
||||
- off-ramp-straight
|
||||
- on-ramp-left
|
||||
- on-ramp-right
|
||||
- on-ramp-sharp-left
|
||||
- on-ramp-sharp-right
|
||||
- on-ramp-slight-left
|
||||
- on-ramp-slight-right
|
||||
- on-ramp-straight
|
||||
- rotary
|
||||
- rotary-left
|
||||
- rotary-right
|
||||
- rotary-sharp-left
|
||||
- rotary-sharp-right
|
||||
- rotary-slight-left
|
||||
- rotary-slight-right
|
||||
- rotary-straight
|
||||
- roundabout
|
||||
- roundabout-left
|
||||
- roundabout-right
|
||||
- roundabout-sharp-left
|
||||
- roundabout-sharp-right
|
||||
- roundabout-slight-left
|
||||
- roundabout-slight-right
|
||||
- roundabout-straight
|
||||
- turn-left
|
||||
- turn-right
|
||||
- turn-sharp-left
|
||||
- turn-sharp-right
|
||||
- turn-slight-left
|
||||
- turn-slight-right
|
||||
- turn-stright
|
||||
- updown
|
||||
- uturn
|
||||
|
|
|
@ -1,33 +1,36 @@
|
|||
# Build a stub for PineTime using NRF52-DK
|
||||
|
||||
[NRF52-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK) is the official development kit for the NRF52832 SoC from Nordic Semiconductor used in the PineTime.
|
||||
|
||||
This development kit can be very useful for PineTime development:
|
||||
* You can use its embedded JLink SWD programmer/debugger to program and debug your code on the PineTime
|
||||
* As it's based on the same SoC than the PineTime, you can program it to actually run the same code as the PineTime.
|
||||
|
||||
|
||||
- You can use its embedded JLink SWD programmer/debugger to program and debug your code on the PineTime
|
||||
- As it's based on the same SoC than the PineTime, you can program it to actually run the same code as the PineTime.
|
||||
|
||||
This page is about the 2nd point. We will build a stub that will allow us to run the same code you can run on the PineTime. This will allow you to work more easily if you don't have a PineTime dev kit around, if you don't want to modify your dev kit for SWD programming, or if you want to use some feature from the NRF52-DK (like power measurement).
|
||||
|
||||
This stub only implements the display, the button and the BLE radio. The other features from the pintime are missing:
|
||||
* heart rate sensor
|
||||
* SPI flash
|
||||
* touchpad
|
||||
* accelerometer
|
||||
This stub only implements the display, the button and the BLE radio. The other features from the pintime are missing:
|
||||
|
||||
- heart rate sensor
|
||||
- SPI flash
|
||||
- touchpad
|
||||
- accelerometer
|
||||
|
||||
These devices could be added on this stub, but I do not have the parts to try them out for now.
|
||||
|
||||
![Pinetime stub](../images/pinetimestub1.jpg "PinetimeStub")
|
||||
|
||||
|
||||
Here are the parts you need to build this simulator:
|
||||
* [NRF52-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK)
|
||||
* An ST7889 display (I bought [this one](https://www.aliexpress.com/item/32859772356.html?spm=a2g0s.9042311.0.0.1b774c4dSoc4Xz))
|
||||
* A push-button (the one I use comes from a previous project build around ESP8266 board Wemos D1 Mini).
|
||||
* Dupont wires
|
||||
|
||||
|
||||
- [NRF52-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK)
|
||||
- An ST7889 display (I bought [this one](https://www.aliexpress.com/item/32859772356.html?spm=a2g0s.9042311.0.0.1b774c4dSoc4Xz))
|
||||
- A push-button (the one I use comes from a previous project build around ESP8266 board Wemos D1 Mini).
|
||||
- Dupont wires
|
||||
|
||||
You just need to make the following connections:
|
||||
|
||||
| NRF52-DK | ST7889 display |
|
||||
| ---------|--------------- |
|
||||
| -------- | -------------- |
|
||||
| VDD | VCC |
|
||||
| GND | GND |
|
||||
| P0.03 | SDA |
|
||||
|
@ -35,11 +38,10 @@ You just need to make the following connections:
|
|||
| P0.02 | SCL |
|
||||
| P0.18 | DC |
|
||||
|
||||
|
||||
| NRF52-DK | Push Button |
|
||||
| ---------|----------------------- |
|
||||
| P0.13 | Button IN (D3 in my case) |
|
||||
| GND | GND |
|
||||
| NRF52-DK | Push Button |
|
||||
| -------- | ------------------------- |
|
||||
| P0.13 | Button IN (D3 in my case) |
|
||||
| GND | GND |
|
||||
|
||||
You also need to enable the I/O expander to disconnect pins from the buttons and LED on the NRF52-DK and leave them available on the pin headers:
|
||||
|
||||
|
@ -47,4 +49,4 @@ You also need to enable the I/O expander to disconnect pins from the buttons and
|
|||
| --------- | --------- |
|
||||
| DETECT | GND |
|
||||
|
||||
Now, you should be able to program the SoC on the NRF52-DK board, and use it as if it was running on the PineTime.
|
||||
Now, you should be able to program the SoC on the NRF52-DK board, and use it as if it was running on the PineTime.
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
# The SPI LCD driver
|
||||
|
||||
## Introduction
|
||||
|
||||
The LCD controller that drives the display of the Pinetime is the [Sitronix ST7789V](https://wiki.pine64.org/images/5/54/ST7789V_v1.6.pdf). This controller is easy to integrate with an MCU thanks to its SPI interface, and has some interesting features like:
|
||||
|
||||
- an on-chip display data RAM that can store the whole framebuffer
|
||||
- partial screen update
|
||||
- hardware assisted vertical scrolling
|
||||
- interrupt pin, allowing to drive the display with DMA and IRQ
|
||||
- interrupt pin, allowing to drive the display with DMA and IRQ
|
||||
- ...
|
||||
|
||||
When you want to write a device driver for a specific component, its datasheet is your holy bible. This document contains a lot of information about the chip, its specification, characteristics, features and functionalities.
|
||||
Luckily for us, the datasheet of the ST7789 is great! It contains everything we need to write a nice driver for our beloved Pinetime.
|
||||
Luckily for us, the datasheet of the ST7789 is great! It contains everything we need to write a nice driver for our beloved Pinetime.
|
||||
|
||||
In this document, I'll try to explain the process I've followed to write a device driver for the LCD. There were multiple iterations:
|
||||
|
||||
- First, I tried to find the correct initialization sequence so that the controller is configured correctly according to the hardware configuration;
|
||||
- Then, I tried to display some pixels on the screen;
|
||||
- Next, I wanted to display squares, colors and text;
|
||||
|
@ -20,12 +24,14 @@ In this document, I'll try to explain the process I've followed to write a devic
|
|||
I'll describe all these steps in the following chapters.
|
||||
|
||||
## The datasheet
|
||||
|
||||
As I said in the introduction, the datasheet will be your bedside book during your journey as a device driver designer. You'll read it from the beginning to the end once, twice, maybe ten times. Then, each time you'll want to do something new, you'll reopen the file and search for that specific paragraph or diagram than explains how the controller works so that you can figure out how to use it.
|
||||
|
||||
The schematic of your board (the Pinetime schematics in this case) will also be very important, as you'll need to know how the LCD controller is physically connected to the MCU.
|
||||
|
||||
How to read the datasheet? I recommend to read it from the beginning to the end (no joke) at least once. You certainly do not need to read everything in details, but it's good to know what information is available and where in the document. It'll be very useful during the development phase.
|
||||
You'll want to read some part with more attention :
|
||||
|
||||
- Data color coding in 4-Line Serial Interface : how to send the pixel to be display to the controller
|
||||
- Display Data Ram : how is the memory organized
|
||||
- Power On/Off sequence
|
||||
|
@ -33,7 +39,6 @@ You'll want to read some part with more attention :
|
|||
|
||||
## One Pixel at a time
|
||||
|
||||
|
||||
## Bulk transfers
|
||||
|
||||
## DMA
|
||||
|
@ -41,6 +46,7 @@ You'll want to read some part with more attention :
|
|||
## IRQ
|
||||
|
||||
## Bare metal integration
|
||||
|
||||
Integration customisée dans la lib GFX que j'ai écrite
|
||||
|
||||
## Integration with LittleVGL
|
||||
## Integration with LittleVGL
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# How to flash InfiniTime using the SWD interface
|
||||
|
||||
Download the files **bootloader.bin**, **image-x.y.z.bin** and **pinetime-graphics-x.y.z.bin** from the release page:
|
||||
|
||||
![Image file](gettingStarted/imageFile.png)
|
||||
|
@ -8,7 +9,7 @@ Using your SWD tool, flash **pinetime-graphics-x.y.z.bin** at offset **0x0000**.
|
|||
|
||||
Then, using your SWD tool, flash these file at the following offsets:
|
||||
|
||||
- bootloader.bin : **0x0000**
|
||||
- image-x.y.z.bin : **0x8000**
|
||||
- bootloader.bin : **0x0000**
|
||||
- image-x.y.z.bin : **0x8000**
|
||||
|
||||
Reset and voilà, you're running InfiniTime on your PineTime!
|
||||
|
|
28
doc/ble.md
28
doc/ble.md
|
@ -1,5 +1,7 @@
|
|||
# Bluetooth Low-Energy :
|
||||
# Bluetooth Low-Energy :
|
||||
|
||||
## Introduction
|
||||
|
||||
This page describes the BLE implementation and API built in this firmware.
|
||||
|
||||
---
|
||||
|
@ -38,6 +40,7 @@ This page describes the BLE implementation and API built in this firmware.
|
|||
---
|
||||
|
||||
## BLE Connection
|
||||
|
||||
When starting, the firmware starts BLE advertising. It sends small messages that can be received by any *central* device in range. This allows the device to announce its presence to other devices.
|
||||
|
||||
A companion application (running on a PC, Raspberry Pi, smartphone, etc.) which receives this advertising packet can request a connection to the device. This connection procedure allows the 2 devices to negotiate communication parameters, security keys, etc.
|
||||
|
@ -58,7 +61,8 @@ The documentation for BLE FS can be found here:
|
|||
---
|
||||
|
||||
## BLE UUIDs
|
||||
When possible, InfiniTime tries to implement BLE services defined by the BLE specification.
|
||||
|
||||
When possible, InfiniTime tries to implement BLE services defined by the BLE specification.
|
||||
|
||||
When the service does not exist in the BLE specification, InfiniTime implements custom services. Custom services are identified by a UUID, as are all BLE services. Here is how to define the UUID of custom services in InfiniTime:
|
||||
|
||||
|
@ -70,34 +74,38 @@ When the service does not exist in the BLE specification, InfiniTime implements
|
|||
|
||||
The following custom services are implemented in InfiniTime:
|
||||
|
||||
- Since InfiniTime 0.8:
|
||||
* Music Service : 00000000-78fc-48fe-8e23-433b3a1942d0
|
||||
|
||||
- Since InfiniTime 0.8:
|
||||
|
||||
- Since InfiniTime 0.11:
|
||||
* [Navigation Service](NavigationService.md) : 00010000-78fc-48fe-8e23-433b3a1942d0
|
||||
- Music Service : `00000000-78fc-48fe-8e23-433b3a1942d0`
|
||||
|
||||
- Since InfiniTime 0.11:
|
||||
|
||||
- [Navigation Service](NavigationService.md) : `00010000-78fc-48fe-8e23-433b3a1942d0`
|
||||
|
||||
- Since InfiniTime 0.13
|
||||
* Call characteristic (extension to the Alert Notification Service): 00020001-78fc-48fe-8e23-433b3a1942d0
|
||||
|
||||
- Call characteristic (extension to the Alert Notification Service): `00020001-78fc-48fe-8e23-433b3a1942d0`
|
||||
|
||||
- Since InfiniTime 1.7:
|
||||
* [Motion Service](MotionService.md): 00030000-78fc-48fe-8e23-433b3a1942d0
|
||||
|
||||
- [Motion Service](MotionService.md): `00030000-78fc-48fe-8e23-433b3a1942d0`
|
||||
|
||||
- Since InfiniTime 1.8:
|
||||
* [Weather Service](/src/components/ble/weather/WeatherService.h): 00040000-78fc-48fe-8e23-433b3a1942d0
|
||||
|
||||
- [Weather Service](/src/components/ble/weather/WeatherService.h): `00040000-78fc-48fe-8e23-433b3a1942d0`
|
||||
|
||||
---
|
||||
|
||||
## BLE services
|
||||
|
||||
[List of standard BLE services](https://www.bluetooth.com/specifications/gatt/services/)
|
||||
|
||||
### CTS
|
||||
|
||||
[Current Time Service](https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.current_time.xml)
|
||||
|
||||
### ANS
|
||||
|
||||
[Alert Notification Service](https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.alert_notification.xml)
|
||||
|
||||
![ANS sequence diagram](./ble/ans_sequence.png "ANS sequence diagram")
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
# Branches
|
||||
|
||||
The branching model of this project is based on the workflow named [Git flow](https://nvie.com/posts/a-successful-git-branching-model/).
|
||||
|
||||
The project is based on 2 main branches:
|
||||
- **master** : this branch is always ready to be deployed. It means that at any time, we should be able to build the branch and release a new version of the application.
|
||||
- **develop** : this branch contains the latest development that will be integrated in the next release once it's considered as stable.
|
||||
|
||||
- **master** : this branch is always ready to be deployed. It means that at any time, we should be able to build the branch and release a new version of the application.
|
||||
- **develop** : this branch contains the latest development that will be integrated in the next release once it's considered as stable.
|
||||
|
||||
New features should be implemented in **feature branches** created from **develop**. When the feature is ready, a pull-request is created and it'll be merge into **develop** when it is successfully reviewed and accepted.
|
||||
|
||||
To release a new version of the application, when develop is considered stable, a **release** branch is created from **develop**. This can be considered as a *release candidate* branch. When everything is OK, this release branch is merged into **master** and the release is generated (a tag is applied to git, the release note is finalized, binaries are built,...) from **master**.
|
||||
|
||||
Git flow also supports the creation of **hotfix** branches when a bug is discovered in a released version. The **hotfix** branch is created from **master** and will be used only to implement a fix to this bug. Multiple hotfix branches can be created for the same release if multiple bugs are discovered.
|
||||
Git flow also supports the creation of **hotfix** branches when a bug is discovered in a released version. The **hotfix** branch is created from **master** and will be used only to implement a fix to this bug. Multiple hotfix branches can be created for the same release if multiple bugs are discovered.
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
# Build
|
||||
|
||||
## Dependencies
|
||||
|
||||
To build this project, you'll need:
|
||||
- A cross-compiler : [ARM-GCC (10.3-2021.10)](https://developer.arm.com/downloads/-/gnu-rm)
|
||||
- The NRF52 SDK 15.3.0 : [nRF-SDK v15.3.0](https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip)
|
||||
- The Python 3 modules `cbor`, `intelhex`, `click` and `cryptography` modules for the `mcuboot` tool (see [requirements.txt](../tools/mcuboot/requirements.txt))
|
||||
- To keep the system clean, you can install python modules into a python virtual environment (`venv`)
|
||||
```sh
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install wheel
|
||||
python -m pip install -r tools/mcuboot/requirements.txt
|
||||
```
|
||||
- A reasonably recent version of CMake (I use 3.16.5)
|
||||
- lv_font_conv, to generate the font .c files
|
||||
- see [lv_font_conv](https://github.com/lvgl/lv_font_conv#install-the-script)
|
||||
- install npm (commonly done via the package manager, ensure node's version is at least 12)
|
||||
- install lv_font_conv: `npm install lv_font_conv`
|
||||
|
||||
- A cross-compiler : [ARM-GCC (10.3-2021.10)](https://developer.arm.com/downloads/-/gnu-rm)
|
||||
- The NRF52 SDK 15.3.0 : [nRF-SDK v15.3.0](https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip)
|
||||
- The Python 3 modules `cbor`, `intelhex`, `click` and `cryptography` modules for the `mcuboot` tool (see [requirements.txt](../tools/mcuboot/requirements.txt))
|
||||
- To keep the system clean, you can install python modules into a python virtual environment (`venv`)
|
||||
```sh
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install wheel
|
||||
python -m pip install -r tools/mcuboot/requirements.txt
|
||||
```
|
||||
- A reasonably recent version of CMake (I use 3.16.5)
|
||||
- lv_font_conv, to generate the font .c files
|
||||
- see [lv_font_conv](https://github.com/lvgl/lv_font_conv#install-the-script)
|
||||
- install npm (commonly done via the package manager, ensure node's version is at least 12)
|
||||
- install lv_font_conv: `npm install lv_font_conv`
|
||||
|
||||
## Build steps
|
||||
|
||||
### Clone the repo
|
||||
|
||||
```
|
||||
git clone https://github.com/InfiniTimeOrg/InfiniTime.git
|
||||
cd InfiniTime
|
||||
|
@ -26,7 +31,9 @@ git submodule update --init
|
|||
mkdir build
|
||||
cd build
|
||||
```
|
||||
|
||||
### Project generation using CMake
|
||||
|
||||
CMake configures the project according to variables you specify the command line. The variables are:
|
||||
|
||||
Variable | Description | Example|
|
||||
|
@ -41,31 +48,36 @@ CMake configures the project according to variables you specify the command line
|
|||
**BUILD_DFU (\*\*)**|Build DFU files while building (needs [adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil)).|`-DBUILD_DFU=1`
|
||||
**TARGET_DEVICE**|Target device, used for hardware configuration. Allowed: `PINETIME, MOY-TFK5, MOY-TIN5, MOY-TON5, MOY-UNK`|`-DTARGET_DEVICE=PINETIME` (Default)
|
||||
|
||||
####(**) Note about **CMAKE_BUILD_TYPE**:
|
||||
#### (\*) Note about **CMAKE_BUILD_TYPE**
|
||||
By default, this variable is set to *Release*. It compiles the code with size and speed optimizations. We use this value for all the binaries we publish when we [release](https://github.com/InfiniTimeOrg/InfiniTime/releases) new versions of InfiniTime.
|
||||
|
||||
The *Debug* mode disables all optimizations, which makes the code easier to debug. However, the binary size will likely be too big to fit in the internal flash memory. If you want to build and debug a *Debug* binary, you'll need to disable some parts of the code. For example, the icons for the **Navigation** app use a lot of memory space. You can comment the content of `m_iconMap` in the [Navigation](https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/src/displayapp/screens/Navigation.h#L148) application to free some memory.
|
||||
|
||||
####(**) Note about **BUILD_DFU**:
|
||||
#### (\*\*) Note about **BUILD_DFU**
|
||||
DFU files are the files you'll need to install your build of InfiniTime using OTA (over-the-air) mechanism. To generate the DFU file, the Python tool [adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil) is needed on your system. Check that this tool is properly installed before enabling this option.
|
||||
|
||||
#### CMake command line for JLink
|
||||
|
||||
```
|
||||
cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=... -DNRF5_SDK_PATH=... -DUSE_JLINK=1 -DNRFJPROG=... ../
|
||||
```
|
||||
|
||||
#### CMake command line for GDB Client (Black Magic Probe)
|
||||
|
||||
```
|
||||
cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=... -DNRF5_SDK_PATH=... -DUSE_GDB_CLIENT=1 -DGDB_CLIENT_BIN_PATH=... -DGDB_CLIENT_TARGET_REMOTE=... ../
|
||||
```
|
||||
|
||||
#### CMake command line for OpenOCD
|
||||
|
||||
```
|
||||
cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=... -DNRF5_SDK_PATH=... -DUSE_OPENOCD=1 -DGDB_CLIENT_BIN_PATH=[optional] ../
|
||||
```
|
||||
|
||||
### Build the project
|
||||
|
||||
During the project generation, CMake created the following targets:
|
||||
|
||||
- **FLASH_ERASE** : mass erase the flash memory of the NRF52.
|
||||
- **FLASH_pinetime-app** : flash the firmware into the NRF52.
|
||||
- **pinetime-app** : build the standalone (without bootloader support) version of the firmware.
|
||||
|
@ -78,58 +90,69 @@ During the project generation, CMake created the following targets:
|
|||
If you just want to build the project and run it on the Pinetime, using *pinetime-app* is recommended. See [this page](../bootloader/README.md) for more info about bootloader support.
|
||||
|
||||
Build:
|
||||
|
||||
```
|
||||
make -j pinetime-app
|
||||
```
|
||||
|
||||
List of files generated:
|
||||
Binary files are generated into the folder `src`:
|
||||
- **pinetime-app.bin, .hex and .out** : standalone firmware in bin, hex and out formats.
|
||||
- **pinetime-app.map** : map file
|
||||
- **pinetime-mcuboot-app.bin, .hex and .out** : firmware with bootloader support in bin, hex and out formats.
|
||||
- **pinetime-mcuboot-app.map** : map file
|
||||
- **pinetime-mcuboot-app-image** : MCUBoot image of the firmware
|
||||
- **pinetime-mcuboot-ap-dfu** : DFU file of the firmware
|
||||
|
||||
The same files are generated for **pinetime-recovery** and **pinetime-recoveryloader**
|
||||
- **pinetime-app.bin, .hex and .out** : standalone firmware in bin, hex and out formats.
|
||||
- **pinetime-app.map** : map file
|
||||
- **pinetime-mcuboot-app.bin, .hex and .out** : firmware with bootloader support in bin, hex and out formats.
|
||||
- **pinetime-mcuboot-app.map** : map file
|
||||
- **pinetime-mcuboot-app-image** : MCUBoot image of the firmware
|
||||
- **pinetime-mcuboot-ap-dfu** : DFU file of the firmware
|
||||
|
||||
The same files are generated for **pinetime-recovery** and **pinetime-recoveryloader**
|
||||
|
||||
|
||||
### Program and run
|
||||
|
||||
#### Using CMake targets
|
||||
|
||||
These target have been configured during the project generation by CMake according to the parameters you provided to the command line.
|
||||
|
||||
Mass erase:
|
||||
|
||||
```
|
||||
make FLASH_ERASE
|
||||
```
|
||||
```
|
||||
|
||||
Flash the application:
|
||||
|
||||
```
|
||||
make FLASH_pinetime-app
|
||||
```
|
||||
|
||||
### How to generate files needed by the factory
|
||||
|
||||
These files are needed by the Pine64 factory to flash InfiniTime as the default firmware on the PineTimes.
|
||||
|
||||
Two files are needed: an **HEX (.hex)** file that contains the content of the internal flash memory (bootloader + InfiniTime) and a **binary (.bin)** file that contains the content of the external flash memory (recovery firmware).
|
||||
|
||||
#### merged-internal.hex
|
||||
|
||||
First, convert the bootloader to hex:
|
||||
```
|
||||
<ARM TOOLCHAIN>/bin/arm-none-eabi-objcopy -I binary -O ihex ./bootloader.bin ./bootloader.hex
|
||||
```
|
||||
|
||||
```
|
||||
<ARM TOOLCHAIN>/bin/arm-none-eabi-objcopy -I binary -O ihex ./bootloader.bin ./bootloader.hex
|
||||
```
|
||||
|
||||
where `bootloader.bin` is the [last stable version](https://github.com/JF002/pinetime-mcuboot-bootloader/releases) of the [bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader).
|
||||
|
||||
Then, convert the MCUBoot image of InfiniTime:
|
||||
|
||||
```
|
||||
<ARM TOOLCHAIN>/bin/arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x8000 ./pinetime-mcuboot-app-image-1.6.0.bin ./pinetime-mcuboot-app-image-1.6.0.hex
|
||||
```
|
||||
|
||||
where `pinetime-mcuboot-app-image-1.6.0.bin` is [the bin of the last MCUBoot image](https://github.com/InfiniTimeOrg/InfiniTime/releases) of [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime).
|
||||
|
||||
Pay attention to the parameter `--change-addresses 0x8000`. It's needed to ensure the image will be flashed at the offset expected by the bootloader (0x8000).
|
||||
|
||||
Finally, merge them together with **mergehex**:
|
||||
|
||||
```
|
||||
/opt/mergehex/mergehex -m ./bootloader.hex ./pinetime-mcuboot-app-image-1.6.0.hex -o merged-internal.hex
|
||||
```
|
||||
|
@ -137,4 +160,5 @@ Finally, merge them together with **mergehex**:
|
|||
This file must be flashed at offset **0x00** of the internal memory of the NRF52832.
|
||||
|
||||
#### spinor.bin
|
||||
|
||||
This file is the MCUBoot image of the last stable version of the recovery firmware. It must be flashed at offset **0x00** of the external SPINOR flash memory.
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
# Build the project using Docker
|
||||
|
||||
A [Docker image (Dockerfile)](../docker) containing all the build environment is available for X86_64 and AMD64 architectures.
|
||||
A [Docker image (Dockerfile)](../docker) containing all the build environment is available for X86_64 and AMD64 architectures.
|
||||
These images make the build of the firmware and the generation of the DFU file for OTA quite easy, as well as preventing clashes with any other toolchains or development environments you may have installed.
|
||||
|
||||
Based on Ubuntu 22.04 with the following build dependencies:
|
||||
|
||||
* ARM GCC Toolchain
|
||||
* nRF SDK
|
||||
* MCUBoot
|
||||
* adafruit-nrfutil
|
||||
* lv_font_conv
|
||||
- ARM GCC Toolchain
|
||||
- nRF SDK
|
||||
- MCUBoot
|
||||
- adafruit-nrfutil
|
||||
- lv_font_conv
|
||||
|
||||
## Run a container to build the project
|
||||
|
||||
The `infinitime-build` image contains all the dependencies you need.
|
||||
The `infinitime-build` image contains all the dependencies you need.
|
||||
The default `CMD` will compile sources found in `/sources`, so you need only mount your code.
|
||||
|
||||
Before continuing, make sure you first build the image as indicated in the [Build the image](#build-the-image) section, or check the [Using the image from Docker Hub](#using-the-image-from-docker-hub) section if you prefer to use a pre-made image.
|
||||
|
||||
This example will build the firmware, generate the MCUBoot image and generate the DFU file.
|
||||
This example will build the firmware, generate the MCUBoot image and generate the DFU file.
|
||||
For cloning the repo, see [these instructions](../doc/buildAndProgram.md#clone-the-repo). Outputs will be written to **<project_root>/build/output**:
|
||||
|
||||
```bash
|
||||
|
@ -26,12 +26,12 @@ cd <project_root> # e.g. cd ./work/Pinetime
|
|||
docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime-build
|
||||
```
|
||||
|
||||
By default, the container runs as `root`, which is not convenient as all the files generated by the build will also belong to `root`.
|
||||
The parameter `--user` overrides that default behavior.
|
||||
The command above will run as your current user.
|
||||
By default, the container runs as `root`, which is not convenient as all the files generated by the build will also belong to `root`.
|
||||
The parameter `--user` overrides that default behavior.
|
||||
The command above will run as your current user.
|
||||
|
||||
If you only want to build a single CMake target, you can pass it in as the first parameter to the build script.
|
||||
This means calling the script explicitly as it will override the `CMD`.
|
||||
If you only want to build a single CMake target, you can pass it in as the first parameter to the build script.
|
||||
This means calling the script explicitly as it will override the `CMD`.
|
||||
Here's an example for `pinetime-app`:
|
||||
|
||||
```bash
|
||||
|
@ -50,9 +50,9 @@ docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime/infin
|
|||
|
||||
The default `latest` tag *should* automatically identify the correct image architecture, but if for some reason Docker does not, you can specify it manually:
|
||||
|
||||
* For AMD64 (x86_64) systems: `docker pull --platform linux/amd64 infinitime/infinitime-build`
|
||||
- For AMD64 (x86_64) systems: `docker pull --platform linux/amd64 infinitime/infinitime-build`
|
||||
|
||||
* For ARM64v8 (ARM64/aarch64) systems: `docker pull --platform linux/arm64 infinitime/infinitime-build`
|
||||
- For ARM64v8 (ARM64/aarch64) systems: `docker pull --platform linux/arm64 infinitime/infinitime-build`
|
||||
|
||||
## Build the image
|
||||
|
||||
|
@ -62,4 +62,4 @@ The following commands must be run from the root of the project. This operation
|
|||
|
||||
```bash
|
||||
docker build -t infinitime-build ./docker
|
||||
```
|
||||
```
|
||||
|
|
|
@ -26,27 +26,22 @@ We leverage a few VS Code extensions for ease of development.
|
|||
|
||||
Cortex-Debug is only required for interactive debugging using VS Codes built in GDB support.
|
||||
|
||||
|
||||
|
||||
## VS Code/Docker DevContainer
|
||||
|
||||
The .devcontainer folder contains the configuration and scripts for using a Docker dev container for building InfiniTime
|
||||
|
||||
Using the [Remote-Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension is recommended. It will handle configuring the Docker virtual machine and setting everything up.
|
||||
Using the [Remote-Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension is recommended. It will handle configuring the Docker virtual machine and setting everything up.
|
||||
|
||||
More documentation is available in the [readme in .devcontainer](.devcontainer/readme.md)
|
||||
More documentation is available in the [readme in .devcontainer](.devcontainer/readme.md)
|
||||
|
||||
### DevContainer on Ubuntu
|
||||
To use the DevContainer configuration on Ubuntu based systems two changes need to be made:
|
||||
|
||||
1. Modify the file ``.devcontainer/devcontainer.json`` and add the argument ``"--net=host"`` to the ``"runArgs"`` parameter making the line look like this:
|
||||
`` "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--net=host"],
|
||||
``
|
||||
2. Modify the file ``.vscode/launch.json`` and change the argument of ``"gdbTarget"`` to ``"127.0.0.1:3333"``, making the line look like:
|
||||
``"gdbTarget": "127.0.0.1:3333",``
|
||||
3. To start debugging launch openocd on your host system with the appropriate configuration, for example with a stlink-v2 the command is:
|
||||
``openocd -f interface/stlink.cfg -f target/nrf52.cfg``. This launches openocd with the default ports ``3333``, ``4444`` and ``6666``.
|
||||
4. In VsCode go to the Debug pane on the left of the screen and select the configuration ``Debug - Openocd docker Remote`` and hit the play button on the left.
|
||||
|
||||
|
||||
To use the DevContainer configuration on Ubuntu based systems two changes need to be made:
|
||||
|
||||
1. Modify the file `.devcontainer/devcontainer.json` and add the argument `"--net=host"` to the `"runArgs"` parameter making the line look like this:
|
||||
`"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--net=host"],`
|
||||
2. Modify the file `.vscode/launch.json` and change the argument of `"gdbTarget"` to `"127.0.0.1:3333"`, making the line look like:
|
||||
`"gdbTarget": "127.0.0.1:3333",`
|
||||
3. To start debugging launch openocd on your host system with the appropriate configuration, for example with a stlink-v2 the command is:
|
||||
`openocd -f interface/stlink.cfg -f target/nrf52.cfg`. This launches openocd with the default ports `3333`, `4444` and `6666`.
|
||||
4. In VsCode go to the Debug pane on the left of the screen and select the configuration `Debug - Openocd docker Remote` and hit the play button on the left.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Apps
|
||||
|
||||
This page will teach you:
|
||||
|
||||
- what screens and apps are in InfiniTime
|
||||
- how to implement your own app
|
||||
|
||||
|
@ -14,6 +16,7 @@ Apps are responsible for everything drawn on the screen when they are running.
|
|||
By default, apps only do something (as in a function is executed) when they are created or when a touch event is detected.
|
||||
|
||||
## Interface
|
||||
|
||||
Every app class has to be inside the namespace `Pinetime::Applications::Screens` and inherit from `Screen`.
|
||||
The constructor should have at least one parameter `DisplayApp* app`, which it needs for the constructor of its parent class Screen.
|
||||
Other parameters should be references to controllers that the app needs.
|
||||
|
@ -24,10 +27,12 @@ it does not need to override any of these functions, as LVGL can also handle tou
|
|||
If you have any doubts, you can always look at how the other apps function for reference.
|
||||
|
||||
### Continuous updating
|
||||
|
||||
If your app needs to be updated continuously, you can do so by overriding the `Refresh()` function in your class
|
||||
and calling `lv_task_create` inside the constructor.
|
||||
|
||||
An example call could look like this:
|
||||
|
||||
```cpp
|
||||
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
|
||||
```
|
||||
|
@ -37,9 +42,11 @@ Remember to delete the task again using `lv_task_del`.
|
|||
The function `RefreshTaskCallback` is inherited from `Screen` and just calls your `Refresh` function.
|
||||
|
||||
## Creating your own app
|
||||
|
||||
A minimal app could look like this:
|
||||
|
||||
MyApp.h:
|
||||
|
||||
```cpp
|
||||
#pragma once
|
||||
|
||||
|
@ -60,6 +67,7 @@ namespace Pinetime {
|
|||
```
|
||||
|
||||
MyApp.cpp:
|
||||
|
||||
```cpp
|
||||
#include "displayapp/screens/MyApp.h"
|
||||
#include "displayapp/DisplayApp.h"
|
||||
|
@ -77,6 +85,7 @@ MyApp::~MyApp() {
|
|||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
```
|
||||
|
||||
Both of these files should be in [displayapp/screens/](/src/displayapp/screens/)
|
||||
or [displayapp/screens/settings/](/src/displayapp/screens/settings/) if it's a setting app.
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
# Introduction to the code
|
||||
|
||||
This page is meant to guide you through the source code, so you can find the relevant files for what you're working on.
|
||||
|
||||
## FreeRTOS
|
||||
|
||||
Infinitime is based on FreeRTOS, a real-time operating system.
|
||||
FreeRTOS provides several quality of life abstractions (for example easy software timers)
|
||||
and most importantly supports multiple tasks.
|
||||
|
@ -12,6 +14,7 @@ The task scheduler is responsible for giving every task enough cpu time.
|
|||
As there is only one core on the SoC of the PineTime, real concurrency is impossible and the scheduler has to swap tasks in and out to emulate it.
|
||||
|
||||
### Tasks
|
||||
|
||||
Tasks are created by calling `xTaskCreate` and passing a function with the signature `void functionName(void*)`.
|
||||
For more info on task creation see the [FreeRTOS Documentation](https://www.freertos.org/a00125.html).
|
||||
In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**.
|
||||
|
@ -29,6 +32,7 @@ it will need instead of just typing in a large-ish number.
|
|||
You can use `configMINIMAL_STACK_SIZE` which is currently set to 120 words.
|
||||
|
||||
## Controllers
|
||||
|
||||
Controllers in InfiniTime are singleton objects that can provide access to certain resources to apps.
|
||||
Some of them interface with drivers, others are the driver for the resource.
|
||||
The resources provided don't have to be hardware-based.
|
||||
|
@ -37,7 +41,9 @@ Some controllers can be passed by reference to apps that need access to the reso
|
|||
They reside in [components/](/src/components/) inside their own subfolder.
|
||||
|
||||
## Apps
|
||||
|
||||
For more detail see the [Apps page](./Apps.md)
|
||||
|
||||
## Bluetooth
|
||||
|