UF2 is a file format, developed by Microsoft for PXT (also known as Microsoft MakeCode), that is particularly suitable for flashing microcontrollers over MSC (Mass Storage Class; aka removable flash drive).
The list of family IDs is stored in a separate JSON file:
https://github.com/microsoft/uf2/blob/master/utils/uf2families.json
This JSON file is regularly updated. The family_id enum should be kept in
sync with it. For simplicity and consistency, it's strongly recommended to
auto-generate this enum from uf2families.json directly. This was last done
using the following commands:
$ curl -fsSLO https://github.com/microsoft/uf2/raw/90e9741f217f5a40c98ba74d663e408041037578/utils/uf2families.json
$ jq -r '
.[]
| " \(.id | ascii_downcase):\n"
+ " id: \(.short_name | ascii_downcase | gsub("-"; "_"))\n"
+ " doc: \(.description | tojson)"
' uf2families.json
Test files, picked to cover as many different shapes as possible:
num_blocks.family_id::rp2xxx_absolute block that picotool prepends (see the
is_rp2350_e10_block value instance in the block type).file_size rather
than family_id.family_id::rp2040) is moved to the end of the second file, which was
intended for family_id::rp2xxx_absolute (see
https://github.com/raspberrypi/pico-examples/blob/c81c855ffdedc825975a40ba357723a71358ddf0/universal/CMakeLists.txt#L159-L169).flags.is_file_container flag set (for
example
https://github.com/microsoft/pxt-microsoft-boot-sequence/releases/download/v0.0.4/arcade-p0.uf2
is a pure file container for
file_name == "Projects/microsoft-boot-sequence.elf"). Generated by
MakeCode, the only known producer of file container UF2s.This page hosts a formal specification of UF2 (USB Flashing Format) using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
<?php
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
/**
* UF2 is a file format, developed by Microsoft for PXT (also known as
* Microsoft MakeCode), that is particularly suitable for flashing
* microcontrollers over MSC (Mass Storage Class; aka removable flash drive).
*
* The list of family IDs is stored in a separate JSON file:
*
* <https://github.com/microsoft/uf2/blob/master/utils/uf2families.json>
*
* This JSON file is regularly updated. The `family_id` enum should be kept in
* sync with it. For simplicity and consistency, it's strongly recommended to
* auto-generate this enum from `uf2families.json` directly. This was last done
* using the following commands:
*
* ```bash
* $ curl -fsSLO https://github.com/microsoft/uf2/raw/90e9741f217f5a40c98ba74d663e408041037578/utils/uf2families.json
* $ jq -r '
* .[]
* | " \(.id | ascii_downcase):\n"
* + " id: \(.short_name | ascii_downcase | gsub("-"; "_"))\n"
* + " doc: \(.description | tojson)"
* ' uf2families.json
* ```
*
* Test files, picked to cover as many different shapes as possible:
*
* * <https://micropython.org/download/RPI_PICO/> - a typical case: all blocks
* have the same family ID and `num_blocks`.
* * <https://micropython.org/download/RPI_PICO2/> - these .uf2 files are
* actually two UF2 files concatenated. The first UF2 file is the standalone
* `family_id::rp2xxx_absolute` block that `picotool` prepends (see the
* `is_rp2350_e10_block` value instance in the `block` type).
* * <https://circuitpython.org/downloads> - the builds for SAMD boards (for
* example
* [Feather M0 Express](https://circuitpython.org/board/feather_m0_express/))
* set no flags at all, so the field at offset 28 is read as `file_size` rather
* than `family_id`.
* * <https://github.com/raspberrypi/pico-sdk-prebuilts/releases> -
* [Universal UF2](https://github.com/raspberrypi/pico-examples/blob/c81c855ffdedc825975a40ba357723a71358ddf0/universal/README.md#universal-binary-vs-universal-uf2)
* files, which are again two UF2 files concatenated. What's interesting about
* these is that the last block of the first file (with the family ID
* `family_id::rp2040`) is moved to the end of the second file, which was
* intended for `family_id::rp2xxx_absolute` (see
* <https://github.com/raspberrypi/pico-examples/blob/c81c855ffdedc825975a40ba357723a71358ddf0/universal/CMakeLists.txt#L159-L169>).
* * <https://github.com/microsoft/pxt-microsoft-boot-sequence/releases> - some
* files contain blocks with the `flags.is_file_container` flag set (for
* example
* <https://github.com/microsoft/pxt-microsoft-boot-sequence/releases/download/v0.0.4/arcade-p0.uf2>
* is a pure file container for
* `file_name == "Projects/microsoft-boot-sequence.elf"`). Generated by
* MakeCode, the only known producer of file container UF2s.
* * <https://github.com/umi-eng/uftwo/tree/35bccf75b4f81c43f088696a8c4a9912f1f4104e/uftwo/tests> -
* synthetic test files for features that real firmware doesn't seem to use
* (e.g. MD5 checksums).
*/
namespace {
class Uf2 extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, ?\Kaitai\Struct\Struct $_parent = null, ?\Uf2 $_root = null) {
parent::__construct($_io, $_parent, $_root === null ? $this : $_root);
$this->_read();
}
private function _read() {
$this->_m_firstBlock = new \Uf2\Block($this->_io, $this, $this->_root);
$this->_m_blocks = [];
$n = $this->firstBlock()->numBlocks() - 1;
for ($i = 0; $i < $n; $i++) {
$this->_m_blocks[] = new \Uf2\Block($this->_io, $this, $this->_root);
}
}
protected $_m_firstBlock;
protected $_m_blocks;
public function firstBlock() { return $this->_m_firstBlock; }
public function blocks() { return $this->_m_blocks; }
}
}
namespace Uf2 {
class Block extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, ?\Uf2 $_parent = null, ?\Uf2 $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_magic = $this->_io->readBytes(4);
if (!($this->_m_magic == "\x55\x46\x32\x0A")) {
throw new \Kaitai\Struct\Error\ValidationNotEqualError("\x55\x46\x32\x0A", $this->_m_magic, $this->_io, "/types/block/seq/0");
}
$this->_m_secondMagic = $this->_io->readBytes(4);
if (!($this->_m_secondMagic == "\x57\x51\x5D\x9E")) {
throw new \Kaitai\Struct\Error\ValidationNotEqualError("\x57\x51\x5D\x9E", $this->_m_secondMagic, $this->_io, "/types/block/seq/1");
}
$this->_m_flags = new \Uf2\Flags($this->_io, $this, $this->_root);
$this->_m_targetAddress = $this->_io->readU4le();
$_ = $this->_m_targetAddress;
if (!(\Kaitai\Struct\Stream::mod($_, 4) == 0)) {
throw new \Kaitai\Struct\Error\ValidationExprError($this->_m_targetAddress, $this->_io, "/types/block/seq/3");
}
$this->_m_lenPayload = $this->_io->readU4le();
$_ = $this->_m_lenPayload;
if (!(\Kaitai\Struct\Stream::mod($_, 4) == 0)) {
throw new \Kaitai\Struct\Error\ValidationExprError($this->_m_lenPayload, $this->_io, "/types/block/seq/4");
}
$this->_m_blockNumber = $this->_io->readU4le();
$this->_m_numBlocksRaw = $this->_io->readU4le();
if (!($this->_m_numBlocksRaw >= $this->blockNumber() + 1)) {
throw new \Kaitai\Struct\Error\ValidationLessThanError($this->blockNumber() + 1, $this->_m_numBlocksRaw, $this->_io, "/types/block/seq/6");
}
if (!($this->flags()->hasFamilyId())) {
$this->_m_fileSize = $this->_io->readU4le();
}
if ($this->flags()->hasFamilyId()) {
$this->_m_familyId = $this->_io->readU4le();
}
$this->_m__raw_data = $this->_io->readBytes(476);
$_io__raw_data = new \Kaitai\Struct\Stream($this->_m__raw_data);
$this->_m_data = new \Uf2\BlockData($_io__raw_data, $this, $this->_root);
$this->_m_finalMagic = $this->_io->readBytes(4);
if (!($this->_m_finalMagic == "\x30\x6F\xB1\x0A")) {
throw new \Kaitai\Struct\Error\ValidationNotEqualError("\x30\x6F\xB1\x0A", $this->_m_finalMagic, $this->_io, "/types/block/seq/10");
}
}
protected $_m_isRp2350E10Block;
/**
* Determines whether this is a block that `picotool` prepends to RP2350
* flash images as a workaround for erratum RP2350-E10 (i.e. a hardware
* bug in the A2 version of the RP2350 boot ROM).
*
* Such a block is always written on its own, but its `num_blocks_raw` is
* set to 2. If we trusted this value, we would attempt to read one block
* too many (which would most likely fail). Therefore, we must correct it
* to 1 before using it.
*
* The conditions for detecting this block come from the
* [`check_abs_block()`](https://github.com/raspberrypi/picotool/blob/6f6458d792b93685a11423b244a585eaa99eafcf/elf2uf2/elf2uf2.cpp#L147)
* function in `picotool`. However, there are some differences:
*
* 1. In Kaitai Struct, we cannot easily check whether all 256 payload
* bytes are set to `0xef`, so we only check the first and last bytes.
* 2. There are .uf2 files in the wild where `flags.has_extension_tags`
* is true, but there are actually no extension tags (the first and
* only tag has a size of 0, which is just a terminator), so our
* condition allows for this case. You can download an example of such
* a .uf2 file here:
* <https://github.com/neednotapply/DC32-cfw/releases/tag/1.69.13.37>
*
* It's worth noting that we cannot require the presence of the
* `extension_tag_type::rp2_ignore_block`
* (`UF2_EXTENSION_RP2_IGNORE_BLOCK`) tag because the UF2 files generated
* by `picotool` prior to
* <https://github.com/raspberrypi/picotool/commit/78c9bd121b09399823b67ee7ea89003ca0d3315f>
* don't have it. Therefore, we check whether this tag is present only if
* `flags.has_extension_tags` is set.
*
* Test .uf2 files with this special block can be downloaded from
* <https://micropython.org/download/RPI_PICO2/>. Note that all the .uf2
* files there are actually two UF2 (sub)files concatenated, and this
* Kaitai Struct implementation parses only one at a time (so in order to
* parse both, you need something like the helper spec `uf2_files.ksy`
* from
* <https://github.com/kaitai-io/kaitai_struct_formats/pull/542#discussion_r3906386820>).
* v1.24.x releases predate the `extension_tag_type::rp2_ignore_block`
* tag, while releases v1.25.0 and later include it.
*/
public function isRp2350E10Block() {
if ($this->_m_isRp2350E10Block !== null)
return $this->_m_isRp2350E10Block;
$this->_m_isRp2350E10Block = (( (($this->flags()->value() == 8192) || ($this->flags()->value() == 40960)) ) && ($this->familyId() == \Uf2\FamilyId::RP2XXX_ABSOLUTE) && ($this->numBlocksRaw() == 2) && ($this->blockNumber() == 0) && ($this->lenPayload() == 256) && (ord($this->data()->payload()[0]) == 239) && (ord($this->data()->payload()[strlen($this->data()->payload()) - 1]) == 239) && ( ((!($this->flags()->hasExtensionTags())) || ($this->data()->extensionTags()[0]->lenTag() == 0) || ( (($this->data()->extensionTags()[0]->lenTag() == 4) && ($this->data()->extensionTags()[0]->tagType() == \Uf2\ExtensionTagType::RP2_IGNORE_BLOCK)) )) )) ;
return $this->_m_isRp2350E10Block;
}
protected $_m_numBlocks;
public function numBlocks() {
if ($this->_m_numBlocks !== null)
return $this->_m_numBlocks;
$this->_m_numBlocks = ($this->isRp2350E10Block() ? 1 : $this->numBlocksRaw());
return $this->_m_numBlocks;
}
protected $_m_magic;
protected $_m_secondMagic;
protected $_m_flags;
protected $_m_targetAddress;
protected $_m_lenPayload;
protected $_m_blockNumber;
protected $_m_numBlocksRaw;
protected $_m_fileSize;
protected $_m_familyId;
protected $_m_data;
protected $_m_finalMagic;
protected $_m__raw_data;
public function magic() { return $this->_m_magic; }
public function secondMagic() { return $this->_m_secondMagic; }
public function flags() { return $this->_m_flags; }
/**
* Address in flash where `data.payload` should be written, or an offset
* in the file specified by `data.file_name` if `flags.is_file_container`
* is set.
*
* The [official
* spec](https://github.com/microsoft/uf2/blob/90e9741f217f5a40c98ba74d663e408041037578/README.md#payload-sizes)
* says:
*
* > In any event, payload size and target address should always be
* > 4-byte aligned.
*/
public function targetAddress() { return $this->_m_targetAddress; }
/**
* The [official
* spec](https://github.com/microsoft/uf2/blob/90e9741f217f5a40c98ba74d663e408041037578/README.md#payload-sizes)
* says:
*
* > In any event, payload size and target address should always be
* > 4-byte aligned.
*/
public function lenPayload() { return $this->_m_lenPayload; }
public function blockNumber() { return $this->_m_blockNumber; }
/**
* Number of blocks that make up the UF2 file to which this block
* belongs. Every block of a file has the same value. It is at least 1
* and every `block_number` in the file must be less than this value
* (which is validated by this Kaitai Struct implementation).
*/
public function numBlocksRaw() { return $this->_m_numBlocksRaw; }
/**
* Size of the file this block belongs to, but only if
* `flags.is_file_container` is true. Otherwise, the official spec allows
* this field to be set to anything - though in practice, it's always
* zero.
*/
public function fileSize() { return $this->_m_fileSize; }
public function familyId() { return $this->_m_familyId; }
public function data() { return $this->_m_data; }
public function finalMagic() { return $this->_m_finalMagic; }
public function _raw_data() { return $this->_m__raw_data; }
}
}
namespace Uf2 {
class BlockData extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, ?\Uf2\Block $_parent = null, ?\Uf2 $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_payload = $this->_io->readBytes($this->_parent()->lenPayload());
if ($this->_parent()->flags()->isFileContainer()) {
$this->_m_fileName = \Kaitai\Struct\Stream::bytesToStr($this->_io->readBytesTerm(0, false, true, true), "UTF-8");
}
if ($this->_parent()->flags()->hasExtensionTags()) {
$this->_m_extensionTags = [];
$i = 0;
do {
$_ = new \Uf2\ExtensionTag($this->_io, $this, $this->_root);
$this->_m_extensionTags[] = $_;
$i++;
} while (!($_->lenTag() == 0));
}
}
protected $_m_md5Checksum;
/**
* Describes a region that doesn't need to be flashed again if the
* checksum matches.
*
* The [official
* spec](https://github.com/microsoft/uf2/blob/90e9741f217f5a40c98ba74d663e408041037578/README.md#md5-checksum)
* says that "This is currently only used on ESP32", but no real-world
* firmware sample has been found (at least none of the .uf2 files from
* <https://github.com/adafruit/tinyuf2/releases>,
* [MicroPython](https://micropython.org/download/) or
* [CircuitPython](https://circuitpython.org/downloads) contain it). It
* was found only in some synthetic test files, e.g.
* <https://github.com/umi-eng/uftwo/blob/35bccf75b4f81c43f088696a8c4a9912f1f4104e/uftwo/tests/checksum_256.uf2>.
*/
public function md5Checksum() {
if ($this->_m_md5Checksum !== null)
return $this->_m_md5Checksum;
if ($this->_parent()->flags()->hasMd5Checksum()) {
$_pos = $this->_io->pos();
$this->_io->seek($this->_io()->size() - 24);
$this->_m_md5Checksum = new \Uf2\Md5Checksum($this->_io, $this, $this->_root);
$this->_io->seek($_pos);
}
return $this->_m_md5Checksum;
}
protected $_m_payload;
protected $_m_fileName;
protected $_m_extensionTags;
/**
* The bytes to be written to `_parent.target_address`, which is either
* an address in flash, or an offset in the file specified by `file_name`
* if `_parent.flags.is_file_container` is set.
*/
public function payload() { return $this->_m_payload; }
public function fileName() { return $this->_m_fileName; }
public function extensionTags() { return $this->_m_extensionTags; }
}
}
namespace Uf2 {
class ExtensionTag extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, ?\Uf2\BlockData $_parent = null, ?\Uf2 $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_lenTag = $this->_io->readU1();
$_ = $this->_m_lenTag;
if (!( (($_ == 0) || ($_ >= $this->minLenTag())) )) {
throw new \Kaitai\Struct\Error\ValidationExprError($this->_m_lenTag, $this->_io, "/types/extension_tag/seq/0");
}
$this->_m_tagType = $this->_io->readBitsIntLe(24);
$this->_io->alignToByte();
if ($this->lenTag() != 0) {
$this->_m_value = $this->_io->readBytes($this->lenValue());
}
$this->_m_padding = $this->_io->readBytes(\Kaitai\Struct\Stream::mod(-($this->lenTag()), 4));
}
protected $_m_lenValue;
public function lenValue() {
if ($this->_m_lenValue !== null)
return $this->_m_lenValue;
$this->_m_lenValue = ($this->lenTag() >= $this->minLenTag() ? $this->lenTag() - $this->minLenTag() : 0);
return $this->_m_lenValue;
}
protected $_m_minLenTag;
public function minLenTag() {
if ($this->_m_minLenTag !== null)
return $this->_m_minLenTag;
$this->_m_minLenTag = 1 + 3;
return $this->_m_minLenTag;
}
protected $_m_lenTag;
protected $_m_tagType;
protected $_m_value;
protected $_m_padding;
/**
* Total size of the tag in bytes, including this byte and `tag_type`, so
* at least 4. The exception is the last tag which terminates the list -
* it specifies a total size of 0.
*/
public function lenTag() { return $this->_m_lenTag; }
public function tagType() { return $this->_m_tagType; }
public function value() { return $this->_m_value; }
/**
* Tags are 4-byte aligned, so a tag whose size is not a multiple
* of 4 is followed by padding.
*/
public function padding() { return $this->_m_padding; }
}
}
namespace Uf2 {
class Flags extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, ?\Uf2\Block $_parent = null, ?\Uf2 $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_value = $this->_io->readU4le();
$_ = $this->_m_value;
if (!( ((($_ & ~61441) == 0) && (!( (($this->isFileContainer()) && ($this->hasExtensionTags())) ))) )) {
throw new \Kaitai\Struct\Error\ValidationExprError($this->_m_value, $this->_io, "/types/flags/seq/0");
}
}
protected $_m_hasExtensionTags;
/**
* Indicates whether extension tags are present after the payload.
*/
public function hasExtensionTags() {
if ($this->_m_hasExtensionTags !== null)
return $this->_m_hasExtensionTags;
$this->_m_hasExtensionTags = ($this->value() & 32768) != 0;
return $this->_m_hasExtensionTags;
}
protected $_m_hasFamilyId;
/**
* The field at offset 28 in the block is `family_id` instead of
* `file_size`.
*/
public function hasFamilyId() {
if ($this->_m_hasFamilyId !== null)
return $this->_m_hasFamilyId;
$this->_m_hasFamilyId = ($this->value() & 8192) != 0;
return $this->_m_hasFamilyId;
}
protected $_m_hasMd5Checksum;
/**
* Indicates whether `md5_checksum` is present at the end of `data`.
*/
public function hasMd5Checksum() {
if ($this->_m_hasMd5Checksum !== null)
return $this->_m_hasMd5Checksum;
$this->_m_hasMd5Checksum = ($this->value() & 16384) != 0;
return $this->_m_hasMd5Checksum;
}
protected $_m_isFileContainer;
/**
* When set, the UF2 format is used as a container for regular files
* (akin to a TAR file, or ZIP archive without compression).
*
* `target_address` is the offset in the file where the payload is to be
* written, and `file_size` is the size of that file. The name of the
* destination file is stored in `data.file_name`.
*/
public function isFileContainer() {
if ($this->_m_isFileContainer !== null)
return $this->_m_isFileContainer;
$this->_m_isFileContainer = ($this->value() & 4096) != 0;
return $this->_m_isFileContainer;
}
protected $_m_notMainFlash;
/**
* Indicates that this block should be skipped when writing the device
* flash. It can be used to store data that does not fit on the device,
* typically embedded source code or debug info.
*/
public function notMainFlash() {
if ($this->_m_notMainFlash !== null)
return $this->_m_notMainFlash;
$this->_m_notMainFlash = ($this->value() & 1) != 0;
return $this->_m_notMainFlash;
}
protected $_m_value;
/**
* Only the five bits that we cover in value instances below are defined,
* and no other bit may be set. The [official
* spec](https://github.com/microsoft/uf2/blob/90e9741f217f5a40c98ba74d663e408041037578/README.md#flags)
* says "Currently, there are five flags defined". If any other flags are
* added in the future, this .ksy spec will need to be updated.
*
* The `is_file_container` and `has_extension_tags` flags disagree about
* what follows the payload in `data` (a file name or a list of extension
* tags), so this Kaitai Struct implementation treats them as mutually
* exclusive and will reject a block that sets both. The official spec
* does not specify how this should be handled, but logically there's a
* conflict, so we've decided to strictly treat it as an error.
*/
public function value() { return $this->_m_value; }
}
}
namespace Uf2 {
class Md5Checksum extends \Kaitai\Struct\Struct {
public function __construct(\Kaitai\Struct\Stream $_io, ?\Uf2\BlockData $_parent = null, ?\Uf2 $_root = null) {
parent::__construct($_io, $_parent, $_root);
$this->_read();
}
private function _read() {
$this->_m_startAddress = $this->_io->readU4le();
$this->_m_lenRegion = $this->_io->readU4le();
$this->_m_md5 = $this->_io->readBytes(16);
}
protected $_m_startAddress;
protected $_m_lenRegion;
protected $_m_md5;
public function startAddress() { return $this->_m_startAddress; }
public function lenRegion() { return $this->_m_lenRegion; }
public function md5() { return $this->_m_md5; }
}
}
namespace Uf2 {
class ExtensionTagType {
/**
* According to the official spec, this type should be used in the last tag
* with `len_tag == 0`, which terminates the list of extension tags.
*/
const END = 0;
/**
* Page size of the target device, as a 32-bit unsigned number
*/
const PAGE_SIZE = 780791;
/**
* Description of the device for which the firmware file is destined
* (UTF-8)
*/
const DESCRIPTION = 6622621;
/**
* The block is to be ignored. This value doesn't come from the official
* spec, but from the Raspberry Pi Pico SDK. It's written with no value, so
* the whole tag is the 4 bytes `04 e3 57 99`. See the
* `is_rp2350_e10_block` value instance in the `block` type.
*/
const RP2_IGNORE_BLOCK = 10049507;
/**
* Version of the firmware file, as a UTF-8 semver string
*/
const VERSION = 10471356;
/**
* SHA-2 checksum of firmware (can be of various sizes)
*/
const SHA2_CHECKSUM = 11824560;
/**
* Device type identifier, a refinement of `family_id` meant to identify a
* kind of device rather than only an MCU. 32-bit or 64-bit number. Can be
* a hash of the `extension_tag_type::description` tag.
*/
const DEVICE_TYPE_ID = 13149993;
private const _VALUES = [0 => true, 780791 => true, 6622621 => true, 10049507 => true, 10471356 => true, 11824560 => true, 13149993 => true];
public static function isDefined(int $v): bool {
return isset(self::_VALUES[$v]);
}
}
}
namespace Uf2 {
class FamilyId {
/**
* ST STM32L4xx
*/
const STM32L4 = 16738585;
/**
* ST STM32L5xx
*/
const STM32L5 = 69471199;
/**
* ST STM32F411xC
*/
const STM32F411XC = 114362747;
/**
* M0SENSE BL702
*/
const M0SENSE = 299792458;
/**
* Microchip (Atmel) ATmega32
*/
const ATMEGA32 = 374814231;
/**
* Microchip (Atmel) SAML21
*/
const SAML21 = 407992330;
/**
* Nordic NRF52
*/
const NRF52 = 458716255;
/**
* ESP32
*/
const ESP32 = 475996592;
/**
* ST STM32L1xx
*/
const STM32L1 = 505365293;
/**
* ST STM32L0xx
*/
const STM32L0 = 539900561;
/**
* ST STM32WLxx
*/
const STM32WL = 558239728;
/**
* Realtek AmebaZ RTL8710B
*/
const RTL8710B = 585160444;
/**
* NXP LPC55xx
*/
const LPC55 = 716994540;
/**
* ESP32-C2
*/
const ESP32C2 = 730387100;
/**
* ST STM32F411xE
*/
const STM32F411XE = 767756741;
/**
* ST STM32G0xx
*/
const STM32G0 = 806311475;
/**
* ESP32-S31
*/
const ESP32S31 = 822212545;
/**
* GD32F350
*/
const GD32F350 = 835856582;
/**
* ESP32-H2
*/
const ESP32H2 = 858203894;
/**
* Realtek AmebaD RTL8720D
*/
const RTL8720D = 863621090;
/**
* ESP32-P4
*/
const ESP32P4 = 1026592404;
/**
* Sipeed MaixPlay-U4(BL618)
*/
const MAIXPLAY_U4 = 1265126769;
/**
* ST STM32G4xx
*/
const STM32G4 = 1282483210;
/**
* ST STM32H5xx
*/
const STM32H5 = 1318001757;
/**
* LISTENAI CSK300x/400x
*/
const CSK4 = 1332399698;
/**
* NXP i.MX RT10XX
*/
const MIMXRT10XX = 1337120189;
/**
* Xradiotech 809
*/
const XR809 = 1374225320;
/**
* ST STM32F7xx
*/
const STM32F7 = 1404571392;
/**
* ESP32-C6
*/
const ESP32C6 = 1410195298;
/**
* Microchip (Atmel) SAMD51
*/
const SAMD51 = 1427194976;
/**
* ST STM32F4xx
*/
const STM32F4 = 1467308631;
/**
* Cypress FX2
*/
const FX2 = 1511523995;
/**
* ST STM32F2xx
*/
const STM32F2 = 1561987630;
/**
* ST STM32F103
*/
const STM32F1 = 1591873650;
/**
* Nordic NRF52833
*/
const NRF52833 = 1646171002;
/**
* ST STM32F0xx
*/
const STM32F0 = 1685595318;
/**
* Beken 7231U/7231T
*/
const BK7231U = 1733968048;
/**
* Microchip (Atmel) SAMD21
*/
const SAMD21 = 1760373640;
/**
* WCH CH32V2xx and CH32V3xx
*/
const CH32V = 1771791084;
/**
* Beken 7251/7252
*/
const BK7251 = 1786956866;
/**
* ST STM32F3xx
*/
const STM32F3 = 1803837832;
/**
* ST STM32F407
*/
const STM32F407 = 1829315322;
/**
* ST STM32H7xx
*/
const STM32H7 = 1840668802;
/**
* LISTENAI CSK60xx
*/
const CSK6 = 1853049000;
/**
* Nordic NRF52832xxAB
*/
const NRF52832XXAB = 1869948536;
/**
* ST STM32WBxx
*/
const STM32WB = 1892771411;
/**
* Nordic NRF52832xxAA
*/
const NRF52832XXAA = 1920081230;
/**
* Analog Devices MAX32690
*/
const MAX32690 = 1947226634;
/**
* ESP32-C61
*/
const ESP32C61 = 2010665156;
/**
* Beken 7231N
*/
const BK7231N = 2067722800;
/**
* Renesas RA4M1
*/
const RA4M1 = 2078840685;
/**
* Quansheng UV-K5 V3 amateur radio based on Puya Semiconductor PY32F071
*/
const PY32F071_UVK5_V3 = 2105173743;
/**
* ESP8266
*/
const ESP8266 = 2125160941;
/**
* NXP KL32L2x
*/
const KL32L2 = 2139350931;
/**
* Nordic NRF52820_xxAA
*/
const NRF52820 = 2181929567;
/**
* ST STM32F407VG
*/
const STM32F407VG = 2410701054;
/**
* Analog Devices MAX78002
*/
const MAX78002 = 2446589208;
/**
* Renesas RZ/A1LU (R7S7210xx)
*/
const RZA1LU = 2501329455;
/**
* GigaDevice GD32VF103
*/
const GD32VF103 = 2599435827;
/**
* ESP32-H4
*/
const ESP32H4 = 2651564682;
/**
* Realtek Ameba1 RTL8710A
*/
const RTL8710A = 2684343619;
/**
* ArteryTek AT32F415
*/
const AT32F415 = 2697558926;
/**
* Nordic NRF52840
*/
const NRF52840 = 2913282112;
/**
* ESP32-H21
*/
const ESP32H21 = 3067936943;
/**
* ESP32-S2
*/
const ESP32S2 = 3218951918;
/**
* ESP32-S3
*/
const ESP32S3 = 3296614247;
/**
* ESP32-C3
*/
const ESP32C3 = 3559628908;
/**
* Analog Devices MAX32650/1/2
*/
const MAX32650 = 3594487346;
/**
* Boufallo 602
*/
const BL602 = 3725750455;
/**
* Realtek AmebaZ2 RTL8720C
*/
const RTL8720C = 3767498084;
/**
* Raspberry Pi RP2040
*/
const RP2040 = 3834380118;
/**
* Raspberry Pi Microcontrollers: Absolute (unpartitioned) download
*/
const RP2XXX_ABSOLUTE = 3834380119;
/**
* Raspberry Pi Microcontrollers: Data partition download
*/
const RP2XXX_DATA = 3834380120;
/**
* Raspberry Pi RP2350, Secure Arm image
*/
const RP2350_ARM_S = 3834380121;
/**
* Raspberry Pi RP2350, RISC-V image
*/
const RP2350_RISCV = 3834380122;
/**
* Raspberry Pi RP2350, Non-secure Arm image
*/
const RP2350_ARM_NS = 3834380123;
/**
* Analog Devices MAX32665/6
*/
const MAX32666 = 4039314801;
/**
* ESP32-C5
*/
const ESP32C5 = 4145808195;
private const _VALUES = [16738585 => true, 69471199 => true, 114362747 => true, 299792458 => true, 374814231 => true, 407992330 => true, 458716255 => true, 475996592 => true, 505365293 => true, 539900561 => true, 558239728 => true, 585160444 => true, 716994540 => true, 730387100 => true, 767756741 => true, 806311475 => true, 822212545 => true, 835856582 => true, 858203894 => true, 863621090 => true, 1026592404 => true, 1265126769 => true, 1282483210 => true, 1318001757 => true, 1332399698 => true, 1337120189 => true, 1374225320 => true, 1404571392 => true, 1410195298 => true, 1427194976 => true, 1467308631 => true, 1511523995 => true, 1561987630 => true, 1591873650 => true, 1646171002 => true, 1685595318 => true, 1733968048 => true, 1760373640 => true, 1771791084 => true, 1786956866 => true, 1803837832 => true, 1829315322 => true, 1840668802 => true, 1853049000 => true, 1869948536 => true, 1892771411 => true, 1920081230 => true, 1947226634 => true, 2010665156 => true, 2067722800 => true, 2078840685 => true, 2105173743 => true, 2125160941 => true, 2139350931 => true, 2181929567 => true, 2410701054 => true, 2446589208 => true, 2501329455 => true, 2599435827 => true, 2651564682 => true, 2684343619 => true, 2697558926 => true, 2913282112 => true, 3067936943 => true, 3218951918 => true, 3296614247 => true, 3559628908 => true, 3594487346 => true, 3725750455 => true, 3767498084 => true, 3834380118 => true, 3834380119 => true, 3834380120 => true, 3834380121 => true, 3834380122 => true, 3834380123 => true, 4039314801 => true, 4145808195 => true];
public static function isDefined(int $v): bool {
return isset(self::_VALUES[$v]);
}
}
}