]> granicus.if.org Git - esp-idf/commitdiff
spi_flash: implement partition API, drop trivial wrappers
authorIvan Grokhotkov <ivan@espressif.com>
Fri, 21 Oct 2016 10:44:57 +0000 (18:44 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Thu, 27 Oct 2016 09:58:42 +0000 (17:58 +0800)
This implements esp_partition_read, esp_partition_write, esp_partition_erase_range, esp_partition_mmap.
Also removed getters which didn't add much sugar after all.

components/spi_flash/include/esp_partition.h
components/spi_flash/include/esp_spi_flash.h
components/spi_flash/partition.c

index 6bdba149f11052c1ba2063d12bc18563e543f82a..89e523f9a774d1db2477f1372c1ba83fda02ad90 100644 (file)
@@ -17,7 +17,9 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <stddef.h>
 #include "esp_err.h"
+#include "esp_spi_flash.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -129,58 +131,26 @@ const esp_partition_t* esp_partition_get(esp_partition_iterator_t iterator);
 esp_partition_iterator_t esp_partition_next(esp_partition_iterator_t iterator);
 
 /**
- * @brief Get partition type
- *
- * @note This is a helper function built around esp_partition_get.
- *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
- *
- * @return esp_partition_type_t value for partition pointed to by the iterator.
- */
-esp_partition_type_t esp_partition_type(esp_partition_iterator_t iterator);
-
-/**
- * @brief Get partition size
- *
- * @note This is a helper function built around esp_partition_get.
- *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
- *
- * @return partition size, in bytes
- */
-uint32_t esp_partition_size(esp_partition_iterator_t iterator);
-
-/**
- * @brief Get partition address
- *
- * @note This is a helper function built around esp_partition_get.
- *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
- *
- * @return flash address of partition start
- */
-uint32_t esp_partition_address(esp_partition_iterator_t iterator);
-
-/**
- * @brief Get partition label
+ * @brief Release partition iterator
  *
- * @note This is a helper function built around esp_partition_get.
+ * Any pointers obtained using esp_partition_label function will be invalid
+ * after this call.
  *
  * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
  *
- * @return pointer to a zero-terminated string with partition label.
- *         The pointer is valid for the lifetime of the application.
  */
-const char* esp_partition_label(esp_partition_iterator_t iterator);
+void esp_partition_iterator_release(esp_partition_iterator_t iterator);
 
 /**
  * @brief Read data from the partition
  *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
+ * @param dst Pointer to the buffer where data should be stored.
+ *            Pointer must be non-NULL and buffer must be at least 'size' bytes long.
  * @param src_offset Address of the data to be read, relative to the
  *                   beginning of the partition.
- * @param dst Pointer to the buffer where data should be stored.
- *            Must be non-NULL and at least 'size' bytes long.
  * @param size Size of data to be read, in bytes.
  *
  * @return ESP_OK, if data was read successfully;
@@ -188,17 +158,22 @@ const char* esp_partition_label(esp_partition_iterator_t iterator);
  *         ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition;
  *         or one of error codes from lower-level flash driver.
  */
-esp_err_t esp_partition_read(esp_partition_iterator_t iterator,
-                             uint32_t src_offset, uint8_t* dst, uint32_t size);
+esp_err_t esp_partition_read(const esp_partition_t* partition,
+                             size_t src_offset, uint8_t* dst, size_t size);
 
 /**
  * @brief Write data to the partition
  *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
- * @param src Pointer to the source buffer.  Must be non-NULL and
- *              at least 'size' bytes long.
+ * Before writing data to flash, corresponding region of flash needs to be erased.
+ * This can be done using esp_partition_erase_range function.
+ *
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
  * @param dst_offset Address where the data should be written, relative to the
  *                   beginning of the partition.
+ * @param src Pointer to the source buffer.  Pointer must be non-NULL and
+ *            buffer must be at least 'size' bytes long.
  * @param size Size of data to be written, in bytes.
  *
  * @note Prior to writing to flash memory, make sure it has been erased with
@@ -209,13 +184,15 @@ esp_err_t esp_partition_read(esp_partition_iterator_t iterator,
  *         ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
  *         or one of error codes from lower-level flash driver.
  */
-esp_err_t esp_partition_write(esp_partition_iterator_t iterator,
-                             const uint8_t* src, uint32_t dst_offset, uint32_t size);
+esp_err_t esp_partition_write(const esp_partition_t* partition,
+                             size_t dst_offset, const uint8_t* src, size_t size);
 
 /**
  * @brief Erase part of the partition
  *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
  * @param start_addr Address where erase operation should start. Must be aligned
  *                   to 4 kilobytes.
  * @param size Size of the range which should be erased, in bytes.
@@ -226,35 +203,37 @@ esp_err_t esp_partition_write(esp_partition_iterator_t iterator,
  *         ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition;
  *         or one of error codes from lower-level flash driver.
  */
-esp_err_t esp_partition_erase_range(esp_partition_iterator_t iterator,
+esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
                                     uint32_t start_addr, uint32_t size);
 
 /**
  * @brief Configure MMU to map partition into data memory
  *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
+ * Unlike spi_flash_mmap function, which requires a 64kB aligned base address,
+ * this function doesn't impose such a requirement.
+ * If offset results in a flash address which is not aligned to 64kB boundary,
+ * address will be rounded to the lower 64kB boundary, so that mapped region
+ * includes requested range.
+ * Pointer returned via out_ptr argument will be adjusted to point to the
+ * requested offset (not necessarily to the beginning of mmap-ed region).
  *
- * @param offset Offset from the beginning of partition where mapping should start.
- *               Must be aligned to 64k.
+ * To release mapped memory, pass handle returned via out_handle argument to
+ * spi_flash_munmap function.
  *
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
+ * @param offset Offset from the beginning of partition where mapping should start.
  * @param size Size of the area to be mapped.
+ * @param memory  Memory space where the region should be mapped
+ * @param out_ptr  Output, pointer to the mapped memory region
+ * @param out_handle  Output, handle which should be used for spi_flash_munmap call
  *
- * @return pointer to mapped memory, if successful
- *         NULL, if memory can not be mapped for any reason
+ * @return ESP_OK, if successful
  */
-void* esp_partition_mmap(esp_partition_iterator_t iterator, uint32_t offset, uint32_t size);
-
-
-/**
- * @brief Release partition iterator
- *
- * Any pointers obtained using esp_partition_label function will be invalid
- * after this call.
- *
- * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
- *
- */
-void esp_partition_iterator_release(esp_partition_iterator_t iterator);
+esp_err_t esp_partition_mmap(const esp_partition_t* partition, uint32_t offset, uint32_t size,
+                             spi_flash_mmap_memory_t memory,
+                             const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
 
 
 #ifdef __cplusplus
index ab66a42041a32c0066fdf500dc0ac571d696bf17..2aa92d9a5d798482f6b4bd23d0fcff89a270f5d8 100644 (file)
@@ -16,6 +16,7 @@
 #define ESP_SPI_FLASH_H
 
 #include <stdint.h>
+#include <stddef.h>
 #include "esp_err.h"
 #include "sdkconfig.h"
 
index 381a1624b5bfc760a11c0c1259c31d137e50d5bb..d138f09b5f0a2934082f26f68ba70fb5d9e7f4d4 100644 (file)
@@ -135,38 +135,6 @@ const esp_partition_t* esp_partition_find_first(esp_partition_type_t type, const
     return res;
 }
 
-void esp_partition_iterator_release(esp_partition_iterator_t iterator)
-{
-    // iterator == NULL is okay
-    free(iterator);
-}
-
-const esp_partition_t* esp_partition_get(esp_partition_iterator_t iterator)
-{
-    assert(iterator != NULL);
-    return iterator->info;
-}
-
-esp_partition_type_t esp_partition_type(esp_partition_iterator_t iterator)
-{
-    return esp_partition_get(iterator)->type;
-}
-
-uint32_t esp_partition_size(esp_partition_iterator_t iterator)
-{
-    return esp_partition_get(iterator)->size;
-}
-
-uint32_t esp_partition_address(esp_partition_iterator_t iterator)
-{
-    return esp_partition_get(iterator)->address;
-}
-
-const char* esp_partition_label(esp_partition_iterator_t iterator)
-{
-    return esp_partition_get(iterator)->label;
-}
-
 static esp_partition_iterator_opaque_t* iterator_create(esp_partition_type_t type, const char* label)
 {
     esp_partition_iterator_opaque_t* it =
@@ -219,3 +187,92 @@ static esp_err_t load_partitions()
     spi_flash_munmap(handle);
     return ESP_OK;
 }
+
+void esp_partition_iterator_release(esp_partition_iterator_t iterator)
+{
+    // iterator == NULL is okay
+    free(iterator);
+}
+
+const esp_partition_t* esp_partition_get(esp_partition_iterator_t iterator)
+{
+    assert(iterator != NULL);
+    return iterator->info;
+}
+
+esp_err_t esp_partition_read(const esp_partition_t* partition,
+        size_t src_offset, uint8_t* dst, size_t size)
+{
+    assert(partition != NULL);
+    if (src_offset > partition->size) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (src_offset + size > partition->size) {
+        return ESP_ERR_INVALID_SIZE;
+    }
+    return spi_flash_read(partition->address + src_offset, dst, size);
+}
+
+esp_err_t esp_partition_write(const esp_partition_t* partition,
+                             size_t dst_offset, const uint8_t* src, size_t size)
+{
+    assert(partition != NULL);
+    if (dst_offset > partition->size) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (dst_offset + size > partition->size) {
+        return ESP_ERR_INVALID_SIZE;
+    }
+    return spi_flash_write(partition->address + dst_offset, src, size);
+}
+
+esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
+                                    size_t start_addr, size_t size)
+{
+    assert(partition != NULL);
+    if (start_addr > partition->size) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (start_addr + size > partition->size) {
+        return ESP_ERR_INVALID_SIZE;
+    }
+    if (size % SPI_FLASH_SEC_SIZE != 0) {
+        return ESP_ERR_INVALID_SIZE;
+    }
+    if (start_addr % SPI_FLASH_SEC_SIZE != 0) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    return spi_flash_erase_range(partition->address + start_addr, size);
+
+}
+
+/*
+ * Note: current implementation ignores the possibility of multiple regions in the same partition being
+ * mapped. Reference counting and address space re-use is delegated to spi_flash_mmap.
+ *
+ * If this becomes a performance issue (i.e. if we need to map multiple regions within the partition),
+ * we can add esp_partition_mmapv which will accept an array of offsets and sizes, and return array of
+ * mmaped pointers, and a single handle for all these regions.
+ */
+esp_err_t esp_partition_mmap(const esp_partition_t* partition, uint32_t offset, uint32_t size,
+                             spi_flash_mmap_memory_t memory,
+                             const void** out_ptr, spi_flash_mmap_handle_t* out_handle)
+{
+    assert(partition != NULL);
+    if (offset > partition->size) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (offset + size > partition->size) {
+        return ESP_ERR_INVALID_SIZE;
+    }
+    size_t phys_addr = partition->address + offset;
+    // offset within 64kB block
+    size_t region_offset = phys_addr & 0xffff;
+    size_t mmap_addr = phys_addr & 0xffff0000;
+    esp_err_t rc = spi_flash_mmap(mmap_addr, size, memory, out_ptr, out_handle);
+    // adjust returned pointer to point to the correct offset
+    if (rc == ESP_OK) {
+        *out_ptr = (void*) (((ptrdiff_t) *out_ptr) + region_offset);
+    }
+    return rc;
+}