blob: 79d9e71e52b342628d3575660d048f200c3155d1 [file] [log] [blame]
flash
-----
The flash driver subsystem is a work in progress which aims at
supporting common external SPI/I2C flash/eeprom memory chips. This is
equivalent to what Linux calls ``MTD`` for
``Memory Technology Devices``.
At the moment the only ``flash`` device that is already supported is the
AT45DBxxx SPI flash family with the ``at45db`` driver.
The flash driver aims for full compatibility with the ``hal_flash`` API,
which means initialization and usage can be performed by any ``fs`` that
supports the ``hal_flash`` interface.
Initialization
^^^^^^^^^^^^^^
To be compatible with the standard ``hal_flash`` interface, the
``at45db`` driver embeds a ``struct hal_flash`` to its own
``struct at45db_dev``. The whole ``at45db_dev`` struct is shown below.
.. code:: c
struct at45db_dev {
struct hal_flash hal;
struct hal_spi_settings *settings;
int spi_num;
void *spi_cfg; /** Low-level MCU SPI config */
int ss_pin;
uint32_t baudrate;
uint16_t page_size; /** Page size to be used, valid: 512 and 528 */
uint8_t disable_auto_erase; /** Reads and writes auto-erase by default */
};
To ease with initialization a helper function ``at45db_default_config``
was added. It returns an already initialized ``struct at45db_dev``
leaving the user with just having to provide the SPI related config.
To initialize the device, pass the ``at45db_dev`` struct to
``at45db_init``.
.. code:: c
int at45db_init(const struct hal_flash *dev);
For low-level access to the device the following functions are provided:
.. code:: c
int at45db_read(const struct hal_flash *dev, uint32_t addr, void *buf,
uint32_t len);
int at45db_write(const struct hal_flash *dev, uint32_t addr, const void *buf,
uint32_t len);
int at45db_erase_sector(const struct hal_flash *dev, uint32_t sector_address);
int at45db_sector_info(const struct hal_flash *dev, int idx, uint32_t *address,
uint32_t *sz);
Also, ``nffs`` is able to run on the device due to the fact that
standard ``hal_flash`` interface compatibility is provided. Due to
current limitations of ``nffs``, it can only run on ``at45db`` if the
internal flash of the MCU is not being used.
Dependencies
^^^^^^^^^^^^
To include the ``at45db`` driver on a project, just include it as a
dependency in your pkg.yml:
::
pkg.deps:
- "@apache-mynewt-core/hw/drivers/flash/at45db"
Header file
^^^^^^^^^^^
The ``at45db`` SPI flash follows the standard ``hal_flash`` interface
but requires that a special struct
.. code:: c
#include <at45db/at45db.h>
Example
^^^^^^^
This following examples assume that the ``at45db`` is being used on a
STM32F4 MCU.
.. code:: c
static const int SPI_SS_PIN = MCU_GPIO_PORTA(4);
static const int SPI_SCK_PIN = MCU_GPIO_PORTA(5);
static const int SPI_MISO_PIN = MCU_GPIO_PORTA(6);
static const int SPI_MOSI_PIN = MCU_GPIO_PORTA(7);
struct stm32f4_hal_spi_cfg spi_cfg = {
.ss_pin = SPI_SS_PIN,
.sck_pin = SPI_SCK_PIN,
.miso_pin = SPI_MISO_PIN,
.mosi_pin = SPI_MOSI_PIN,
.irq_prio = 2
};
struct at45db_dev *my_at45db_dev = NULL;
my_at45db_dev = at45db_default_config();
my_at45db_dev->spi_num = 0;
my_at45db_dev->spi_cfg = &spi_cfg;
my_at45db_dev->ss_pin = spi_cfg.ss_pin;
rc = at45db_init((struct hal_flash *) my_at45db_dev);
if (rc) {
/* XXX: error handling */
}
The enable ``nffs`` to run on the ``at45db``, the ``flash_id`` 0 needs
to map to provide a mapping from 0 to this struct.
.. code:: c
const struct hal_flash *
hal_bsp_flash_dev(uint8_t id)
{
if (id != 0) {
return NULL;
}
return &my_at45db_dev;
}