Skip to content

FM24Cxx: FRAM (I2C) console driver with block read/write/format#24457

Merged
arendst merged 2 commits intoarendst:developmentfrom
TheHexaMaster:FM24CXX-FRAM-Driver
Feb 16, 2026
Merged

FM24Cxx: FRAM (I2C) console driver with block read/write/format#24457
arendst merged 2 commits intoarendst:developmentfrom
TheHexaMaster:FM24CXX-FRAM-Driver

Conversation

@TheHexaMaster
Copy link
Contributor

@TheHexaMaster TheHexaMaster commented Feb 15, 2026

Description:

Usecase:

FRAM is particularly suitable for highly volatile, frequently updated data where Flash/EEPROM wear would be a concern:

  • fast-changing device states (relays, switches, mode flags)
  • frequently modified configuration values and runtime parameters
  • lightweight log / event data and counters written often

This driver provides a simple console interface to validate wiring, test read/write behavior, and manage FRAM contents during development and troubleshooting.

Driver Features:

  • Add XDRV_93 console driver for FM24Cxx FRAM over I2C (16-bit address, MSB first).
  • Auto-detect FRAM on I2C bus 0/1 at configurable address (default 0x57).
  • Provide commands: FramInfo, FramReadFormat, FramRead, FramWrite, FramErase, plus text helpers FramReadString / FramWriteString.
  • Chunked I2C transfers and write payload sizing compatible with typical Wire TX buffer constraints.
  • Robust hex input parser for write command (supports separators and 0x.. tokens).
  • JSON-safe string output via escaping; block writes optionally fill remainder with 0x00.

Driver Compatibility:

  • FM24C16,32,64,128,256,512 FRAM Modules trought I2C
  • AT24C16,32,64,128,256,512 EEPROM Modules (not very suitable for high volatile data because of EEPROM limited lifespan)

Short Manual:

Build options and configuration

#DEFINE USE_I2C
#DEFINE USE_FM24CXX

Optional compile-time configuration macros:

#DEFINE FM24CXX_I2C_ADD
FRAM I2C address (default: 0x57)

#DEFINE FM24CXX_CAPACITY
Total FRAM size in bytes (default: 8192)

#DEFINE FM24CXX_BLOCK_SIZE
Block size in bytes. If set to 0, the whole chip is a single block.

#DEFINE FM24CXX_I2C_CHUNK
I2C read chunk size (default: 32).
Write payload is automatically limited to FM24CXX_I2C_CHUNK - 2 (because 16-bit address must be sent in the same I2C transaction).

#DEFINE FM24CXX_MAX_WRITE_BYTES
Hard cap for write payload (default: 4096).

#DEFINE FM24CXX_JSON_MAX_BYTES
Maximum bytes returned by FramRead as hex in JSON (default: 4096).

#DEFINE FM24CXX_JSON_MAX_STRING
Maximum bytes returned by FramReadString (default: 4096).

Block model

The FRAM memory is split into blocks:

If FM24CXX_BLOCK_SIZE == 0 → one block spanning the entire chip.

Otherwise → multiple blocks of size FM24CXX_BLOCK_SIZE, with the last block possibly smaller.

All commands that accept operate on the block start address and block length derived from this model.

Command reference
FramInfo

Shows detection and configuration.

Example

FramInfo
FramReadFormat

Reads a block and prints a formatted hex dump to the log (16 bytes per line). Returns a summary JSON.

Example

FramReadFormat 0
FramRead <block>

Reads an entire block and returns the result as a hex string in JSON ("data":"AABBCC...").
This is the recommended command for binary-safe dumps.

Example

FramRead 0
FramWrite <block> <hex-bytes>

Writes bytes parsed from the provided hex payload to the start of the block, then fills the remaining block bytes with 0x00.

Accepts flexible hex formats: AABBCC, AA BB CC, 0xAA,0xBB,0xCC

Example

FramWrite 0 AABBCCDD0011
FramWrite 0 0xAA 0xBB 0xCC
FramWriteString <block> <text>

Writes the provided text bytes directly to FRAM, then fills the remaining block bytes with 0x00 (including a terminating 0x00).

Supports quoted input for spaces:

FramWriteString 0 "Hello World!"

Examples

FramWriteString 0 Hello
FramWriteString 0 "Hello World!"
FramReadString <block>

Reads bytes from the start of the block until the first 0x00 byte (C-string style) or until FM24CXX_JSON_MAX_STRING is reached.

The returned text is JSON-escaped to prevent invalid JSON output.

Example

FramReadString 0
FramErase <block> / FramFormat all

Fills the target block (or all blocks) with 0x00.

Examples

FramErase 0
FramErase all

Console read output example:

