Architecture Deep Dive

Application developers use the same fs* API for every project. Customer-specific settings such as the filesystem backend, flash geometry, and hardware callbacks are defined in JSON and converted into generated headers. To support a new deployment, you update the configuration and regenerate the files—application code stays unchanged.

Developer Perspective

A developer writes business logic once and keeps using the same file operations. No customer branch is required in app modules.

  • One include: `Midd_FS/fs_port.h`
  • One startup contract: `FS_HARDWARE_INIT` then `fsInit`
  • One API family: `fs*` operations

Customer Perspective

Each customer/project controls file system behavior in JSON. The customer can switch active backend and parameters without editing app source files.

  • `activeFsName` selects backend
  • `cells`, `geometry`, `flashHwFunc` define behavior
  • Generated header reflects selected configuration

Layer Overview

flowchart TB
  APP[Application Services] --> API["Midd_FS/fs_port.h"]
  API --> GEN1["Customers/FS_Port_Config.h"]
  GEN1 --> GEN2["Customers/NAME/Fs/cus_fs_port_config.h"]
  GEN2 --> PORT["fs_port_flashLink or littlefs or flashFS"]
  PORT --> HW["Hardware callbacks from flashHwFunc"]
  CONF["Customers/NAME/Fs/fs_config.json"] --> SCRIPT[generate_fs_port_config.py]
  SCRIPT --> GEN1
  SCRIPT --> GEN2
[Fallback layer model]
Application Services
  -> Midd_FS/fs_port.h
    -> Customers/FS_Port_Config.h
      -> Customers/NAME/Fs/cus_fs_port_config.h
        -> selected fs_port backend
          -> hardware callbacks
Customers/NAME/Fs/fs_config.json
  -> generate_fs_port_config.py
    -> generated headers

Lifecycle

During startup, generated macros create and configure backend operations. After this point, app code only sees common API behavior.

Startup sequence
sequenceDiagram
  participant App as AppZMeterGw
  participant Gen as Generated FS config
  participant Port as Active FS port
  App->>Gen: FS_HARDWARE_INIT(error)
  Gen->>Port: bind callbacks and geometry
  App->>Port: fsInit()
  Port-->>App: ready
  App->>Port: fsOpenFile/fsReadFile/fsWriteFile
[Fallback sequence]
App -> FS_HARDWARE_INIT(error)
    -> backend callback and geometry binding
App -> fsInit()
    -> backend ready
App -> fs* operations

Operational benefit

  • Lower regression risk during customer/project adaptation
  • Clear change scope in generated files
  • Fast onboarding for new developers
  • Safer long term maintenance

The architecture is fit for product families where hardware and memory map may change per customer/project.