This commit is contained in:
Michal Moskal 2016-12-02 14:53:43 -08:00
commit b9752da8ac
4 changed files with 118 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
tmp
*.sw?

37
README.md Normal file
View file

@ -0,0 +1,37 @@
# USB Flashing Format (UF2)
UF2 (USB Flashing Format) is a name of a file format, that is particularly
suitable for flashing devices over MSC (Mass Storage Class most commonly used
by various pendrives) The file consists of 512 byte blocks, each of which is
self-contained and independent of others.
Each 512 byte block consist of (see `uf2.h` for details):
* magic numbers at the beginning and at the end
* address where the data should be flashed
* size of data
* data (up to 476 bytes; for SAMD it's 256 bytes so it's easy to flash in one go)
Thus, it's really easy for the microcontroller to recognize a block of
a UF2 file is written and immediately write it to flash.
In `uf2conv.c` you can find a small converter from `.bin` to `.uf2`.
## Board identification
There is also `BOARD_ID`, which is meant to be machine-readable and specific
to a given version of board hardware. The programming environment might use
this to suggest packages to be imported (i.e., a package for a particular
external flash chip, SD card etc.).
These configuration values can be read from `INFO_UF2.TXT` file.
Presence of this file can be tested to see if the board supports `UF2` flashing,
while contest, particularly `Board-ID` field, can be used for feature detection.
The current flash contents of the board is exposed as `CURRENT.UF2` file.
This file includes the bootloader address space. The last word of bootloader
space points to the string holding the `INFO_UF2.TXT` file, so it can be parsed
by a programming environment to determine which board does the `.UF2` file comes from.
## License
MIT

34
uf2.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef UF2FORMAT_H
#define UF2FORMAT_H 1
#include <stdint.h>
#include <stdbool.h>
// All entries are little endian.
#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n"
#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected
#define UF2_MAGIC_END 0x0AB16F30UL // Ditto
// If set, the block is "comment" and should not be flashed to the device
#define UF2_FLAG_NOFLASH 0x00000001
typedef struct {
// 32 byte header
uint32_t magicStart0;
uint32_t magicStart1;
uint32_t flags;
uint32_t targetAddr;
uint32_t payloadSize;
uint32_t blockNo;
uint32_t numBlocks;
uint32_t reserved;
// raw data;
uint8_t data[476];
// store magic also at the end to limit damage from partial block reads
uint32_t magicEnd;
} UF2_Block;
#endif

45
utils/uf2conv.c Normal file
View file

@ -0,0 +1,45 @@
#include <stdio.h>
#include <string.h>
#include "uf2format.h"
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "USAGE: %s file.bin [file.uf2]\n", argv[0]);
return 1;
}
FILE *f = fopen(argv[1], "rb");
if (!f) {
fprintf(stderr, "No such file: %s\n", argv[1]);
return 1;
}
fseek(f, 0L, SEEK_END);
uint32_t sz = ftell(f);
fseek(f, 0L, SEEK_SET);
const char *outname = argc > 2 ? argv[2] : "flash.uf2";
FILE *fout = fopen(outname, "wb");
UF2_Block bl;
memset(&bl, 0, sizeof(bl));
bl.magicStart0 = UF2_MAGIC_START0;
bl.magicStart1 = UF2_MAGIC_START1;
bl.magicEnd = UF2_MAGIC_END;
bl.targetAddr = APP_START_ADDRESS;
bl.numBlocks = (sz + 255) / 256;
bl.payloadSize = 256;
int numbl = 0;
while (fread(bl.data, 1, bl.payloadSize, f)) {
bl.blockNo = numbl++;
fwrite(&bl, 1, sizeof(bl), fout);
bl.targetAddr += bl.payloadSize;
// clear for next iteration, in case we get a short read
memset(bl.data, 0, sizeof(bl.data));
}
fclose(fout);
fclose(f);
printf("Wrote %d blocks to %s\n", numbl, outname);
return 0;
}