]> granicus.if.org Git - esp-idf/commitdiff
spi_flash: improve documentation
authorIvan Grokhotkov <ivan@espressif.com>
Tue, 25 Oct 2016 03:43:00 +0000 (11:43 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Thu, 27 Oct 2016 09:58:42 +0000 (17:58 +0800)
components/esp32/include/esp_flash_data_types.h
components/spi_flash/README.rst
components/spi_flash/include/esp_spi_flash.h

index b16ee59f575243a4581ef7f6b827d90416ba6075..4bf886c842bdd52422ca77f3d82d7a2348c98f37 100644 (file)
@@ -24,7 +24,7 @@ extern "C"
 #define ESP_PARTITION_TABLE_ADDR 0x4000
 #define ESP_PARTITION_MAGIC 0x50AA
 
-/*spi mode,saved in third byte in flash */
+/* SPI flash mode, used in esp_image_header_t */
 typedef enum {
     ESP_IMAGE_SPI_MODE_QIO,
     ESP_IMAGE_SPI_MODE_QOUT,
@@ -34,7 +34,7 @@ typedef enum {
     ESP_IMAGE_SPI_MODE_SLOW_READ
 } esp_image_spi_mode_t;
 
-/* spi speed*/
+/* SPI flash clock frequency */
 enum {
     ESP_IMAGE_SPI_SPEED_40M,
     ESP_IMAGE_SPI_SPEED_26M,
@@ -42,7 +42,7 @@ enum {
     ESP_IMAGE_SPI_SPEED_80M = 0xF
 } esp_image_spi_freq_t;
 
-/*supported flash sizes*/
+/* Supported SPI flash sizes */
 typedef enum {
     ESP_IMAGE_FLASH_SIZE_1MB = 0,
     ESP_IMAGE_FLASH_SIZE_2MB,
@@ -52,22 +52,23 @@ typedef enum {
     ESP_IMAGE_FLASH_SIZE_MAX
 } esp_image_flash_size_t;
 
+/* Main header of binary image */
 typedef struct {
-    char magic;
-    char blocks;
-    char spi_mode;      /* flag of flash read mode in unpackage and usage in future */
-    char spi_speed: 4;  /* low bit */
-    char spi_size: 4;
-    unsigned int entry_addr;
+    uint8_t magic;
+    uint8_t blocks;
+    uint8_t spi_mode;      /* flash read mode (esp_image_spi_mode_t as uint8_t) */
+    uint8_t spi_speed: 4;  /* flash frequency (esp_image_spi_freq_t as uint8_t) */
+    uint8_t spi_size: 4;   /* flash chip size (esp_image_flash_size_t as uint8_t) */
+    uint32_t entry_addr;
     uint8_t encrypt_flag;    /* encrypt flag */
     uint8_t secure_boot_flag; /* secure boot flag */
-    char extra_header[14]; /* ESP32 additional header, unused by second bootloader */
+    uint8_t extra_header[14]; /* ESP32 additional header, unused by second bootloader */
 }  esp_image_header_t;
 
-/* each header of flash bin block */
+/* Header of binary image segment */
 typedef struct {
-    unsigned int load_addr;
-    unsigned int data_len;
+    uint32_t load_addr;
+    uint32_t data_len;
 } esp_image_section_header_t;
 
 
@@ -85,13 +86,16 @@ typedef struct {
     uint32_t size;
 } esp_partition_pos_t;
 
+/* Structure which describes the layout of partition table entry.
+ * See docs/partition_tables.rst for more information about individual fields.
+ */
 typedef struct {
        uint16_t magic;
-       uint8_t  type;        /* partition Type */
-    uint8_t  subtype;     /* part_subtype */
+       uint8_t  type;
+    uint8_t  subtype;
     esp_partition_pos_t pos;
-       uint8_t  label[16];    /* label for the partition */
-    uint8_t  reserved[4];     /* reserved */
+       uint8_t  label[16];
+    uint8_t  reserved[4];
 } esp_partition_info_t;
 
 
index 22f98cf02d014434f9dd5af1edc01a596f6cd3d9..b479c3b0e9b8f1fa76a84e673d3227cedea6a46a 100644 (file)
@@ -1,5 +1,128 @@
-Driver for SPI flash read/write/erase operations
-================================================
+SPI flash related APIs
+======================
+
+Overview
+--------
+Spi_flash component contains APIs related to reading, writing, erasing,
+memory mapping data in the external SPI flash. It also has higher-level
+APIs which work with partition table and partitions.
+
+Note that all the functionality is limited to the "main" flash chip,
+i.e. the flash chip from which program runs. For ``spi_flash_*`` functions, 
+this is software limitation. Underlying ROM functions which work with SPI flash 
+do not have provisions for working with flash chips attached to SPI peripherals
+other than SPI0.
+
+SPI flash access APIs
+---------------------
+
+This is the set of APIs for working with data in flash:
+
+- ``spi_flash_read`` used to read data from flash to RAM
+- ``spi_flash_write`` used to write data from RAM to flash
+- ``spi_flash_erase_sector`` used to erase individual sectors of flash
+- ``spi_flash_erase_range`` used to erase range of addresses in flash
+- ``spi_flash_get_chip_size`` returns flash chip size, in bytes, as configured in menuconfig
+
+There are some data alignment limitations which need to be considered when using
+spi_flash_read/spi_flash_write functions:
+
+- buffer in RAM must be 4-byte aligned
+- size must be 4-byte aligned
+- address in flash must be 4-byte aligned
+
+These alignment limitations are purely software, and should be removed in future
+versions.
+
+It is assumed that correct SPI flash chip size is set at compile time using
+menuconfig. While run-time detection of SPI flash chip size is possible, it is
+not implemented yet. Applications which need this (e.g. to provide one firmware
+binary for different flash sizes) can do flash chip size detection and set
+the correct flash chip size in ``chip_size`` member of ``g_rom_flashchip``
+structure. This size is used by ``spi_flash_*`` functions for bounds checking.
+
+SPI flash APIs disable instruction and data caches while reading/writing/erasing.
+See implementation notes below on details how this happens. For application
+this means that at some periods of time, code can not be run from flash,
+and constant data can not be fetched from flash by the CPU. This is not an
+issue for normal code which runs in a task, because SPI flash APIs prevent
+other tasks from running while caches are disabled. This is an issue for
+interrupt handlers, which can still be called while flash operation is in
+progress. If the interrupt handler is not placed into IRAM, there is a
+possibility that interrupt will happen at the time when caches are disabled,
+which will cause an illegal instruction exception.
+
+To prevent this, make sure that all ISR code, and all functions called from ISR
+code are placed into IRAM, or are located in ROM. Most useful C library
+functions are located in ROM, so they can be called from ISR.
+
+To place a function into IRAM, use ``IRAM_ATTR`` attribute, e.g.::
+
+       #include "esp_attr.h"
+       
+       void IRAM_ATTR gpio_isr_handler(void* arg)
+       {
+               // ...          
+       }
+       
+When flash encryption is enabled, ``spi_flash_read`` will read data as it is
+stored in flash (without decryption), and ``spi_flash_write`` will write data
+in plain text. In other words, ``spi_flash_read/write`` APIs don't have
+provisions to deal with encrypted data.
+
+
+Partition table APIs
+--------------------
+
+ESP-IDF uses partition table to maintain information about various regions of
+SPI flash memory (bootloader, various application binaries, data, filesystems).
+More information about partition tables can be found in docs/partition_tables.rst.
+
+This component provides APIs to enumerate partitions found in the partition table
+and perform operations on them. These functions are declared in ``esp_partition.h``:
+
+- ``esp_partition_find`` used to search partition table for entries with specific type, returns an opaque iterator
+- ``esp_partition_get`` returns a structure describing the partition, for the given iterator
+- ``esp_partition_next`` advances iterator to the next partition found
+- ``esp_partition_iterator_release`` releases iterator returned by ``esp_partition_find``
+- ``esp_partition_find_first`` is a convenience function which returns structure describing the first partition found by esp_partition_find
+- ``esp_partition_read``, ``esp_partition_write``, ``esp_partition_erase_range`` are equivalent to ``spi_flash_read``, ``spi_flash_write``, ``spi_flash_erase_range``, but operate within partition boundaries
+
+Most application code should use ``esp_partition_*`` APIs instead of lower level
+``spi_flash_*`` APIs. Partition APIs do bounds checking and calculate correct
+offsets in flash based on data stored in partition table.
+
+Memory mapping APIs
+-------------------
+
+ESP32 features memory hardware which allows regions of flash memory to be mapped
+into instruction and data address spaces. This mapping works only for read operations,
+it is not possible to modify contents of flash memory by writing to mapped memory
+region. Mapping happens in 64KB pages. Memory mapping hardware can map up to
+4 megabytes of flash into data address space, and up to 16 megabytes of flash into
+instruction address space. See the technical reference manual for more details
+about memory mapping hardware.
+
+Note that some number of 64KB pages is used to map the application
+itself into memory, so the actual number of available 64KB pages may be less.
+Reading data from flash using a memory mapped region is the only way to decrypt
+contents of flash when flash encryption is enabled. Decryption is performed at
+hardware level.
+
+Memory mapping APIs are declared in ``esp_spi_flash.h`` and ``esp_partition.h``:
+
+- ``spi_flash_mmap`` maps a region of physical flash addresses into instruction space or data space of the CPU
+- ``spi_flash_munmap`` unmaps previously mapped region
+- ``esp_partition_mmap`` maps part of a partition into the instruction space or data space of the CPU
+
+Differences between ``spi_flash_mmap`` and ``esp_partition_mmap`` are as follows:
+
+- ``spi_flash_mmap`` must be given a 64KB aligned physical address
+- ``esp_partition_mmap`` may be given an arbitrary offset within the partition, it will adjust returned pointer to mapped memory as necessary
+
+Note that because memory mapping happens in 64KB blocks, it may be possible to
+read data outside of the partition provided to ``esp_partition_mmap``. 
 
 Implementation notes
 --------------------
@@ -19,8 +142,10 @@ signals that cache is disabled by setting s_flash_op_can_start flag.
 Then the task on CPU A disables cache as well, and proceeds to execute flash
 operation.
 
-While flash operation is running, interrupts can still run on CPU B.
-We assume that all interrupt code is placed into RAM.
+While flash operation is running, interrupts can still run on CPUs A and B.
+We assume that all interrupt code is placed into RAM. Once interrupt allocation
+API is added, we should add a flag to request interrupt to be disabled for
+the duration of flash operations.
 
 Once flash operation is complete, function on CPU A sets another flag,
 s_flash_op_complete, to let the task on CPU B know that it can re-enable
index 2aa92d9a5d798482f6b4bd23d0fcff89a270f5d8..16b50a718922b45569e0c70a4dfa5020dae9aa3c 100644 (file)
@@ -35,6 +35,8 @@ extern "C" {
  *
  *  This function must be called exactly once, before any other 
  *  spi_flash_* functions are called.
+ *  Currently this function is called from startup code. There is
+ *  no need to call it from application code.
  *
  */
 void spi_flash_init();