ESP8266: How to register partitions

Starting with v3.0, the ESP8266 NONOS SDK requires that partitions be registered in function void user_pre_init(void), like this:

#define SPI_FLASH_SIZE_MAP 2
void ICACHE_FLASH_ATTR user_pre_init(void)
{
        bool rc;
        static const partition_item_t part_table[] =
        {
                {SYSTEM_PARTITION_RF_CAL, 0xfb000, 0x1000},
                {SYSTEM_PARTITION_PHY_DATA, 0xfc000, 0x1000},
                {SYSTEM_PARTITION_SYSTEM_PARAMETER, 0xfd000, 0x3000},
        };
        rc = system_partition_table_regist(part_table,
                        sizeof(part_table)/sizeof(part_table[0]),
                        SPI_FLASH_SIZE_MAP);
        if (rc)
                goto done;
        os_printf("Error while registering partitions\r\n");
        while (1) ;
done:
}

The code above initialises and registers a table of partitions, each having a type, a start address, and a size. Despite the documentation in ESP8266 Non-OS SDK API Reference and README, partitions can still be difficult to understand. This post aims to provide some clarity.

As an aside:

Some images are mandatory for ESP8266 to work, as
described in ESP8266 SDK Getting Started Guide (see screenshot below).

They are obtained in bin of the SDK code repository and can be written to the flash as per the instructions. The addresses here are for the ESP-01 but can be found in the documentation for other models.

  • blank.bin at address 0xFB000
  • esp_init_data_default.bin at 0xFC000
  • blank.bin at 0xFD000

The bootloader and user program are written normally at 0x0000 and 0x1000 respectively. It is not necessary to rewrite the mandatory images every time, as long as they have not been overwritten. If in doubt, erase all the flash and write them again.

Back to the partitions:

The choice of partitions’ addresses is driven by the flash size on the target ESP8266 controller. Referring to the flash map given below and the size of each partition, it is easy to calculate the start addresses by starting with the last partition and working backwards.

Consider the 1 MiB flash of the ESP-01, with a size of 0x100000 bytes (1024 KiB).

The SYSTEM_PARTITION_SYSTEM_PARAMETER partition at the last position must be 12 KiB large. Therefore, its start address must be at 0x100000 – 0x3000 (0x3000 being hex for 12288), giving a value of 0xFD000.

The second to last partition, SYSTEM_PARTITION_PHY_DATA, must be 4 KiB large. Using the same math, 0xFD000 – 0x1000 (0x1000 being hex for 4096) the start address is determined to be 0xFC000

The first partition, SYSTEM_PARTITION_RF_CAL, with a size of 4 KiB, is then found to start at 0xFC000 – 0x1000, which is 0xFB000.

These calculated start addresses correspond to the values in the code above—and the addresses where the mandatory images are written.

The last argument passed to system_partition_table_regist is the “map”. In the example above, the macro SPI_FLASH_SIZE_MAP is defined with a value of 2. Where does it come from?

The enum flash_size_map in include/user_interface.h lists all possible values; in this case, the one corresponding to the 1 MiB flash of an ESP-01 (or 8M bits map) is 2.

Join the Conversation

4 Comments

  1. Hi mate, good post,

    Without this SDK, is it possible that you can write a partition table on an ESP8266 ? I know for a fact that on ESP32 yes, and without this SDK you mention.

    1. Thanks. Yes, you can download the images and use `esptool.py` to write the partitions. But usually the images are included in the SDK, so you have to download the SDK even if you won’t write the partitions programmatically.

      1. How are you doing?

        I’m still not sure how to do it, if I manage more or less the write_flash and read_flash with esptool.py but.

        Do you have a post on how to do it ? and the files needed for them ?

        I have several esp8266 on hand, I know as you say, in case something goes wrong, a –erase-all can be done.

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.