<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pine64.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Caligari</id>
	<title>PINE64 - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pine64.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Caligari"/>
	<link rel="alternate" type="text/html" href="https://wiki.pine64.org/wiki/Special:Contributions/Caligari"/>
	<updated>2026-04-30T13:12:18Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Hardware_Wishlist&amp;diff=8361</id>
		<title>PineTime Hardware Wishlist</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Hardware_Wishlist&amp;diff=8361"/>
		<updated>2020-12-02T18:42:56Z</updated>

		<summary type="html">&lt;p&gt;Caligari: /* Hardware */ My hardware wishes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains a list of things people wish PineTime did differently&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
&lt;br /&gt;
* Long pressing the button should power-cycle the watch without any software being involved&lt;br /&gt;
* Used sensors should be NDA-free and preferably also blob-free&lt;br /&gt;
* Other display tech could be explored. [//en.Wikipedia.org/wiki/Transflective_liquid-crystal_display A transflective LCD] would probably be a nice option. Or potentially OLED?&lt;br /&gt;
* Touchscreen should possibly have a configurable sensitivity level for both glove-wearing and droplet-resistance. Preferably it should still be a capacitive one, a resistive touchscreen would have too many trade-offs.&lt;br /&gt;
* A slightly bigger 256×256 pixel graphics display size is preferable for its binary alignment, affording some low-level simplicity – it has the property that its X and Y coördinates are each addressable with a single byte, with no out-of-bounds; its total number of pixels is 65536 (another power of 2), and each pixel is addressable with exactly 2 bytes, with perfect efficiency. The [http://Pelulamu.net/ibniz IBNIZ (Ideally Bare Numeric Impression giZmo) virtual machine], designed for fun minimalist demoscene graphics, has chosen 256×256 for its virtual display, and makes use of these simplicity advantages. If PineTime also chose 256×256 then it would be a target platform for unclipped IBNIZ demoscene programmes, which would be really fun to play around with on one's wrist!&lt;br /&gt;
* A full redraw on the display takes 120ms at the very least, which is 8Hz. A smooth scrolling/usage/animation experience would be 30Hz minimum, preferably 60. I heard a rumor that the SPI connection to the display is a bottleneck. Can this be fixed?&lt;br /&gt;
* Some sort of scroll wheel would be nice for convenience.&lt;br /&gt;
* Changed GPIO assignment so more functionality is available (i.e. NFC and VSYNC)&lt;br /&gt;
* Wireless charging, or Qi Charging capability&lt;br /&gt;
* An external RTC circuit saving the current time to allow the main MCU go to deep-sleep.&lt;br /&gt;
* nrf52840 update, that'll allow SPI x4 speed faster than nrf52832 and moreeeee RAM.&lt;br /&gt;
* A couple of pins on the programmer connector to allow UART while developing (currently there is a TX test point on PCB).&lt;br /&gt;
* Connect the pin of LCD controller that allows RD/WR from it in order to save RAM on the MCU.&lt;br /&gt;
* LCD must be centered on case. Currently is not and watchfaces seems different when clock is put on the other wrist.&lt;br /&gt;
* A NFC antenna around the case, connected to the NFC pins.&lt;br /&gt;
* BMA421 accelerometer doesn't have a datasheet (it seems private to some hardware integrators): take it off and put alternative with open documentation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_bootloader_improvements&amp;diff=8327</id>
		<title>PineTime bootloader improvements</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_bootloader_improvements&amp;diff=8327"/>
		<updated>2020-11-30T04:17:30Z</updated>

		<summary type="html">&lt;p&gt;Caligari: Link to the proposal of external flash partitioning&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Request for comments == &lt;br /&gt;
In this page, I explain the changes and improvements I would like to implement to the MCUBoot bootloader to make it more reliable, and to allow bootloader upgrade and switch (mcuboot &amp;lt;-&amp;gt; wasp-bootloader, for example). &lt;br /&gt;
I try to explain why I made these choices too.&lt;br /&gt;
&lt;br /&gt;
Do not hesitate to edit this page and add a new section if you want to add any comment to these points (if you agree, disagree, want to try something else,...).&lt;br /&gt;
&lt;br /&gt;
== Introduction == &lt;br /&gt;
This pages describes the improvements I propose to make to the bootloader and OTA to make the whole process more reliable.&lt;br /&gt;
&lt;br /&gt;
My goals are:&lt;br /&gt;
&lt;br /&gt;
* KISS : Keep It Stupid Simple. Simple code contains less bugs than complicated/complex code.&lt;br /&gt;
* As reliable as possible. 100% reliability is not feasible with the current hardware (no physical reset button, no bootloader in ROM code,...), but let's try to reach 99.9% reliability :)&lt;br /&gt;
* Provide a read-only factory image we'll be able to restore in case of unrecoverable errors during OTA&lt;br /&gt;
* Provide a way to upgrade the bootloader&lt;br /&gt;
* Provide a way to switch from MCUBoot to NRF bootloaders&lt;br /&gt;
&lt;br /&gt;
== Current memory map == &lt;br /&gt;
&lt;br /&gt;
[[PineTime| Pinetime Devkit0]] is using a nRF52832-QFAA MCU with 512kB flash and a [https://datasheet.lcsc.com/szlcsc/2005251035_XTX-XT25F32BSOIGU-S_C558851.pdf XT25F32B SPI NOR external flash] with 4096kB.&lt;br /&gt;
&lt;br /&gt;
[[File:MemoryMap.png]]&lt;br /&gt;
&lt;br /&gt;
Internal flash (512Kb):&lt;br /&gt;
* Page size is 4Kb.&lt;br /&gt;
* Bootloader contains the MCUBoot bootloader. &lt;br /&gt;
* Boot log is currently not used. Can be use to provide reboot logs to the application&lt;br /&gt;
* App is the PRIMARY SLOT for MCUBoot : the firmware that is currently running.&lt;br /&gt;
* Scratch is used by MCUBoot as temporary storage for swap operation&lt;br /&gt;
&lt;br /&gt;
External flash (4096Kb):&lt;br /&gt;
* Page size is 256 bytes.&lt;br /&gt;
* Bootloader assets : boot logo&lt;br /&gt;
* OTA : SECONDARY SLOT for MCUBoot. During OTA, this is where the new version of the firmware is stored.&lt;br /&gt;
* FS : space available for the application firmware.&lt;br /&gt;
&lt;br /&gt;
This memory map allows a strong boundary between the bootloader and the application :&lt;br /&gt;
* The bootloader is ran by the MCU at reset time and loads its boot logo from the SPI flash&lt;br /&gt;
* The bootloader (MCUBoot) swaps images from primary and secondary slots if necessary&lt;br /&gt;
* The bootloader starts the watchdog&lt;br /&gt;
* The bootloader jumps to 0x8000 to run the application&lt;br /&gt;
&lt;br /&gt;
The application don't know anything about the bootloader except that:&lt;br /&gt;
* it must be linked @0x8000&lt;br /&gt;
* it must refresh the watchdog periodically&lt;br /&gt;
* it must store the image for OTA at a specific location in the external SPI flash memory&lt;br /&gt;
&lt;br /&gt;
In this configuration, the boot logo is part of the bootloader, not of the application : the same logo will be displayed whatever application firmware will be loaded.&lt;br /&gt;
&lt;br /&gt;
== Changes == &lt;br /&gt;
&lt;br /&gt;
=== Factory image ===&lt;br /&gt;
The factory image is a 'light' build of InfiniTime that contains the bare minimum code to provide OTA to the user : basic UI, BLE and OTA. No apps, no fancy functionalities,...&lt;br /&gt;
This factory image will be stored in the &amp;quot;bootloader assets&amp;quot; area of the external flash memory.&lt;br /&gt;
&lt;br /&gt;
This factory image will be restored either automatically, when the bootloader detect it cannot boot from primary slot (App in internal memory) and secondary slot (OTA from exeternal).&lt;br /&gt;
The user can also request to restore this factory image if necessary (using the button?).&lt;br /&gt;
&lt;br /&gt;
=== Bootloader assets ===&lt;br /&gt;
Graphics can be compressed using a simple RLE encoding. RLE encoding on 1 bits (2 colors images) is very efficient (115200KB -&amp;gt; 1-5KB).&lt;br /&gt;
&lt;br /&gt;
In order to simplify the code, the graphics will be stored into the bootloader code instead of storing them into the external flash:&lt;br /&gt;
 - Less code.&lt;br /&gt;
 - Easier to document : 1 specific logo = bootloader mode&lt;br /&gt;
 - Do not have to worry about the dynamic size of the logo (the binary size of the graphics will vary with the content when they are RLE encoded).&lt;br /&gt;
&lt;br /&gt;
=== Bootloader === &lt;br /&gt;
* Display the bootloader version on the screen and expose the version to the application firmware&lt;br /&gt;
* Provide a way to revert the firmware to the last working version AND to the factory firmware&lt;br /&gt;
* Display status and progression (progress bar similar to wasp-reloader, color code,...)&lt;br /&gt;
* Test as much as possible&lt;br /&gt;
&lt;br /&gt;
=== Bootloader workflow ===&lt;br /&gt;
[[File:PineTimeBootloaderWorkflow.png]]&lt;br /&gt;
&lt;br /&gt;
=== Upgrade &amp;amp; Reloader === &lt;br /&gt;
The reloader is a tool that allows to upgrade the current version of the bootloader AND to switch from MCUBoot to NRF and vice versa.&lt;br /&gt;
&lt;br /&gt;
==== How does it work ? ====&lt;br /&gt;
* Upgrade&lt;br /&gt;
** The reloader is first OTAed like any firmware upgrade.&lt;br /&gt;
** When the system resets, MCUBoot swaps the application firmware with the reloader. The reloader upgrade the current bootloader and resets the system. It does NOT flag the image as validated. It resets the MCU.&lt;br /&gt;
** The new version of MCUBoot notice that the last upgrade is not validated and reverts to the firmware that was running just before.&lt;br /&gt;
** Voilà, you're running your firmware and a new version of the bootloader&lt;br /&gt;
&lt;br /&gt;
* Switch bootloader&lt;br /&gt;
** The reloader is first OTAed like any firmware upgrade.&lt;br /&gt;
** When the system resets, MCUBoot swaps the application firmware with the reloader. The reloader overwrite the current bootloader with a new one and reset.&lt;br /&gt;
** The new bootloader is running.&lt;br /&gt;
&lt;br /&gt;
* Switch&lt;br /&gt;
** From InfiniTime to wasp-os : the reloader contains the NRF Bootloader and Softdevice. This bootloader provides the OTA mecanism out of the box. Wasp-os is downloaded when the NRF bootloader is running&lt;br /&gt;
** From wasp-os to InfiniTime : the reloader contains the factory image (infinitime-factory). The complete version of InfiniTime will be OTAed when this factory image is running.&lt;br /&gt;
&lt;br /&gt;
== Discussions == &lt;br /&gt;
=== Boot Logo : embedded into the bootloader binary vs stored in the external SPI flash ===&lt;br /&gt;
Embedding (and compressing) the boot logo inside the bootloader binary brings many advantages:&lt;br /&gt;
* All the data are available in memory at runtime. No need to load them &amp;amp; check them, and no need to handle errors and invalid corrupted data.&lt;br /&gt;
* The data is available and can be sent directly to the display controller&lt;br /&gt;
* 1 unique logo for the bootloader : easier to document and explain to the user that this specific logo is the logo from the bootloader mode.&lt;br /&gt;
&lt;br /&gt;
But it also has some disadvantages:&lt;br /&gt;
* 1-Bit RLE encoding (very effective compression) allows only 2 colors (background/foreground)&lt;br /&gt;
* The boot logo cannot be customized (unless you recompile and flash this new build of the bootloader)&lt;br /&gt;
* The size of the boot logo is limited (depending on the compression ratio)&lt;br /&gt;
&lt;br /&gt;
My (JF) point is that the bootloader must be as reliable as possible. I would like to remove all part of the code than can fail. If we read the boot logo from the SPI flash, we will write something like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;int ret;&lt;br /&gt;
boot_logo_info info;&lt;br /&gt;
ret = SpiNor_read(infoOffset, &amp;amp;info, sizeof(boot_logo_info));&lt;br /&gt;
if(ret != 0) {&lt;br /&gt;
  // Something went wrong while reading image info&lt;br /&gt;
  panic(); // ? reset ?&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(check_boot_logo_info(info) == false) {&lt;br /&gt;
  // image info are invalid (ex : size &amp;gt; 240*240), we cannot use them&lt;br /&gt;
  panic(); // ? reset ? Display nothing?&lt;br /&gt;
}&lt;br /&gt;
... &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
We could find invalid image info if a firmware did not respect the memory map and erased/overwrote the external memory map. In this case, the bootloader couldn't run properly.&lt;br /&gt;
Of course, we can implement something smart in panic() (retry, use failover values,...), but again, this adds complexity and bug probability.&lt;br /&gt;
&lt;br /&gt;
All these if's that call panic() can be avoided by using hard-coded values at build-time.&lt;br /&gt;
&lt;br /&gt;
If the image is hard-coded, you won't be able to easily (not that easy, actually...) customize the boot logo. But remember that this logo is only display for a short time only when the device reset (manually or during an OTA).&lt;br /&gt;
&lt;br /&gt;
=== Why not add OTA functionality to the bootloader ? ===&lt;br /&gt;
This is exactly how the NRF bootloader/SoftDevice works: the bootloader is a standalone firmware that provides OTA functionality thanks to the SoftDevice. The downside is that the BLE stack needed to provide OTA is quite big and uses a lot of space in flash memory (~124kB according to the documentation). This is roughly 1/4 of the available space in the internal flash memory.&lt;br /&gt;
&lt;br /&gt;
Firmware based on the NRF SoftDevice share the BLE stack with the bootloader, it is mutualised between both entities.&lt;br /&gt;
The downside of this design is that firmwares developers are somewhat forced to use the NRF BLE stack. If they want to integrate another BLE stacak (NimBLE for example), these 120kB used by the SoftDevice would be wasted.&lt;br /&gt;
&lt;br /&gt;
That's why we decided to make the MCUBoot bootloader a simple bootloader without OTA functionality. It's very lighweight (less than 20kB) and leaves the developers the right to choose the BLE stack they want.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixed vs dynamic memory map ===&lt;br /&gt;
A dynamic memory map, using a partition stored in a fixed place (at the beginning of the external flash, for example) would allow different firmware to customize the partition table, image sizes,... and use the memory for efficiently.&lt;br /&gt;
&lt;br /&gt;
But it has the downside to add complexity and code that could fail.&lt;br /&gt;
&lt;br /&gt;
See [[PineTime external flash partitioning]] proposal.&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_external_flash_partitioning&amp;diff=8326</id>
		<title>PineTime external flash partitioning</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_external_flash_partitioning&amp;diff=8326"/>
		<updated>2020-11-30T04:17:05Z</updated>

		<summary type="html">&lt;p&gt;Caligari: Partition table draft-#0&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== The partition table ==&lt;br /&gt;
&lt;br /&gt;
Partitions on a storage (disk of flash memory) have different sizes depending on the type of data they contain. Size and location for those partitions could vary along the time, specially if the operating systems (&amp;quot;firmware&amp;quot; on embedded systems) are changed or the same OS is upgraded and it has the need of reestructuring the partitions. In any case, an index has to describe the partition structure somewhere.&lt;br /&gt;
&lt;br /&gt;
What is the basic info to know about a storage partitions? &lt;br /&gt;
&lt;br /&gt;
* The offset address: indicates where the partion starts on the storage.&lt;br /&gt;
* The partition size: how long is the partition from its offset address.&lt;br /&gt;
* The partition type: identifies what is the usage of the data contents.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Where to store the partition entries ===&lt;br /&gt;
&lt;br /&gt;
To put that index of partitions hardcoded with the firmware is a bad idea. How to know if those partitions are initializaded with the expected data type? What if the user decides to try another OS and it initializates the the partitions just like the developer has decided to do so? Installed OS has to check the rightness of the storage on every boot? Definitely, the index of partitions must be out of the own OS code in order to keep organized the data on the flash memory.&lt;br /&gt;
&lt;br /&gt;
==== PC ====&lt;br /&gt;
&lt;br /&gt;
Nowadays, personal computers use partition tables on every disk (see [https://en.wikipedia.org/wiki/GUID_Partition_Table GPT] and [https://en.wikipedia.org/wiki/Master_boot_record#PT MBR]). This partitions tables are located very close to the beginning of the disk (reserving some initial sector of bytes for old bootloaders). However, this partition tables are designed for very large disks and they have some complexity related to PC and its computer history, not really needed for flash memories.&lt;br /&gt;
&lt;br /&gt;
==== SBC ====&lt;br /&gt;
&lt;br /&gt;
Single board computers and embedded systems with the [https://en.wikipedia.org/wiki/Das_U-Boot U-Boot bootloader] store the partition index as parameters in the _mtdparts_ environment variable and it is passed to the OS as argument. This environment is hardcoded or stored in a defined partition as text. More recently, they use [https://en.wikipedia.org/wiki/Device_tree Device tree] but this is also stored in a partition.&lt;br /&gt;
&lt;br /&gt;
==== ESP32 ====&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/ESP32 ESP32] is a MCU managing partitions without hardcoded information and it is a good example to examine. It defines a [https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html partition table] of 3Kb length at a fixed position with capacity to define 95 partitions. Maybe some excessive but the interesting thing is that partition table follow the pattern &amp;quot;offset-size-type&amp;quot; as basic information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The summing-up is that every system using partion index and not hardcoded stores the partition entries in some storage space and, this partition table, can be considered a little partition too. It is located in a well-know offset address of the flash storage.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Paper ===&lt;br /&gt;
&lt;br /&gt;
PineTime is a device under open development and it offers undreamed possibilities to develop and to flash several firmwares by users. It might be convenient that external storage (SPI flash) can be accessed by using a partition table so, different firmwares will be able to share partitions with user information, settings, bluetooth bindings, calibration parameters, etcetera...&lt;br /&gt;
&lt;br /&gt;
For example, it is possible to organize the flash to save a logo shown by the bootloader. And it doesn't mean a mandatory requirement at the moment but bootloader or application can be changed and they will be able to found the logo to show or save a customized one.&lt;br /&gt;
&lt;br /&gt;
What is the cost of managing a partition table? In this case, community (developers) should be discuss and publish a paper with a proposal for the partition table structures and implement in their firmware for the Pinetime. It must be simple and suitable in order to organize the flash storage in partitions without more overhead than read the partition table, look for the partitions those are interested in and use them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Partition table draft-#0 ==&lt;br /&gt;
&lt;br /&gt;
Location of partition table: first page of external flash (256 bytes).&lt;br /&gt;
&lt;br /&gt;
=== C structures ===&lt;br /&gt;
&lt;br /&gt;
C code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	#define OFFSET_T uint32_t&lt;br /&gt;
	#define SIZE_T   uint32_t  &lt;br /&gt;
&lt;br /&gt;
	/* bits 0-7 is type, bits 8-15 is subtype, bits 16-31 are flags */&lt;br /&gt;
	#define TYPE_T   uint32_t  &lt;br /&gt;
&lt;br /&gt;
	struct partition_entry_t {&lt;br /&gt;
	    OFFSET_T offset;&lt;br /&gt;
	    SIZE_T size;&lt;br /&gt;
	    TYPE_T type;      &lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	struct partition_table_t {&lt;br /&gt;
	    uint32_t magic_bytes;           /* always 0x50494e45 (&amp;quot;PINE&amp;quot;) */&lt;br /&gt;
	    uint32_t reserved[2];           /* reserved, do not use */&lt;br /&gt;
	    partition_entry_t entries[20];  /* 20*sizeof(partition_entry_t) == 240 */&lt;br /&gt;
	    uint32_t checksum;              /* CRC-32 MPEG2 variant (used by MCU bootloader) */&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	#define PARTITION_TYPE_NOT_USED		0x00&lt;br /&gt;
	#define PARTITION_TYPE_BOOT_LOGO 	0x01&lt;br /&gt;
	#define PARTITION_TYPE_FACTORY_IMG 	0x02&lt;br /&gt;
	#define PARTITION_TYPE_LITTLE_FS 	0x03&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_bootloader_improvements&amp;diff=8298</id>
		<title>PineTime bootloader improvements</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_bootloader_improvements&amp;diff=8298"/>
		<updated>2020-11-28T13:43:38Z</updated>

		<summary type="html">&lt;p&gt;Caligari: /* Current memory map */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Request for comments == &lt;br /&gt;
In this page, I explain the changes and improvements I would like to implement to the MCUBoot bootloader to make it more reliable, and to allow bootloader upgrade and switch (mcuboot &amp;lt;-&amp;gt; wasp-bootloader, for example). &lt;br /&gt;
I try to explain why I made these choices too.&lt;br /&gt;
&lt;br /&gt;
Do not hesitate to edit this page and add a new section if you want to add any comment to these points (if you agree, disagree, want to try something else,...).&lt;br /&gt;
&lt;br /&gt;
== Introduction == &lt;br /&gt;
This pages describes the improvements I propose to make to the bootloader and OTA to make the whole process more reliable.&lt;br /&gt;
&lt;br /&gt;
My goals are:&lt;br /&gt;
&lt;br /&gt;
* KISS : Keep It Stupid Simple. Simple code contains less bugs than complicated/complex code.&lt;br /&gt;
* As reliable as possible. 100% reliability is not feasible with the current hardware (no physical reset button, no bootloader in ROM code,...), but let's try to reach 99.9% reliability :)&lt;br /&gt;
* Provide a read-only factory image we'll be able to restore in case of unrecoverable errors during OTA&lt;br /&gt;
* Provide a way to upgrade the bootloader&lt;br /&gt;
* Provide a way to switch from MCUBoot to NRF bootloaders&lt;br /&gt;
&lt;br /&gt;
== Current memory map == &lt;br /&gt;
&lt;br /&gt;
[[PineTime| Pinetime Devkit0]] is using a nRF52832-QFAA MCU with 512kB flash and a [https://datasheet.lcsc.com/szlcsc/2005251035_XTX-XT25F32BSOIGU-S_C558851.pdf XT25F32B SPI NOR external flash] with 4096kB.&lt;br /&gt;
&lt;br /&gt;
[[File:MemoryMap.png]]&lt;br /&gt;
&lt;br /&gt;
Internal flash (512Kb):&lt;br /&gt;
* Page size is 4Kb.&lt;br /&gt;
* Bootloader contains the MCUBoot bootloader. &lt;br /&gt;
* Boot log is currently not used. Can be use to provide reboot logs to the application&lt;br /&gt;
* App is the PRIMARY SLOT for MCUBoot : the firmware that is currently running.&lt;br /&gt;
* Scratch is used by MCUBoot as temporary storage for swap operation&lt;br /&gt;
&lt;br /&gt;
External flash (4096Kb):&lt;br /&gt;
* Page size is 256 bytes.&lt;br /&gt;
* Bootloader assets : boot logo&lt;br /&gt;
* OTA : SECONDARY SLOT for MCUBoot. During OTA, this is where the new version of the firmware is stored.&lt;br /&gt;
* FS : space available for the application firmware.&lt;br /&gt;
&lt;br /&gt;
This memory map allows a strong boundary between the bootloader and the application :&lt;br /&gt;
* The bootloader is ran by the MCU at reset time and loads its boot logo from the SPI flash&lt;br /&gt;
* The bootloader (MCUBoot) swaps images from primary and secondary slots if necessary&lt;br /&gt;
* The bootloader starts the watchdog&lt;br /&gt;
* The bootloader jumps to 0x8000 to run the application&lt;br /&gt;
&lt;br /&gt;
The application don't know anything about the bootloader except that:&lt;br /&gt;
* it must be linked @0x8000&lt;br /&gt;
* it must refresh the watchdog periodically&lt;br /&gt;
* it must store the image for OTA at a specific location in the external SPI flash memory&lt;br /&gt;
&lt;br /&gt;
In this configuration, the boot logo is part of the bootloader, not of the application : the same logo will be displayed whatever application firmware will be loaded.&lt;br /&gt;
&lt;br /&gt;
== Changes == &lt;br /&gt;
&lt;br /&gt;
=== Factory image ===&lt;br /&gt;
The factory image is a 'light' build of InfiniTime that contains the bare minimum code to provide OTA to the user : basic UI, BLE and OTA. No apps, no fancy functionalities,...&lt;br /&gt;
This factory image will be stored in the &amp;quot;bootloader assets&amp;quot; area of the external flash memory.&lt;br /&gt;
&lt;br /&gt;
This factory image will be restored either automatically, when the bootloader detect it cannot boot from primary slot (App in internal memory) and secondary slot (OTA from exeternal).&lt;br /&gt;
The user can also request to restore this factory image if necessary (using the button?).&lt;br /&gt;
&lt;br /&gt;
=== Bootloader assets ===&lt;br /&gt;
Graphics can be compressed using a simple RLE encoding. RLE encoding on 1 bits (2 colors images) is very efficient (115200KB -&amp;gt; 1-5KB).&lt;br /&gt;
&lt;br /&gt;
In order to simplify the code, the graphics will be stored into the bootloader code instead of storing them into the external flash:&lt;br /&gt;
 - Less code.&lt;br /&gt;
 - Easier to document : 1 specific logo = bootloader mode&lt;br /&gt;
 - Do not have to worry about the dynamic size of the logo (the binary size of the graphics will vary with the content when they are RLE encoded).&lt;br /&gt;
&lt;br /&gt;
=== Bootloader === &lt;br /&gt;
* Display the bootloader version on the screen and expose the version to the application firmware&lt;br /&gt;
* Provide a way to revert the firmware to the last working version AND to the factory firmware&lt;br /&gt;
* Display status and progression (progress bar similar to wasp-reloader, color code,...)&lt;br /&gt;
* Test as much as possible&lt;br /&gt;
&lt;br /&gt;
=== Upgrade &amp;amp; Reloader === &lt;br /&gt;
The reloader is a tool that allows to upgrade the current version of the bootloader AND to switch from MCUBoot to NRF and vice versa.&lt;br /&gt;
&lt;br /&gt;
==== How does it work ? ====&lt;br /&gt;
* Upgrade&lt;br /&gt;
** The reloader is first OTAed like any firmware upgrade.&lt;br /&gt;
** When the system resets, MCUBoot swaps the application firmware with the reloader. The reloader upgrade the current bootloader and resets the system. It does NOT flag the image as validated. It resets the MCU.&lt;br /&gt;
** The new version of MCUBoot notice that the last upgrade is not validated and reverts to the firmware that was running just before.&lt;br /&gt;
** Voilà, you're running your firmware and a new version of the bootloader&lt;br /&gt;
&lt;br /&gt;
* Switch bootloader&lt;br /&gt;
** The reloader is first OTAed like any firmware upgrade.&lt;br /&gt;
** When the system resets, MCUBoot swaps the application firmware with the reloader. The reloader overwrite the current bootloader with a new one and reset.&lt;br /&gt;
** The new bootloader is running.&lt;br /&gt;
&lt;br /&gt;
* Switch&lt;br /&gt;
** From InfiniTime to wasp-os : the reloader contains the NRF Bootloader and Softdevice. This bootloader provides the OTA mecanism out of the box. Wasp-os is downloaded when the NRF bootloader is running&lt;br /&gt;
** From wasp-os to InfiniTime : the reloader contains the factory image (infinitime-factory). The complete version of InfiniTime will be OTAed when this factory image is running.&lt;br /&gt;
&lt;br /&gt;
== Discussions == &lt;br /&gt;
=== Boot Logo : embedded into the bootloader binary vs stored in the external SPI flash ===&lt;br /&gt;
Embedding (and compressing) the boot logo inside the bootloader binary brings many advantages:&lt;br /&gt;
* All the data are available in memory at runtime. No need to load them &amp;amp; check them, and no need to handle errors and invalid corrupted data.&lt;br /&gt;
* The data is available and can be sent directly to the display controller&lt;br /&gt;
* 1 unique logo for the bootloader : easier to document and explain to the user that this specific logo is the logo from the bootloader mode.&lt;br /&gt;
&lt;br /&gt;
But it also has some disadvantages:&lt;br /&gt;
* 1-Bit RLE encoding (very effective compression) allows only 2 colors (background/foreground)&lt;br /&gt;
* The boot logo cannot be customized (unless you recompile and flash this new build of the bootloader)&lt;br /&gt;
* The size of the boot logo is limited (depending on the compression ratio)&lt;br /&gt;
&lt;br /&gt;
My (JF) point is that the bootloader must be as reliable as possible. I would like to remove all part of the code than can fail. If we read the boot logo from the SPI flash, we will write something like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;int ret;&lt;br /&gt;
boot_logo_info info;&lt;br /&gt;
ret = SpiNor_read(infoOffset, &amp;amp;info, sizeof(boot_logo_info));&lt;br /&gt;
if(ret != 0) {&lt;br /&gt;
  // Something went wrong while reading image info&lt;br /&gt;
  panic(); // ? reset ?&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(check_boot_logo_info(info) == false) {&lt;br /&gt;
  // image info are invalid (ex : size &amp;gt; 240*240), we cannot use them&lt;br /&gt;
  panic(); // ? reset ? Display nothing?&lt;br /&gt;
}&lt;br /&gt;
... &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
We could find invalid image info if a firmware did not respect the memory map and erased/overwrote the external memory map. In this case, the bootloader couldn't run properly.&lt;br /&gt;
Of course, we can implement something smart in panic() (retry, use failover values,...), but again, this adds complexity and bug probability.&lt;br /&gt;
&lt;br /&gt;
All these if's that call panic() can be avoided by using hard-coded values at build-time.&lt;br /&gt;
&lt;br /&gt;
If the image is hard-coded, you won't be able to easily (not that easy, actually...) customize the boot logo. But remember that this logo is only display for a short time only when the device reset (manually or during an OTA).&lt;br /&gt;
&lt;br /&gt;
=== Fixed vs dynamic memory map ===&lt;br /&gt;
A dynamic memory map, using a partition stored in a fixed place (at the beginning of the external flash, for example) would allow different firmware to customize the partition table, image sizes,... and use the memory for efficiently.&lt;br /&gt;
&lt;br /&gt;
But it has the downside to add complexity and code that could fail. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=File:MemoryMap.png&amp;diff=8297</id>
		<title>File:MemoryMap.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=File:MemoryMap.png&amp;diff=8297"/>
		<updated>2020-11-28T13:07:56Z</updated>

		<summary type="html">&lt;p&gt;Caligari: Caligari uploaded a new version of File:MemoryMap.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Current memory map of Pinetime using MCUBoot bootloader&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_bootloader_improvements&amp;diff=8296</id>
		<title>PineTime bootloader improvements</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_bootloader_improvements&amp;diff=8296"/>
		<updated>2020-11-28T12:47:25Z</updated>

		<summary type="html">&lt;p&gt;Caligari: /* Current memory map */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Request for comments == &lt;br /&gt;
In this page, I explain the changes and improvements I would like to implement to the MCUBoot bootloader to make it more reliable, and to allow bootloader upgrade and switch (mcuboot &amp;lt;-&amp;gt; wasp-bootloader, for example). &lt;br /&gt;
I try to explain why I made these choices too.&lt;br /&gt;
&lt;br /&gt;
Do not hesitate to edit this page and add a new section if you want to add any comment to these points (if you agree, disagree, want to try something else,...).&lt;br /&gt;
&lt;br /&gt;
== Introduction == &lt;br /&gt;
This pages describes the improvements I propose to make to the bootloader and OTA to make the whole process more reliable.&lt;br /&gt;
&lt;br /&gt;
My goals are:&lt;br /&gt;
&lt;br /&gt;
* KISS : Keep It Stupid Simple. Simple code contains less bugs than complicated/complex code.&lt;br /&gt;
* As reliable as possible. 100% reliability is not feasible with the current hardware (no physical reset button, no bootloader in ROM code,...), but let's try to reach 99.9% reliability :)&lt;br /&gt;
* Provide a read-only factory image we'll be able to restore in case of unrecoverable errors during OTA&lt;br /&gt;
* Provide a way to upgrade the bootloader&lt;br /&gt;
* Provide a way to switch from MCUBoot to NRF bootloaders&lt;br /&gt;
&lt;br /&gt;
== Current memory map == &lt;br /&gt;
&lt;br /&gt;
[[PineTime| Pinetime Devkit0]] is using a nRF52832-QFAA MCU with 512kB flash and a [https://datasheet.lcsc.com/szlcsc/2005251035_XTX-XT25F32BSOIGU-S_C558851.pdf XT25F32B SPI NOR external flash] with 4096kB.&lt;br /&gt;
&lt;br /&gt;
[[File:MemoryMap.png]]&lt;br /&gt;
&lt;br /&gt;
Internal flash (512Kb):&lt;br /&gt;
* Page size is 4Kb&lt;br /&gt;
* Bootloader contains the MCUBoot bootloader. &lt;br /&gt;
* Boot log is currently not used. Can be use to provide reboot logs to the application&lt;br /&gt;
* App is the PRIMARY SLOT for MCUBoot : the firmware that is currently running.&lt;br /&gt;
* Scratch is used by MCUBoot as temporary storage for swap operation&lt;br /&gt;
&lt;br /&gt;
External flash (4096Kb):&lt;br /&gt;
* Bootloader assets : boot logo&lt;br /&gt;
* OTA : SECONDARY SLOT for MCUBoot. During OTA, this is where the new version of the firmware is stored.&lt;br /&gt;
* FS : space available for the application firmware.&lt;br /&gt;
&lt;br /&gt;
This memory map allows a strong boundary between the bootloader and the application :&lt;br /&gt;
* The bootloader is ran by the MCU at reset time and loads its boot logo from the SPI flash&lt;br /&gt;
* The bootloader (MCUBoot) swaps images from primary and secondary slots if necessary&lt;br /&gt;
* The bootloader starts the watchdog&lt;br /&gt;
* The bootloader jumps to 0x8000 to run the application&lt;br /&gt;
&lt;br /&gt;
The application don't know anything about the bootloader except that:&lt;br /&gt;
* it must be linked @0x8000&lt;br /&gt;
* it must refresh the watchdog periodically&lt;br /&gt;
* it must store the image for OTA at a specific location in the external SPI flash memory&lt;br /&gt;
&lt;br /&gt;
In this configuration, the boot logo is part of the bootloader, not of the application : the same logo will be displayed whatever application firmware will be loaded.&lt;br /&gt;
&lt;br /&gt;
== Changes == &lt;br /&gt;
&lt;br /&gt;
=== Factory image ===&lt;br /&gt;
The factory image is a 'light' build of InfiniTime that contains the bare minimum code to provide OTA to the user : basic UI, BLE and OTA. No apps, no fancy functionalities,...&lt;br /&gt;
This factory image will be stored in the &amp;quot;bootloader assets&amp;quot; area of the external flash memory.&lt;br /&gt;
&lt;br /&gt;
This factory image will be restored either automatically, when the bootloader detect it cannot boot from primary slot (App in internal memory) and secondary slot (OTA from exeternal).&lt;br /&gt;
The user can also request to restore this factory image if necessary (using the button?).&lt;br /&gt;
&lt;br /&gt;
=== Bootloader assets ===&lt;br /&gt;
Graphics can be compressed using a simple RLE encoding. RLE encoding on 1 bits (2 colors images) is very efficient (115200KB -&amp;gt; 1-5KB).&lt;br /&gt;
&lt;br /&gt;
In order to simplify the code, the graphics will be stored into the bootloader code instead of storing them into the external flash:&lt;br /&gt;
 - Less code.&lt;br /&gt;
 - Easier to document : 1 specific logo = bootloader mode&lt;br /&gt;
 - Do not have to worry about the dynamic size of the logo (the binary size of the graphics will vary with the content when they are RLE encoded).&lt;br /&gt;
&lt;br /&gt;
=== Bootloader === &lt;br /&gt;
* Display the bootloader version on the screen and expose the version to the application firmware&lt;br /&gt;
* Provide a way to revert the firmware to the last working version AND to the factory firmware&lt;br /&gt;
* Display status and progression (progress bar similar to wasp-reloader, color code,...)&lt;br /&gt;
* Test as much as possible&lt;br /&gt;
&lt;br /&gt;
=== Upgrade &amp;amp; Reloader === &lt;br /&gt;
The reloader is a tool that allows to upgrade the current version of the bootloader AND to switch from MCUBoot to NRF and vice versa.&lt;br /&gt;
&lt;br /&gt;
==== How does it work ? ====&lt;br /&gt;
* Upgrade&lt;br /&gt;
** The reloader is first OTAed like any firmware upgrade.&lt;br /&gt;
** When the system resets, MCUBoot swaps the application firmware with the reloader. The reloader upgrade the current bootloader and resets the system. It does NOT flag the image as validated. It resets the MCU.&lt;br /&gt;
** The new version of MCUBoot notice that the last upgrade is not validated and reverts to the firmware that was running just before.&lt;br /&gt;
** Voilà, you're running your firmware and a new version of the bootloader&lt;br /&gt;
&lt;br /&gt;
* Switch bootloader&lt;br /&gt;
** The reloader is first OTAed like any firmware upgrade.&lt;br /&gt;
** When the system resets, MCUBoot swaps the application firmware with the reloader. The reloader overwrite the current bootloader with a new one and reset.&lt;br /&gt;
** The new bootloader is running.&lt;br /&gt;
&lt;br /&gt;
* Switch&lt;br /&gt;
** From InfiniTime to wasp-os : the reloader contains the NRF Bootloader and Softdevice. This bootloader provides the OTA mecanism out of the box. Wasp-os is downloaded when the NRF bootloader is running&lt;br /&gt;
** From wasp-os to InfiniTime : the reloader contains the factory image (infinitime-factory). The complete version of InfiniTime will be OTAed when this factory image is running.&lt;br /&gt;
&lt;br /&gt;
== Discussions == &lt;br /&gt;
=== Boot Logo : embedded into the bootloader binary vs stored in the external SPI flash ===&lt;br /&gt;
Embedding (and compressing) the boot logo inside the bootloader binary brings many advantages:&lt;br /&gt;
* All the data are available in memory at runtime. No need to load them &amp;amp; check them, and no need to handle errors and invalid corrupted data.&lt;br /&gt;
* The data is available and can be sent directly to the display controller&lt;br /&gt;
* 1 unique logo for the bootloader : easier to document and explain to the user that this specific logo is the logo from the bootloader mode.&lt;br /&gt;
&lt;br /&gt;
But it also has some disadvantages:&lt;br /&gt;
* 1-Bit RLE encoding (very effective compression) allows only 2 colors (background/foreground)&lt;br /&gt;
* The boot logo cannot be customized (unless you recompile and flash this new build of the bootloader)&lt;br /&gt;
* The size of the boot logo is limited (depending on the compression ratio)&lt;br /&gt;
&lt;br /&gt;
My (JF) point is that the bootloader must be as reliable as possible. I would like to remove all part of the code than can fail. If we read the boot logo from the SPI flash, we will write something like this:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;int ret;&lt;br /&gt;
boot_logo_info info;&lt;br /&gt;
ret = SpiNor_read(infoOffset, &amp;amp;info, sizeof(boot_logo_info));&lt;br /&gt;
if(ret != 0) {&lt;br /&gt;
  // Something went wrong while reading image info&lt;br /&gt;
  panic(); // ? reset ?&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if(check_boot_logo_info(info) == false) {&lt;br /&gt;
  // image info are invalid (ex : size &amp;gt; 240*240), we cannot use them&lt;br /&gt;
  panic(); // ? reset ? Display nothing?&lt;br /&gt;
}&lt;br /&gt;
... &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
We could find invalid image info if a firmware did not respect the memory map and erased/overwrote the external memory map. In this case, the bootloader couldn't run properly.&lt;br /&gt;
Of course, we can implement something smart in panic() (retry, use failover values,...), but again, this adds complexity and bug probability.&lt;br /&gt;
&lt;br /&gt;
All these if's that call panic() can be avoided by using hard-coded values at build-time.&lt;br /&gt;
&lt;br /&gt;
If the image is hard-coded, you won't be able to easily (not that easy, actually...) customize the boot logo. But remember that this logo is only display for a short time only when the device reset (manually or during an OTA).&lt;br /&gt;
&lt;br /&gt;
=== Fixed vs dynamic memory map ===&lt;br /&gt;
A dynamic memory map, using a partition stored in a fixed place (at the beginning of the external flash, for example) would allow different firmware to customize the partition table, image sizes,... and use the memory for efficiently.&lt;br /&gt;
&lt;br /&gt;
But it has the downside to add complexity and code that could fail. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime&amp;diff=7902</id>
		<title>PineTime</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime&amp;diff=7902"/>
		<updated>2020-10-19T20:57:11Z</updated>

		<summary type="html">&lt;p&gt;Caligari: /* Display */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Frequently asked questions ==&lt;br /&gt;
&lt;br /&gt;
'''Read these first!'''&lt;br /&gt;
&lt;br /&gt;
* [[Frequently asked questions about the PineTime| Frequently Asked Questions about the devkit]]&lt;br /&gt;
* [[Reprogramming the PineTime|Reprogramming the PineTime (development kit)]]&lt;br /&gt;
&lt;br /&gt;
== Default OS ==&lt;br /&gt;
&lt;br /&gt;
The current default operating system on the PineTime is called [[InfiniTime]]. First devkits shipped with a proprietary custom firmware. The project was started by JF002 and is shipped with the latest edition of PineTime. You can use various companion apps with the OS, for example Gadgetbridge.&lt;br /&gt;
&lt;br /&gt;
== Short overview ==&lt;br /&gt;
'''Dimensions:''' 37.5 x 40 x 11mm &amp;lt;br&amp;gt;&lt;br /&gt;
'''Weight:''' 38 grams &amp;lt;br&amp;gt;&lt;br /&gt;
'''IP Rating:''' IP67 (waterproof to 1 meter (sealed edition!)) &amp;lt;br&amp;gt;&lt;br /&gt;
'''Display:'''&lt;br /&gt;
: '''Size:''' 1.3 inches (33mm) diagonal&lt;br /&gt;
: '''Type:''' IPS capacitive touchscreen, RGB 65K colors&lt;br /&gt;
: '''Display Controller:''' ST7789&lt;br /&gt;
: '''Resolution:''' 240x240 pixels &amp;lt;br&amp;gt;&lt;br /&gt;
'''System on Chip:''' Nordic Semiconductor nRF52832 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Flash:''' 512KB with additional 4MB SPI NOR &amp;lt;br&amp;gt;&lt;br /&gt;
'''RAM:''' 64KB &amp;lt;br&amp;gt;&lt;br /&gt;
'''Bluetooth:''' [[PineTime_Bluetooth|5.0 (including Bluetooth Low Energy)]] &amp;lt;br&amp;gt;&lt;br /&gt;
'''Sensors:''' Accelerometer, Heart rate sensor &amp;lt;br&amp;gt;&lt;br /&gt;
'''Feedback:''' Vibration motor &amp;lt;br&amp;gt;&lt;br /&gt;
'''Battery:''' 170-180mAh LiPo&lt;br /&gt;
&lt;br /&gt;
= Community =&lt;br /&gt;
* [https://forum.pine64.org/forumdisplay.php?fid=134 PineTime forum]&lt;br /&gt;
* [https://app.element.io/#/room/#pinetime:matrix.org Matrix Channel] (No login required to read)&lt;br /&gt;
* IRC Server: [ircs://irc.pine64.org#pinetime irc.pine64.org] Channel: PineTime&lt;br /&gt;
* [https://t.me/pinetime Telegram group]&lt;br /&gt;
* [https://discordapp.com/invite/DgB7kzr Discord server invite link]&lt;br /&gt;
&lt;br /&gt;
== Development efforts ==&lt;br /&gt;
&lt;br /&gt;
To read more about development on the PineTime, the projects available and more technical details, check out [[PineTime Development]]&lt;br /&gt;
&lt;br /&gt;
== Useful articles and blog posts == &lt;br /&gt;
&lt;br /&gt;
If you want to dive in to the ecosystem, here's a short list of various articles and blog posts that can help you set up your soft- or hardware development environment.&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/swlh/sneak-peek-of-pinetime-smart-watch-and-why-its-perfect-for-teaching-iot-81b74161c159 Sneak Peek of PineTime Smart Watch… And why it’s perfect for teaching IoT]&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/@ly.lee/building-a-rust-driver-for-pinetimes-touch-controller-cbc1a5d5d3e9 Building a Rust Driver for PineTime’s Touch Controller]&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/@ly.lee/porting-druid-rust-widgets-to-pinetime-smart-watch-7e1d5a5d977a Porting (druid) Rust Widgets to PineTime Smart Watch]&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/@ly.lee/optimising-pinetimes-display-driver-with-rust-and-mynewt-3ba269ea2f5c Optimising PineTime’s Display Driver with Rust and Mynewt]&lt;br /&gt;
&lt;br /&gt;
* [https://www.zephyrproject.org/getting-started-with-zephyr-rtos-on-nordic-nrf52832-hackable/ Getting Started with Zephyr RTOS on Nordic nRF52832 hackaBLE]&lt;br /&gt;
&lt;br /&gt;
* [https://blog.aegrel.ee/absniffer-cmsis-dap-sniffer.html Removing the lock and installing another firmware on the nRF52832 using CMSIS-DAP dongle on Linux]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/JF002/nrf52-baseproject/wiki/Build,-program-and-debug-NRF52-project-with-JLink,-CMake-and-CLion Build, program and debug NRF52 project with JLink, CMake and CLion]&lt;br /&gt;
&lt;br /&gt;
* [https://www.nrbtech.io/blog/2020/1/4/using-clion-for-nordic-nrf52-projects Using CLion for Nordic nRF52 projects]&lt;br /&gt;
&lt;br /&gt;
* [https://dev.to/aaronc81/flashing-your-pinetime-using-an-st-link-and-openocd-54dd Flashing your PineTime using an ST-Link and OpenOCD]&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Display ===&lt;br /&gt;
&lt;br /&gt;
Note: The factory-default software on the PineTime does not auto-detect the display being disconnected when it has already booted. That can cause garbled output, to fix it just restart the PineTime.&lt;br /&gt;
&lt;br /&gt;
The display is driven using the ST7789 display controller. Use the following pins to drive the screen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! PineTime pin&lt;br /&gt;
! ST7789 pin&lt;br /&gt;
|-&lt;br /&gt;
| LCD_SCK (P0.02)&lt;br /&gt;
| SPI clock&lt;br /&gt;
|-&lt;br /&gt;
| LCD_SDI (P0.03)&lt;br /&gt;
| SPI MOSI&lt;br /&gt;
|-&lt;br /&gt;
| LCD_RS (P0.18)&lt;br /&gt;
| Command/Data pin (CD)&lt;br /&gt;
|-&lt;br /&gt;
| LCD_CS (P0.25)&lt;br /&gt;
| Chip select&lt;br /&gt;
|-&lt;br /&gt;
| LCD_RESET (P0.26)&lt;br /&gt;
| Display reset&lt;br /&gt;
|-&lt;br /&gt;
| LCD_BACKLIGHT_{LOW,MID,HIGH}&lt;br /&gt;
| Backlight (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
* Chip select must be held low while driving the display. It must be high when using other SPI devices on the same bus (such as external flash storage) so that the display controller won't respond to the wrong commands.&lt;br /&gt;
* SPI must be used in mode 3. Mode 0 (the default) won't work.&lt;br /&gt;
* LCD_DISPLAY_* is used to enable the backlight. Set at least one to low to see anything on the screen.&lt;br /&gt;
* Use SPI at 8MHz (the fastest clock available on the nRF52832) because otherwise refreshing will be super slow.&lt;br /&gt;
&lt;br /&gt;
'''References''':&lt;br /&gt;
&lt;br /&gt;
[https://github.com/adafruit/Adafruit-ST7735-Library/ Adafruit ST7789 driver in cpp]&lt;br /&gt;
&lt;br /&gt;
=== Battery measurement ===&lt;br /&gt;
&lt;br /&gt;
Reading whether the PineTime has power attached is easy: simply read the charge indication pin (P0.12). When it is high it is running on battery, when it is low it is charging.&lt;br /&gt;
&lt;br /&gt;
Reading the battery voltage is a bit harder. For that you can use the battery voltage pin on P0.31 (AIN7). The returned value is 12 bits, which means it is 0..4095. You can get the measured voltage with the following formula, assuming a reference voltage of 3.3V (this is configurable in the ADC):&lt;br /&gt;
&lt;br /&gt;
 adcVoltage = adcValue / (4095 / 3.3)&lt;br /&gt;
&lt;br /&gt;
The measured voltage is actually half of the actual battery voltage, because the ADC is connected between a voltage divider where both resistors are 1MΩ. This can be corrected by multiplying the value:&lt;br /&gt;
&lt;br /&gt;
 batteryVoltage = adcValue * 2 / (4095 / 3.3)&lt;br /&gt;
&lt;br /&gt;
It's often better to avoid floating point values on embedded systems and in this case there is no reason to use float at all, we can just represent the value in millivolts. Therefore the formula can be simplified to:&lt;br /&gt;
&lt;br /&gt;
 batteryVoltage = adcValue * 2000 / (4095 / 3.3)&lt;br /&gt;
 batteryVoltage = adcValue * 2000 / 1241&lt;br /&gt;
&lt;br /&gt;
Converting this voltage to an estimated capacity in percent requires a more complicated algorithm, because Lithium-ion batteries have a non-linear discharge curve.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Button ===&lt;br /&gt;
&lt;br /&gt;
The button on the side of the PineTime is disabled by default. To enable it, drive the button out pin (P0.15) high.&lt;br /&gt;
&lt;br /&gt;
While enabled, the button in pin (P0.13) will be high when the button is pressed, and low when it is not pressed.&lt;br /&gt;
&lt;br /&gt;
=== Touch panel ===&lt;br /&gt;
&lt;br /&gt;
The touch panel is controlled by a Hynitron CST816S chips. Unfortunately, there is not much information about this chip on the internet apart from the datasheet below and a [https://github.com/lupyuen/hynitron_i2c_cst0xxse/ reference driver]. This is enough to implement a basic driver, but crucial information needed to implement advanced functionalities are missing (I²C protocol and registers, timings, power modes,...).&lt;br /&gt;
&lt;br /&gt;
==== Pins ====&lt;br /&gt;
&lt;br /&gt;
* P0.10 : Reset&lt;br /&gt;
* P0.28 : Interrupt (signal to the CPU when a touch event is detected)&lt;br /&gt;
* P0.06 : I²C SDA&lt;br /&gt;
* P0.07 : I²C SCL&lt;br /&gt;
&lt;br /&gt;
==== I²C ====&lt;br /&gt;
&lt;br /&gt;
* Device address : 0x15&lt;br /&gt;
* Frequency : from 10Khz to 400Khz&lt;br /&gt;
&lt;br /&gt;
'''NOTE : ''' The controller go to sleep when no event is detected. In sleep mode, the controller does not communicate on the I²C bus (it appears disconnected). So, for the communication to work, you need to tap on the screen so that the chip wakes-up.&lt;br /&gt;
&lt;br /&gt;
==== Touch events ====&lt;br /&gt;
&lt;br /&gt;
Touch information is available from the 63 first registers of the controller. Remember: the device is in sleep mode when no touch event is detected. It means that you can read the register only when the touch controller detected an event. You can use the ''Interrupt'' pin to detect such event in the software. &lt;br /&gt;
&lt;br /&gt;
These 63 bytes contain up to 10 touch point (X, Y, event type, pressure,...) : &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Byte&lt;br /&gt;
! Bit7&lt;br /&gt;
! Bit6&lt;br /&gt;
! Bit5&lt;br /&gt;
! Bit4&lt;br /&gt;
! Bit3&lt;br /&gt;
! Bit2&lt;br /&gt;
! Bit1&lt;br /&gt;
! Bit0&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|?&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|GestureID : (Gesture code ,&lt;br /&gt;
&lt;br /&gt;
0x00: no gesture,&lt;br /&gt;
&lt;br /&gt;
0x01: Slide down,&lt;br /&gt;
&lt;br /&gt;
0x02: Slide up,&lt;br /&gt;
&lt;br /&gt;
0x03: Slide left,&lt;br /&gt;
&lt;br /&gt;
0x04: Slide right,&lt;br /&gt;
&lt;br /&gt;
0x05: Single click,&lt;br /&gt;
&lt;br /&gt;
0x0B: Double click,&lt;br /&gt;
&lt;br /&gt;
0x0C: Long press) &lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|? &lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|Number of touch points &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|Event (0 = Down, 1 = Up, 2 = Contact)&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|?&lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|X (MSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|X (LSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|?&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|Touch ID&lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|Y (MSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|Y (LSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|Pressure (?)&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|Miscellaneous (?)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bytes 3 to 8 are repeated 10 times (10*6 + 3 = 63 bytes).&lt;br /&gt;
&lt;br /&gt;
'''NOTES'''&lt;br /&gt;
&lt;br /&gt;
* The touch controller seems to report only 1 touch point&lt;br /&gt;
* Fields X, Y, Number of touch points and touch ID are updated. The others are always 0.&lt;br /&gt;
&lt;br /&gt;
==== Registers ====&lt;br /&gt;
&lt;br /&gt;
The reference driver specifies some registers and value, but there is no information about them: &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!Register&lt;br /&gt;
!Address&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_INT_CNT&lt;br /&gt;
|0x8F&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_FLOW_WORK_CNT&lt;br /&gt;
|0x91&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_WORKMODE &lt;br /&gt;
|0x00&lt;br /&gt;
|0 = WORK, 0x40 = FACTORY&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_CHIP_ID&lt;br /&gt;
|0xA3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_CHIP_ID2&lt;br /&gt;
|0x9F&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_POWER_MODE&lt;br /&gt;
|0xA5&lt;br /&gt;
|0x03 = SLEEP (reset the touchpanel using the reset pin before using this register : pin_low, delay 5ms, pin_high, delay 50ms then write 3 to register 0xA5)&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_FW_VER&lt;br /&gt;
|0xA6&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_VENDOR_ID&lt;br /&gt;
|0xA8&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_LCD_BUSY_NUM&lt;br /&gt;
|0xAB&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_FACE_DEC_MODE_EN&lt;br /&gt;
|0xB0&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_GLOVE_MODE_EN&lt;br /&gt;
|0xC0&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_COVER_MODE_EN&lt;br /&gt;
|0xC1&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_CHARGER_MODE_EN&lt;br /&gt;
|0x8B&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_GESTURE_EN&lt;br /&gt;
|0xD0&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_GESTURE_OUTPUT_ADDRESS&lt;br /&gt;
|0xD3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_ESD_SATURATE 0xED&lt;br /&gt;
|0xED&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''WARNING : ''' &amp;lt;del&amp;gt;Writing the SLEEP command (write 0x05 in HYN_REG_POWER_MODE) seems to freeze the controller (it returns only static values) until the battery is totally drained and the whole system reset. Analysis and debugging is more than welcome!&amp;lt;/del&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Datasheets and Schematics ==&lt;br /&gt;
&lt;br /&gt;
=== Schematics ===&lt;br /&gt;
* [http://files.pine64.org/doc/PineTime/PineTime%20Schematic-V1.0a-20191103.pdf PineTime Schematic ver1.0a]&lt;br /&gt;
* [http://files.pine64.org/doc/PineTime/PineTime%20Port%20Assignment%20rev1.0.pdf PineTime GPIO Port Assignment ver1.0]&lt;br /&gt;
&lt;br /&gt;
Note: The part number for the SPI FLASH in the schematic diagram is not correct, the PineTime features a larger external FLASH device, see below.&lt;br /&gt;
&lt;br /&gt;
=== Chip Datasheets ===&lt;br /&gt;
* NORDIC nRF52832 information:&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf nRF52832 Product Brief]&lt;br /&gt;
** [https://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.1.pdf nRF52832 Product Specification v1.1]&lt;br /&gt;
* ARMv7-M information:&lt;br /&gt;
** [https://static.docs.arm.com/ddi0403/eb/DDI0403E_B_armv7m_arm.pdf ARMv7-M Architecture Reference Manual]&lt;br /&gt;
&lt;br /&gt;
=== Component Datasheets ===&lt;br /&gt;
* PMU (Power Management Unit) information:&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/SGM40561.pdf SGMicro SGM40561 Single Cell Charger Datasheet]&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/SGMICRO-SGM2036.pdf SGMicro SGM2036 3.3V Low Power Low Dropout RF Linear Regulator Datasheet]&lt;br /&gt;
* SPI Flash information:&lt;br /&gt;
** [https://www.elnec.com/en/device/XTX/XT25F32B+%28QuadSPI%29+%5BSOP8-200%5D/ XTX XT25F32B 32Mb(4MB) SPI NOR Flash] (data sheets for this part are hard to find but it acts similar to other QuadSPI SPI NOR Flash such as [https://www.macronix.com/Lists/Datasheet/Attachments/7426/MX25L3233F,%203V,%2032Mb,%20v1.6.pdf Macronix 32Mb(4MB) SPI NOR Flash])&lt;br /&gt;
** IDs for XT25F32B are: manufacturer (0x0b), device (0x15), memory type (0x40), density (0x16)&lt;br /&gt;
* LCD Panel:&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/PineTime%20LCD%20Panel.jpg 1.3&amp;quot; 240x240 IPS LCD Panel Specification for PineTime]&lt;br /&gt;
** [https://wiki.pine64.org/images/5/54/ST7789V_v1.6.pdf 11.6&amp;quot; Sitronix LCD Driver/Controller Datasheet]&lt;br /&gt;
* Touchpad information:&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/PineTime%20Touch%20Panel.jpg Touchpad Specification for PineTimel]&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/CST816S数据手册V1.1.pdf 11.6&amp;quot; Hynitron CST816S Capacitive Touch Controller Datasheet in Chinese]&lt;br /&gt;
*** [https://wiki.pine64.org/images/5/51/CST816S%E6%95%B0%E6%8D%AE%E6%89%8B%E5%86%8CV1.1.en.pdf English Translation]&lt;br /&gt;
* Sensor:&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/BST-BMA421-FL000.pdf BOSCH BMA421 Triaxial VAcceleration Sensor Product Brief]&lt;br /&gt;
** [https://wiki.pine64.org/images/c/cc/Bst-bma400-ds000.pdf BOSCH BMA400 3-axes ultra-low power accelerometer datasheet]&lt;br /&gt;
** [http://files.pine64.org/doc/datasheet/pinetime/HRS3300%20Heart%20Rate%20Sensor.pdf TianYiHeXin HRS3300 PPG Heart Rate Sensor Data Sheet]&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Development&amp;diff=7514</id>
		<title>PineTime Development</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Development&amp;diff=7514"/>
		<updated>2020-10-10T17:37:34Z</updated>

		<summary type="html">&lt;p&gt;Caligari: /* Available firmware and projects */ sethitow/mbed-pinetime repository URL&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Reprogramming ==&lt;br /&gt;
&lt;br /&gt;
[[PineTime devkit wiring|Wire it up]] and then [[Reprogramming the PineTime| flash something]].&lt;br /&gt;
&lt;br /&gt;
== Available firmware and projects ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&lt;br /&gt;
! Project Homepage&lt;br /&gt;
! Project Source&lt;br /&gt;
! PineTime Implementations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! FreeRTOS&lt;br /&gt;
|https://www.freertos.org&lt;br /&gt;
| https://sourceforge.net/projects/freertos/&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[[InfiniTime]] ([https://github.com/JF002/Pinetime JF002/Pinetime])&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/kaythe/pinetime-os kaythe/pinetime-os]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Zephyr&lt;br /&gt;
| https://www.zephyrproject.org&lt;br /&gt;
| https://github.com/zephyrproject-rtos/zephyr&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/najnesnaj/pinetime-zephyr najnesnaj/pinetime-zephyr]&lt;br /&gt;
|- &lt;br /&gt;
|[https://github.com/SuperPrower/pinetime_zephyr_sample_fw SuperPrower/pinetime_zephyr_sample_fw]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/Dejvino/pinetime-hermes-firmware Dejvino/pinetime-hermes-firmware]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/endian-albin/pinetime-hypnos endian-albin/pinetime-hypnos]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! mynewt&lt;br /&gt;
| https://mynewt.apache.org/about/&lt;br /&gt;
| https://github.com/apache/mynewt-core&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/lupyuen/pinetime-rust-mynewt lupyuen/pinetime-rust-mynewt]&lt;br /&gt;
|-&lt;br /&gt;
|[https://gitlab.com/caspermeijn/klok caspermeijn/klok]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! MbedOS&lt;br /&gt;
| https://os.mbed.com&lt;br /&gt;
| https://github.com/ARMmbed/mbed-os&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/sethitow/mbed-pinetime sethitow/mbed-pinetime]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/geoffrey-vl/mbed-pinetime geoffrey.vl/mbed-pinetime]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! RIOT&lt;br /&gt;
| http://riot-os.org/&lt;br /&gt;
| https://github.com/RIOT-OS/RIOT/&lt;br /&gt;
| [https://github.com/bosmoment/PineTime-apps bosmoment/PineTime-apps]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! TinyGo&lt;br /&gt;
| https://tinygo.org&lt;br /&gt;
| https://github.com/tinygo-org/tinygo&lt;br /&gt;
| [https://github.com/aykevl/go-smartwatch aykevl/go-smartwatch]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! wasp-os (MicroPython)&lt;br /&gt;
| https://wasp-os.readthedocs.io/&lt;br /&gt;
| https://github.com/daniel-thompson/wasp-os&lt;br /&gt;
| [https://wasp-os.readthedocs.io/en/latest/install.html#pine64-pinetime-developer-edition PineTime install guide]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Rust + RTFM&lt;br /&gt;
| https://rtfm.rs/&lt;br /&gt;
| [https://github.com/rtfm-rs/cortex-m-rtfm rtfm-rs/cortex-m-rtfm]&lt;br /&gt;
| https://github.com/dbrgn/pinetime-rtfm/&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Bare Metal&lt;br /&gt;
| &lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|https://github.com/xriss/timecake&lt;br /&gt;
|-&lt;br /&gt;
|https://github.com/Arc13/Pyrus&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/xriss/timecake xriss/timecake]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/Arc13/Pyrus Arc13/Pyrus]&lt;br /&gt;
|}&lt;br /&gt;
|-&lt;br /&gt;
! AdaFruit bootloader&lt;br /&gt;
|&lt;br /&gt;
| https://github.com/adafruit/Adafruit_nRF52_Bootloader&lt;br /&gt;
| [https://github.com/daniel-thompson/wasp-bootloader daniel-thompson/wasp-bootloader]&lt;br /&gt;
|-&lt;br /&gt;
! Useful drivers&lt;br /&gt;
|&lt;br /&gt;
| https://github.com/sethitow/mbed-pinetime&lt;br /&gt;
| [https://github.com/sethitow/mbed-pinetime/tree/master/drivers https://github.com/sethitow/mbed-pinetime]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! UI concepts and drawings&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://gitlab.com/arteeh/pinetime-os arteeh/pinetime-os]&lt;br /&gt;
|-&lt;br /&gt;
! Linux companion app&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [https://gitlab.com/arteeh/pinetime-companion arteeh/pinetime-companion]&lt;br /&gt;
|-&lt;br /&gt;
! Android companion app&lt;br /&gt;
| https://gadgetbridge.org/&lt;br /&gt;
| https://codeberg.org/Freeyourgadget/Gadgetbridge&lt;br /&gt;
| [https://github.com/JF002/Pinetime InfiniTime] [https://codeberg.org/Freeyourgadget/Gadgetbridge/commit/9b8f4d329e49cafdfe0497ed38a715faa9f844c6 initial support added]&lt;br /&gt;
|-&lt;br /&gt;
! Arduino&lt;br /&gt;
| https://youtu.be/4aFDjymXjOw&lt;br /&gt;
| https://github.com/atc1441/ATCwatch&lt;br /&gt;
| https://github.com/atc1441/ATCwatch&lt;br /&gt;
|-&lt;br /&gt;
! OTA Update Flasher / DaFlasher&lt;br /&gt;
| https://youtu.be/gUVEz-pxhgg&lt;br /&gt;
| https://github.com/atc1441/DaFlasherFiles&lt;br /&gt;
| https://github.com/atc1441/DaFlasherFiles&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Manuals ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/JF002/Pinetime InfiniTime installation]&lt;br /&gt;
* [https://github.com/najnesnaj/pinetime-zephyr Zephyr installation] Beginner manual which explains how to install Zephyr (by najnesnaj).&lt;br /&gt;
* [https://wasp-os.readthedocs.io/en/latest/ Wasp-OS installation] Full manual with install instructions and an application writer's guide.&lt;br /&gt;
&lt;br /&gt;
== How to write battery friendly software? ==&lt;br /&gt;
&lt;br /&gt;
The key to save battery is to enable only what you need when you need it. nRF52832 has a lot of functionalities allowing you to draw as little current as possible. Here are some tips and tricks:&lt;br /&gt;
&lt;br /&gt;
* Disable / shutdown / put in sleep mode '''all devices around the MCU''' (display controller, touch controller, external memory,...). &lt;br /&gt;
* Disable all '''peripheral inside the MCU''' when you don't need them (SPI, TWI(I²C),...). The power management of the NRF52832 is very smart and will completely shut down (power off and disable the clock) the peripheral when the software disables it.&lt;br /&gt;
* Put the MCU to sleep as soon and as often as possible. If you are not using a RTOS, this is done by calling ''WFE'' (wait for event) instruction. Most of the time, RTOS implement this functionality. For example, FreeRTOS calls it the ''tickless mode'' : it puts the CPU in sleep mode when no task is planned for execution for more than a specified time, and wakes up as soon as an event is detected or when a task is ready to run.&lt;br /&gt;
* Do not use logging (JLink RTT, SWO, semihosting,...), it uses a lot of power.&lt;br /&gt;
* Ensure that the debug circuitry of the MCU is not enabled when you measuring the battery life. The debug peripheral is enabled as soon as you connect a debugger to the device, and '''is not automatically disabled''', even if you disconnect the debugger you will have to wait for the battery to go flat to disable to port. The software running in the NRF52832 cannot disable the debug peripheral. How to disable the debug circuitry:&lt;br /&gt;
  - using ''nrfjprog --reset''&lt;br /&gt;
  - using JLinkExe : issue the command ''writeDP 1 0''&lt;br /&gt;
&lt;br /&gt;
  or with OpenOCD&lt;br /&gt;
  - issue the command ''halt''&lt;br /&gt;
  - issue the command ''flash fillw 0x10001208 0xFFFFFF00 0x01''&lt;br /&gt;
  - issue the command ''reset''&lt;br /&gt;
&lt;br /&gt;
  you can check if the debug port is enabled using the following code&lt;br /&gt;
  DWT-&amp;gt;CYCCNT ? &amp;quot;NO&amp;quot;:&amp;quot;YES&amp;quot;&lt;br /&gt;
* Read [https://infocenter.nordicsemi.com/pdf/nRF52832_Rev_2_Errata_v1.1.pdf the errata sheet of the MCU] and apply workarounds if they apply to your software.&lt;br /&gt;
&lt;br /&gt;
== Wishlist ==&lt;br /&gt;
&lt;br /&gt;
In order to keep track of features and changes to the hardware people would like to see, check out this article: [[PineTime hardware wishlist]]&lt;br /&gt;
&lt;br /&gt;
== Compatibility with other projects ==&lt;br /&gt;
&lt;br /&gt;
Different firmware running using different bootloaders and Bluetooth stacks on the nRF52832 have different requirements on how they should be initialised and what should be placed where in the internal flash.&lt;br /&gt;
&lt;br /&gt;
To keep track of what, how and why things work like they do across the different projects, check out the [[PineTime SD MCUBoot|PineTime SoftDevice and MCUBoot compatibility]] article.&lt;br /&gt;
&lt;br /&gt;
== Compatibility with companions apps and Bluetooth communication ==&lt;br /&gt;
&lt;br /&gt;
There are a lot of different firmware running on the Pinetime that implement different BLE APIs (time synchronization, notifications, ...). Companion apps must be able to differentiate between different firmware and forks of the same firmware. See [[PineTime Bluetooth]].&lt;br /&gt;
&lt;br /&gt;
== PineTime equivalents and jailbreaking ==&lt;br /&gt;
&lt;br /&gt;
This page contains a list of PineTime-like smartwatches that might be &amp;quot;jailbreakable&amp;quot; or a good source for ideas for the PineTime: [[PineTime Equivalents]]&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_RTOS_Comparison&amp;diff=4289</id>
		<title>PineTime RTOS Comparison</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_RTOS_Comparison&amp;diff=4289"/>
		<updated>2019-12-22T13:33:03Z</updated>

		<summary type="html">&lt;p&gt;Caligari: More implementations&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&lt;br /&gt;
! Project Homepage&lt;br /&gt;
! Project Source&lt;br /&gt;
! Sponsor&lt;br /&gt;
! Language&lt;br /&gt;
! PineTime Implementations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! FreeRTOS&lt;br /&gt;
|https://www.freertos.org&lt;br /&gt;
| https://sourceforge.net/projects/freertos/&lt;br /&gt;
| [https://www.freertos.org/RTOS-contact-and-support.html Amazon Web Services]&lt;br /&gt;
| C&lt;br /&gt;
| [https://github.com/JF002/Pinetime JF002/Pinetime]&lt;br /&gt;
[https://github.com/kaythe/pinetime-os kaythe/pinetime-os]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Zephyr&lt;br /&gt;
| https://www.zephyrproject.org&lt;br /&gt;
| https://github.com/zephyrproject-rtos/zephyr&lt;br /&gt;
| Linux Foundation&lt;br /&gt;
| C/C++&lt;br /&gt;
| [https://github.com/najnesnaj/pinetime-zephyr najnesnaj/pinetime-zephyr]&lt;br /&gt;
[https://github.com/SuperPrower/pinetime_zephyr_sample_fw SuperPrower/pinetime_zephyr_sample_fw]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! mynewt&lt;br /&gt;
| https://mynewt.apache.org/about/&lt;br /&gt;
| https://github.com/apache/mynewt-core&lt;br /&gt;
| Apache Foundation&lt;br /&gt;
| C&lt;br /&gt;
| [https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/pinetime lupyuen/stm32bluepill-mynewt-sensor]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Tock&lt;br /&gt;
| https://www.tockos.org&lt;br /&gt;
| https://github.com/tock/tock&lt;br /&gt;
|&lt;br /&gt;
| Rust&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! MbedOS&lt;br /&gt;
| https://os.mbed.com&lt;br /&gt;
| https://github.com/ARMmbed/mbed-os&lt;br /&gt;
| ARM&lt;br /&gt;
| C/C++&lt;br /&gt;
| [https://github.com/sethitow/awesome-pinetime sethitow/mbed-pinetime]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! TinyGo&lt;br /&gt;
| https://tinygo.org&lt;br /&gt;
| https://github.com/tinygo-org/tinygo&lt;br /&gt;
| &lt;br /&gt;
| Go&lt;br /&gt;
| [https://github.com/aykevl/go-smartwatch aykevl/go-smartwatch]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_RTOS_Comparison&amp;diff=4287</id>
		<title>PineTime RTOS Comparison</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_RTOS_Comparison&amp;diff=4287"/>
		<updated>2019-12-21T21:42:55Z</updated>

		<summary type="html">&lt;p&gt;Caligari: Implementation links.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&lt;br /&gt;
! Project Homepage&lt;br /&gt;
! Project Source&lt;br /&gt;
! Sponsor&lt;br /&gt;
! Language&lt;br /&gt;
! PineTime Implementations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! FreeRTOS&lt;br /&gt;
|https://www.freertos.org&lt;br /&gt;
| https://sourceforge.net/projects/freertos/&lt;br /&gt;
| [https://www.freertos.org/RTOS-contact-and-support.html Amazon Web Services]&lt;br /&gt;
| C&lt;br /&gt;
| [https://github.com/JF002/Pinetime JF002/Pinetime]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Zephyr&lt;br /&gt;
| https://www.zephyrproject.org&lt;br /&gt;
| https://github.com/zephyrproject-rtos/zephyr&lt;br /&gt;
| Linux Foundation&lt;br /&gt;
| C&lt;br /&gt;
|  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! mynewt&lt;br /&gt;
| https://mynewt.apache.org/about/&lt;br /&gt;
| https://github.com/apache/mynewt-core&lt;br /&gt;
| Apache Foundation&lt;br /&gt;
| C&lt;br /&gt;
| [https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/pinetime lupyuen/stm32bluepill-mynewt-sensor]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Tock&lt;br /&gt;
| https://www.tockos.org&lt;br /&gt;
| https://github.com/tock/tock&lt;br /&gt;
|&lt;br /&gt;
| Rust&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! MbedOS&lt;br /&gt;
| https://os.mbed.com&lt;br /&gt;
| https://github.com/ARMmbed/mbed-os&lt;br /&gt;
| ARM&lt;br /&gt;
| C/C++&lt;br /&gt;
|  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! TinyGo&lt;br /&gt;
| https://tinygo.org&lt;br /&gt;
| https://github.com/tinygo-org/tinygo&lt;br /&gt;
| &lt;br /&gt;
| Go&lt;br /&gt;
| [https://github.com/aykevl/go-smartwatch aykevl/go-smartwatch]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Caligari</name></author>
	</entry>
</feed>