Inspired by @DrAzzy's AT25 module implementations, I implemented a dedicated module for FRAM/MRAM. Here the code with usage example, tests, and test output. Documentation is in code (Attachment includes all in one file ready to be pasted into IDE editor, uploaded, and run. - Chip used: 256 Kbit / 32KB - 32K*8 - Cypress FRAM FM25V02-G about 4$). For more about FRAM/MRAM see 256-Kbit (32 K × 8) Serial (SPI) F-RAM - Ferroelecric RAM - SPI challenges.
var FRAM = (function(){
/* Copyright (C) 2014 allObjects aka Markus Muetschard. See the file LICENSE for copying permission. */
/*
FRAM/MRAM SPI Module - Fero-electric / Magneto-resistive nonvolatile RAM
========================================================================
Supports up to 1 MByte capacity FRAM/MRAM such as
- Cypress.com 256Kbit (32 K x 8) SPI FRAM - FM25V02-G
- Fujitsu.com 64Kbit ( 8 K x 8) SPI FRAM - MB85RS64V
*** usage:
var FRAM = require("FRAM");
returns FRAM 'class' (function(), 'default' constructor) for oo-style use.
Note: You can name the class what ever you want it to be.
var fram = new FRAM(spi,cap,cs,md);
creates a connected FRAM instance (same as connect(), see next)
var fram = new (require("FRAM"))(spi,cap,cs,md);
is a combination of require and new and can be used when there is
no need for the application to have access to the class object
Note: new directly on (require("..."))(...); requires require() to be in ()s.
var fram = require("FRAM").connect(spi,cap,cs,md);
is there for connect()-style usage.
Parameters to pass on new ... or connect() are:
- spi - SPI instance (hard or soft)
- cap - capacity in Kbits
- cs - pin that drives FRAM/MRAM chip select
- md - optional - for pinMode(cs,md); // pass "output" when no external pull-up
if undefined is returned on new or connect, error happened (not implemented yet)
fram.read(a,n,f);
reads n bytes starting at address a; f is optional return format:
- f - absent or === 0: Uint8Array
- f - === 1: String
if a === undefined, last read/written address+1 is used; initialized on new to 0
if undefined is returned, error happened (not implemented yet)
fram.write(a,d);
writes String | Array d at address a and returns number of written bytes
if a === undefined, last read/written addr+1 is used; initialized on new w/ 0
if -1 is returned, error happened (not implemented yet)
*** example:
SPI2.setup({sck:B13, miso:B14, mosi:B15, baud: 18000000}); // setup hw SPI2
var fram = new (require("FRAM"))(SPI2,256,A2,"output"); // FRAM w/ CS on A2
console.log("Capacity: " + fram.cap*128/8 + " KBytes"); // 32KBytes w/ 256Kbits
console.log("Bytes written @ 0: "+fram.write(0,"String at addr 0.")); // 17
console.log("17 bytes read @ 0: "+fram.read(0,17,1)); // 'String at addr 0.'
console.log("17 bytes read @ 0: "+fram.read(0,17)); // ...[83, 116, 105,...46]...
console.log("Bytes written @ 0: "+fram.write(0,[65,66,67,68,69,70])); // 6 (0..5)
console.log("Bytes written @ n: "+fram.write(undefined,": @")); // 3 (@ next addr)
console.log("17 bytes read @ 0: "+fram.read(0,17,1)); // 'ABCDEF: @ addr 0.'
*/
var ca2 = function(c,a) { this.cs.reset(); this.spi.send([c,a>>8,a]); };
var ca3 = function(c,a) { this.cs.reset(); this.spi.send([c,a>>16,a>>8,a]); };
var FRAM = function(spi,cap,cs,md) {
cs.set(); if (md) { pinMode(cs,md); }
this.spi = spi;
this.cap = cap>>7;
this.cs = cs;
this.ca = (cap>8388608) ? ca3 : ca2;
this.a=0;
};
FRAM.connect = function(spi,cap,cs,md) {
return new FRAM(spi,cap,cs,md);
};
FRAM.prototype.read = function(a,n,f){
a = (a===undefined) ? this.a : a; this.ca(3,a);
var r = this.spi.send(new Uint8Array(n),this.cs); this.a += n;
return (f===1) ? E.toString(r) : r;
};
FRAM.prototype.write = function(a,d){
a = (a===undefined) ? this.a : a;
this.spi.send(0x06,this.cs); this.ca(2,a);
this.spi.send(d); this.cs.set(); this.a += d.length;
return d.length;
};
return FRAM; // exports = FRAM;
})();
Usage example and test code (256 Kbit / 32KB - 32K*8 - Cypress FRAM F25V02-G):
SPI2.setup({sck:B13, miso:B14, mosi:B15, baud: 18000000});
// var FRAM = require("FRAM"); // get module
var fram = new FRAM(SPI2,256,A2,"output");
// var fram = FRAM.connect(SPI2,256,A2,"output"); // alternative 1 w/ get module
// var fram = new (require("FRAM")).connect(SPI2,256,A2,"output"); // alternative 2
// var fram = require("FRAM").connect(SPI2,256,A2,"output"); // classical
console.log("~");
console.log("fram.cap(acity)" +
" = " + fram.cap*128 + " Kbit" +
" = " + (fram.cap*128)*(1024/8) + " Bytes" +
" = " + (fram.cap*128)*(1024/8)/1024 + " KBytes");
function writes() {console.log("~");
console.log("*** writes ***");
console.log("@000:10: 'FRAM@000 A': " + fram.write( 0,"FRAM@000 A"));
console.log("@008:11: 'FRAM@016 AB': " + fram.write( 16,"FRAM@016 AB"));
console.log("@032:12: 'FRAM@032 ACD': " + fram.write( 32,"FRAM@032 ABC"));
console.log("@128:13: 'FRAM@128 ABCD': " + fram.write(128,"FRAM@128 ABCD"));
console.log("@256:14: 'FRAM@256 ABCDE': " + fram.write(256,"FRAM@256 ABCDE"));
console.log("@512:15: 'FRAM@512 ABCDEF': " + fram.write(512,"FRAM@512 ABCDEF"));
}
function reads() {console.log("~");
console.log("*** reads ***");
console.log("@000:10:",fram.read( 0, 10));
console.log("@016:11:",fram.read( 16, 11));
console.log("@032:12:",fram.read( 32, 12));
console.log("@128:13:",fram.read(128, 13));
console.log("@256:14:",fram.read(256, 14));
console.log("@512:15:",fram.read(512, 15));
console.log("@000:10:",fram.read( 0, 10,1));
console.log("@016:11:",fram.read( 16, 11,1));
console.log("@032:12:",fram.read( 32, 12,1));
console.log("@128:13:",fram.read(128, 13,1));
console.log("@256:14:",fram.read(256, 14,1));
console.log("@512:15:",fram.read(512, 15,1));
}
function hurray() {console.log("~");
console.log("*** reads, overwrite, and reads ***");
console.log("read @000:44: " + fram.read( 0,44));
console.log("read @000:44: " + fram.read( 0,44,1));
console.log(" 0....'....1....'....2....'....3....'....4....'");
console.log("write @010:20: 'Hurray! ...it works!': " +
fram.write( 10,"Hurray! ...it works!"));
console.log("read @010:20: " + fram.read(10,20));
console.log("read @010:20: " + fram.read(10,20,1));
console.log("read @000:44: " + fram.read( 0,44));
console.log("read @000:44: " + fram.read( 0,44,1));
console.log(" 0....'....1....'....2....'....3....'....4....'");
}
function clear() {console.log("~");
console.log("*** clear (fill all with '~' ***");
var x = 0, b = 256, r = fram.cap * 16 * 1024 ; // bytes;
var f = new Uint8Array(b); f.fill(126,0,b); f = E.toString(f);
while(r > 0) {
x += fram.write(x,(r > b) ? f : f.substr(0,r));
r -= b;
}
}
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
Inspired by @DrAzzy's AT25 module implementations, I implemented a dedicated module for FRAM/MRAM. Here the code with usage example, tests, and test output. Documentation is in code (Attachment includes all in one file ready to be pasted into IDE editor, uploaded, and run. - Chip used: 256 Kbit / 32KB - 32K*8 - Cypress FRAM FM25V02-G about 4$). For more about FRAM/MRAM see 256-Kbit (32 K × 8) Serial (SPI) F-RAM - Ferroelecric RAM - SPI challenges.
Usage example and test code (256 Kbit / 32KB - 32K*8 - Cypress FRAM F25V02-G):
Test output:
1 Attachment