diff --git a/README.md b/README.md index 451de84..396a5ce 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ UF2 is a file format, that is particularly suitable for flashing devices over MSC (Mass Storage Class; aka removable flash drive). The file consists of 512 byte blocks, each of which is self-contained and independent of others. -Each 512 byte block consist of (see below for details): +Each 512 byte block consists of (see below for details): * magic numbers at the beginning and at the end * address where the data should be flashed * up 476 bytes of data @@ -54,19 +54,22 @@ The magic number at the end is meant to mitigate partial block writes. Second and final magic numbers were randomly selected, except for the last byte of final magic number, which was forced to be `'\n'` (`0xA`). Together with the -first magic number being `"UF2\n"` this makes it easy to identify UF2 files in +first magic number being `"UF2\n"` this makes it easy to identify UF2 blocks in a text editor. The header was padded to 32 bytes, as hex editors commonly use 16 or 32 bytes -as line length. This way, the data is aligned to line start. +as line length. This way, the data payload is aligned to line start. 32 bit integers are used for all fields so that large flash sizes can be supported in future, as well as for simplicity. Little endian is used, as most -of microcontroller are little endian. +of microcontroller are little endian. 8 bit microcontrollers can choose to just +use the first 16 bits of various header fields. The total number of blocks in the file and the sequential block number make it easy for the bootloader to detect that all blocks have been transferred. It requires one bit of memory per block (eg., on SAMD21G18A it's 128 bytes). +Alternatively, the bootloader might ignore that and just implement a reset +after say 1 second break in incoming UF2 blocks. ### Payload sizes @@ -82,12 +85,13 @@ microcontroller. In any event, payload size and target address should be always 4-byte aligned. -Note that payload size of `256` is always correct. +Note that payload size of `256` is always correct, and makes it easy to convert +between flash addresses and UF2 file offsets. For example, on Atmel's SAMD21 chips the page size is `256` bytes, and this also the payload size used. If the page size was `128` bytes, one could use payload of `128*3`. Nordic nRF51 has page size of `1024` bytes, and thus -any payload sizes are allowed. +any payload sizes should be allowed. ### Embedding sources @@ -102,19 +106,21 @@ If the bootloader can expose `CURRENT.UF2` file (see below) and there is enough flash available, than the second option is more desirable, as it allows sharing programs directly from the board. +See https://www.pxt.io/source-embedding for more info. + ### Robustness The file format is designed specifically to deal with the following problems: -* operating system (OS) writing blocks of files not in order the blocks occur in file +* operating system (OS) writing blocks not in order the blocks occur in a file * OS writing some blocks multiple times -* OS writing data that is not blocks -* OS writing first/last half of a block, possibly for metadata detection or search indexing +* OS writing data that is not UF2 blocks +* OS writing first/final part of a block, possibly for metadata detection or search indexing The only file system assumption we make is that blocks of file are aligned with blocks on the hard drive. It's likely true of many file systems besides FAT. -We also assume that USB MSC device reports its block size to be a multiple of 512 +We also assume that USB MSC device reports its block size to be a multiple of `512` bytes. In the wild these devices always almost report exactly `512`, and some operating systems do not support other values. diff --git a/utils/uf2conv.py b/utils/uf2conv.py index ecd1c54..3828284 100755 --- a/utils/uf2conv.py +++ b/utils/uf2conv.py @@ -29,7 +29,8 @@ def convertFromUF2(buf): block = buf[ptr:ptr + 512] hd = struct.unpack("