23:13:44.942 CMD: Grp 0, Cmd 'FRAMREADFORMAT', Idx 1, Len 1, Pld 1, Data '1'
23:13:44.943 FM24CXX: READ block=1 start=0x0100 len=256
23:13:44.945 FM24CXX: 0x0100: 4C6F72656D20697073756D2069732061
23:13:44.947 FM24CXX: 0x0110: 2064756D6D79206F7220706C61636568
23:13:44.950 FM24CXX: 0x0120: 6F6C646572207465787420636F6D6D6F
23:13:44.952 FM24CXX: 0x0130: 6E6C79207573656420696E2067726170
23:13:44.954 FM24CXX: 0x0140: 6869632064657369676E2C207075626C
23:13:44.956 FM24CXX: 0x0150: 697368696E672C20616E642077656220
23:13:44.958 FM24CXX: 0x0160: 646576656C6F706D656E742E20497473
23:13:44.960 FM24CXX: 0x0170: 20707572706F736520697320746F2070
23:13:44.963 FM24CXX: 0x0180: 65726D697420612070616765206C6179
23:13:44.965 FM24CXX: 0x0190: 6F757420746F2062652064657369676E
23:13:44.967 FM24CXX: 0x01A0: 65642C20696E646570656E64656E746C
23:13:44.970 FM24CXX: 0x01B0: 79206F662074686520636F7079207468
23:13:44.972 FM24CXX: 0x01C0: 61742077696C6C207375627365717565
23:13:44.975 FM24CXX: 0x01D0: 6E746C7920706F70756C617465206974
23:13:44.977 FM24CXX: 0x01E0: 2C206F7220746F2064656D6F6E737472
23:13:44.979 FM24CXX: 0x01F0: 61746520766172696F757320666F6E74
23:13:44.980 RSL: RESULT = {"FramReadFormat":{"block":1,"bytes":256}}
23:14:02.555 CMD: framread 1
23:14:02.555 SRC: WebConsole from 10.0.4.226
23:14:02.555 CMD: Grp 0, Cmd 'FRAMREAD', Idx 1, Len 1, Pld 1, Data '1'
23:14:02.585 RSL: RESULT = {"FramRead":{"block":1,"bytes":256,"data":"4C6F72656D20697073756D20697320612064756D6D79206F7220706C616365686F6C646572207465787420636F6D6D6F6E6C79207573656420696E20677261706869632064657369676E2C207075626C697368696E672C20616E642077656220646576656C6F706D656E742E2049747320707572706F736520697320746F207065726D697420612070616765206C61796F757420746F2062652064657369676E65642C20696E646570656E64656E746C79206F662074686520636F707920746861742077696C6C2073756273657175656E746C7920706F70756C6174652069742C206F7220746F2064656D6F6E73747261746520766172696F757320666F6E74"}}
23:14:09.483 CMD: framreadstring 1
23:14:09.484 SRC: WebConsole from 10.0.4.226
23:14:09.484 CMD: Grp 0, Cmd 'FRAMREADSTRING', Idx 1, Len 1, Pld 1, Data '1'
23:14:09.513 RSL: RESULT = {"FramReadString":{"block":1,"bytes":256,"truncated":0,"data":"Lorem ipsum is a dummy or placeholder text commonly used in graphic design, publishing, and web development. Its purpose is to permit a page layout to be designed, independently of the copy that will subsequently populate it, or to demonstrate various font"}}

Notes and limitations

Binary vs text

  • Use FramRead/FramWrite (hex) for binary-safe operations.
  • Use FramReadString/FramWriteString for text only.
  • FramReadString stops at the first 0x00. Data containing embedded zeros is not representable as a “string”.

Response size

FramRead returns hex, which is 2× the byte count. Large blocks may exceed Tasmota’s response buffer limits even if FM24CXX_JSON_MAX_BYTES allows it.

I2C framing

Low-level access uses 16-bit memory addressing (MSB first), with chunked reads/writes and yield() calls to remain watchdog-friendly.

Related issue (if applicable): fixes #

Checklist:

  • The pull request is done against the latest development branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR and the code change compiles without warnings
  • The code change is tested and works with Tasmota core ESP8266 V.2.7.8
  • The code change is tested and works with Tasmota core ESP32 V.3.1.10
  • I accept the CLA.

NOTE: The code change must pass CI tests. Your PR cannot be merged unless tests pass

@TheHexaMaster TheHexaMaster marked this pull request as draft February 15, 2026 22:03
@TheHexaMaster TheHexaMaster marked this pull request as ready for review February 15, 2026 22:04
@TheHexaMaster TheHexaMaster reopened this Feb 15, 2026
@arendst
Copy link
Owner

arendst commented Feb 16, 2026

Isn't it wonderful how easy it is to extend Tasmota; only one driver file and two minor updates.

@arendst arendst merged commit 48df14f into arendst:development Feb 16, 2026
66 of 128 checks passed
josef109 pushed a commit to josef109/Tasmota that referenced this pull request Mar 15, 2026
…dst#24457)

* FM24Cxx: FRAM (I2C) console driver with block read/write/format

* Fix formatting in license comment section
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants