Skip to content

filipembedded/nor_fx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nor_fx

Intro

A cross-platform NOR flash driver library designed for embedded devices. The driver is hardware-agnostic — all platform I/O is supplied by the application via function pointers, making it portable across any MCU or operating system. The library also ships a Linux-hosted flash simulator, enabling full driver testing on a development machine without any hardware.

Design

This library is designed in a layered manner:

+-------------------+
|    application    | - Embedded application using NOR flash as a storage medium
+-------------------+
          ^
          |
+-------------------+
|    file system    | - Optional: littlefs glue layer (fs/littlefs/)
+-------------------+
          ^
          |
+-------------------+
|      driver       | - NOR flash driver: constant, cross-platform (driver/)
+-------------------+
          ^
          |
+-------------------+
|       port        | - Platform port: user configurable, depends on hardware (port/)
+-------------------+

The driver layer provides a unified API that remains identical across all supported platforms. All hardware interaction is abstracted behind six function pointers held in a struct norfx_device:

Callback Description
spi_chip_select Assert chip-select (CS low)
spi_chip_deselect De-assert chip-select (CS high)
spi_write Transmit bytes over SPI
spi_read Receive bytes over SPI
get_tick_ms Return a millisecond tick counter
delay_ms Block for N milliseconds

The port layer connects a specific platform to the driver by implementing those six callbacks. The optional file system layer provides a ready-made littlefs integration on top of the driver.

Driver API

enum norfx_status norfx_reset(struct norfx_device *dev);

enum norfx_status norfx_read_id(struct norfx_device *dev,
                                enum norfx_id_kind id,
                                uint32_t *id_val);

enum norfx_status norfx_read(struct norfx_device *dev,
                             uint32_t start_page, uint8_t offset,
                             uint32_t size, uint8_t *rx_buf);

enum norfx_status norfx_fast_read(struct norfx_device *dev,
                                  uint32_t start_page, uint8_t offset,
                                  uint32_t size, uint8_t *rx_buf);

enum norfx_status norfx_erase_sector(struct norfx_device *dev,
                                     uint16_t num_sector);

enum norfx_status norfx_page_program(struct norfx_device *dev,
                                     uint32_t page, uint16_t offset,
                                     uint32_t size, uint8_t *data);

enum norfx_status norfx_write(struct norfx_device *dev,
                              uint32_t page, uint16_t offset,
                              uint32_t size, uint8_t *data,
                              uint8_t *scratch_buf);

Note: norfx_write performs an automatic read-modify-write cycle and is intended for raw flash usage. Do not use it with a file system such as littlefs — pass norfx_page_program and norfx_erase_sector directly to the littlefs block device callbacks instead.

Porting the Library

Create a .c / .h pair under port/<platform>/ and implement the six callbacks. Rules:

  • No platform headers in .h — use void * for HAL handle types. Cast inside the .c file only.
  • Implement a struct norfx_<platform>_ctx to carry the hardware handles passed through void *context.

A complete STM32F4 port (HAL SPI) is located at port/stm32/f4/.
A Linux simulation port (file-backed, no hardware needed) is located at port/native_sim/linux/.

Minimal port skeleton:

/* port_myplatform.h */
#include "nor_fx.h"

struct norfx_myplatform_ctx {
    void    *hspi;      /* SPI handle — void* to avoid HAL header in .h */
    void    *cs_port;   /* GPIO port  — void* for the same reason        */
    uint16_t cs_pin;
};

enum norfx_status norfx_myplatform_cs_select(void *context);
enum norfx_status norfx_myplatform_cs_deselect(void *context);
enum norfx_status norfx_myplatform_spi_write(void *context, uint8_t *data, uint16_t size);
enum norfx_status norfx_myplatform_spi_read(void *context, uint8_t *data, uint16_t size);
uint32_t          norfx_myplatform_get_tick_ms(void *context);
void              norfx_myplatform_delay_ms(void *context, uint32_t delay);
/* port_myplatform.c */
#include "platform_hal.h"   /* HAL header lives here only */
#include "port_myplatform.h"

enum norfx_status norfx_myplatform_spi_write(void *context,
                                             uint8_t *data,
                                             uint16_t size)
{
    struct norfx_myplatform_ctx *ctx = context;
    /* cast void* back to real HAL type here */
    ...
}

Linux Simulator

The library includes a file-backed NOR flash simulator for host testing (port/native_sim/linux/). It models correct NOR flash behaviour:

  • Read — returns flash content directly.
  • Page program — ANDs incoming bytes with existing content (bits can only go 1→0, not 0→1 without an erase).
  • Sector erase — resets 4 KB to 0xFF.
  • WIP / WEL bits — simulated in Status Register 1.
  • JEDEC ID — returns Winbond W25Q128JV values (0xEF 0x70 0x18).
  • Persistent state — backed by a file on disk; state survives across runs.

Basic usage:

#include "nor_fx.h"
#include "port_linux.h"

norfx_sim_ctx_t ctx;
norfx_sim_init(&ctx, "flash.bin", NORFX_SIM_FLASH_SIZE);

struct norfx_device dev = {
    .context          = &ctx,
    .spi_chip_select   = norfx_sim_cs_select,
    .spi_chip_deselect = norfx_sim_cs_deselect,
    .spi_write         = norfx_sim_spi_write,
    .spi_read          = norfx_sim_spi_read,
    .get_tick_ms       = norfx_sim_get_tick_ms,
    .delay_ms          = norfx_sim_delay_ms,
};

norfx_reset(&dev);
/* ... use driver normally ... */
norfx_sim_deinit(&ctx);

Building and Running Tests

The library uses explicit CMake options for optional components.

Default behavior:

  • standalone (PROJECT_IS_TOP_LEVEL=TRUE): builds the Linux simulation port, norfx_lfs, and tests,
  • submodule / parent-project mode: builds only norfx_driver unless the parent explicitly enables other components.

Important options:

  • NORFX_BUILD_LFS
  • NORFX_BUILD_PORT_NATIVE_LINUX
  • NORFX_BUILD_PORT_STM32_F4
  • NORFX_BUILD_TESTS
git submodule update --init --recursive   # pulls Unity test framework
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug
cmake --build build
ctest --test-dir build --output-on-failure

Expected output (depending on whether NORFX_BUILD_LFS is enabled):

100% tests passed, 0 tests failed out of 6
# or
100% tests passed, 0 tests failed out of 7

Submodule Integration

When consumed as a git submodule, the parent project explicitly selects the optional NORFX components it needs:

# Parent project CMakeLists.txt
set(NORFX_BUILD_PORT_STM32_F4 ON CACHE BOOL "" FORCE)
add_subdirectory(libraries/nor_fx)

# Provide STM32 HAL headers/includes to the actual STM32 port target.
target_link_libraries(norfx_port_stm32 PRIVATE stm32cubemx)

target_link_libraries(my_firmware PRIVATE
    norfx_driver
    norfx_port_stm32_f4
)

Compatibility notes:

  • norfx_port_stm32 remains the concrete target used to attach STM32 HAL dependencies.
  • norfx_port_stm32_f4 is provided as a clearer alias for linking from firmware targets.
  • norfx_port_native_linux is provided as a clearer alias for the Linux simulator target.

See ARCHITECTURE.md for a full description of the CMake target graph and design decisions.

Demos

A complete demo of the nor_fx library running on STM32 can be found in the following repository.

License

This project is licensed under the BSD 3-Clause License — see the LICENSE file for details.

About

NOR FLASH XPLAT - NOR Flash memory cross-platform driver

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors