Skip to content

Commit 3eded85

Browse files
committed
finish up EEPROM library, add docs, add examples
1 parent 18c7dfb commit 3eded85

27 files changed

Lines changed: 1296 additions & 212 deletions

docs/api/EEPROM.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# EEPROM
2+
3+
This is a library to access the built-in EEPROM of the STM8 MCUs. It does
4+
**not** work with external I2C or SPI-EEPROM.
5+
6+
It is based on the Arduino EEPROM Library V2.0 by Christopher Andrews.
7+
In addition to the common Arduino-methods it defines some functions for
8+
low-level access. These functions behave similar to the built-in AVR
9+
functions. (see [below](#avr-api))
10+
11+
12+
## Arduino-API
13+
14+
This is a pre-instantiated singleton library. It is not possible to use more
15+
than one instance per sketch or to change the instance name.
16+
17+
The API syntax is very similar to the original C++ syntax. In most cases
18+
replacing the dots in the method names for underscores is all it needs. Only
19+
the `EEPROM[]` operator and the `EEPtr` and `EERef` behave a little
20+
different than their Arduino counterparts.
21+
22+
23+
Arduino syntax |sduino syntax
24+
-------------------- |---------------------
25+
`val = EEPROM.read(idx)` |`val = EEPROM_read(idx)`
26+
`EEPROM.write(idx, val)` |`EEPROM_write(idx, val)`
27+
`EEPROM.update(idx, val)` |`EEPROM_update(idx, val)`
28+
`val = EEPROM.begin()` |`val = EEPROM_begin()`
29+
`val = EEPROM.end()` |`val = EEPROM_end()`
30+
`val = EEPROM.length()` |`val = EEPROM_length()`
31+
`EEPROM.put(idx,T)` |`EEPROM_put(idx,T)`
32+
`EEPROM.get(idx,T)` |`EEPROM_get(idx,T)`
33+
`EEPROM[idx]` |`EEPROM_cell[idx]`
34+
35+
36+
#### **`EEPROM_read( address )`** [[_example_]](EEPROM/examples/eeprom_read.md)
37+
38+
This function allows you to read a single byte of data from the eeprom. Its
39+
only parameter is an `int` which should be set to the address you wish to
40+
read.
41+
42+
The function returns an `unsigned char` containing the value read.
43+
44+
45+
#### **`EEPROM_write( address, value )`** [[_example_]](EEPROM/examples/eeprom_write.md)
46+
47+
The `EEPROM_write()` method allows you to write a single byte of data to the
48+
EEPROM. Two parameters are needed. The first is an `int` containing the
49+
address that is to be written, and the second is a the data to be written
50+
(`unsigned char`).
51+
52+
This function does not return any value.
53+
54+
55+
#### **`EEPROM_update( address, value )`** [[_example_]](EEPROM/examples/eeprom_update.md)
56+
57+
This function is similar to `EEPROM_write()` however this method will only
58+
write data if the cell contents pointed to by `address` is different to
59+
`value`. This method can help prevent unnecessary wear on the EEPROM cells.
60+
61+
This function does not return any value.
62+
63+
64+
#### **`EEPROM_get( address, object )`** [[_example_]](EEPROM/examples/eeprom_get.md)
65+
66+
This function will retrieve any object from the EEPROM. Two parameters are
67+
needed to call this function. The first is an `int` containing the address
68+
that is to be written, and the second is the object you would like to read.
69+
70+
This function is implemented as a macro. On completion, it evaluates to a
71+
pointer to the `object` passed in. It does not need to be used and is only
72+
returned for convience.
73+
74+
**Note:** This means that the expression for `object` will be evaluated
75+
twice. This **will break sketches** using pre- or postincrement operators,
76+
because they will end up beeing called twice.
77+
78+
79+
#### **`EEPROM_put( address, object )`** [[_example_]](EEPROM/examples/eeprom_put.md)
80+
81+
This function will write any object to the EEPROM. Two parameters are needed
82+
to call this function. The first is an `int` containing the address that is
83+
to be written, and the second is the object you would like to write.
84+
85+
This function uses the _update_ method to write its data, and therefore only
86+
rewrites changed cells.
87+
88+
This function is implemented as a macro using `&object` and `sizeof(object)`
89+
to reference the actual data to be written. This means that:
90+
91+
- integer constants can't be directly written, `EEPROM_put(0,42)` will fail.
92+
- The expression for `object` will be evaluated twice. This will break
93+
sketches using pre- or postincrement operators.
94+
95+
This macro evaluates to a pointer to the `object` passed in. It does not
96+
need to be used and is only returned for convience.
97+
98+
99+
#### **`EEPROM_length()`**
100+
101+
This function returns an `unsigned int` containing the number of cells in
102+
the EEPROM.
103+
104+
105+
#### **`EEPROM_begin()`**
106+
107+
This function returns the number of the first cell in the EEPROM. This is
108+
similar to the semantics of the original libray, where this method is ment
109+
for use with STL objects, custom iteration and C++11 style ranged for loops.
110+
111+
112+
#### **`EEPROM_end()`**
113+
114+
This function returns the number just behind the last EEPROM cell. Since the
115+
EEPROM cells always start at zero this is the number of EEPROM cells. Used
116+
with `EEPROM_begin()` to provide custom iteration.
117+
118+
119+
#### **Subscript operator: `EEPROM_cell[address]`**
120+
121+
Use the syntax `EEPROM_cell[address]` instead. This allows acessing the
122+
EEPROM like an array. EEPROM cells can be read _and_ **_written_** directly
123+
using this method.
124+
125+
**Note:** For write access, the EEPROM has to be unlocked by calling
126+
`eeprom_unlock()` first. Trying to write the EEPROM without unlocking will
127+
permanently lock the EEPROM after three failed write accesses. Only a
128+
hardware reset can re-enable the EEPROM.
129+
130+
Please keep in mind that every call of `EEPROM_write()` or `EEPROM_update()`
131+
re-locks the EEPROM after the access.
132+
133+
134+
135+
136+
137+
## AVR-API
138+
139+
In addition to the common Arduino-methods it defines some functions for
140+
low-level access. These functions behave similar to the built-in AVR
141+
functions.
142+
143+
For the sake of compatibility to the Arduino world all EEPROM addresses
144+
start at zero at the needed offset calculation is handled internally.
145+
146+
AVR/Arduino syntax |sduino syntax |Description
147+
-------------------- |--------------------- |-----------------
148+
N/A |`eeprom_unlock()` |
149+
N/A |`eeprom_lock()` |
150+
N/A |`s = eeprom_is_unlocked()`|returns true if EEPROM is unlocked
151+
`s = eeprom_is_ready()` |`s = eeprom_is_ready()`|returns true if EEPROM is ready (no write in progress)
152+
`eeprom_write_block(idx, *src, len)`|`eeprom_write_block(idx, *src, len)`|
153+
`eeprom_update_block(idx, *src, len)`|`eeprom_update_block(idx, *src, len)`|
154+
`eeprom_read_block(idx, *dest, len)`|`eeprom_read_block(idx, *dest, len)`|
155+
156+
157+
#### **Access control: `eeprom_lock()`/`eeprom_unlock()`**
158+
159+
To prevent accidental modifications of the EEPROM contents, write access is blocked by default. For write access, the EEPROM has to be unlocked first. This can be done by calling `eeprom_unlock()`.
160+
161+
After accessing the EEPROM it can be re-locked by calling `eeprom_lock()`. Please keep in mind that every call of `EEPROM_write()` or `EEPROM_update()` re-locks the EEPROM after the access.
162+
163+
**Note:** Without unlocking, the EEPROM will be permanently locked until the next hardware reset after three failed write accesses.
164+
165+
#### **Status check: `eeprom_is_ready()`**
166+
167+
A write access is slow. To avoid stalling the MCU for a longer time by busy waiting it is possible to check the current write status. This can be used to spread out single byte writes over time and use the waiting time in a more productive way.
168+
169+
This macro returns a non-zero value if the EEPROM is ready for a new write access.
170+
171+
172+
173+
## Example
174+
175+
Stores values read from analog input 0 into the EEPROM. These values will
176+
stay in the EEPROM when the board is turned off and may be retrieved later
177+
by another sketch.
178+
179+
```c
180+
#include <EEPROM.h>
181+
182+
int addr = 0;
183+
184+
void setup()
185+
{
186+
}
187+
188+
void loop()
189+
{
190+
int val = analogRead(0) / 4;
191+
192+
EEPROM_write(addr, val);
193+
194+
addr = addr + 1;
195+
if (addr == EEPROM_length()) {
196+
addr = 0;
197+
}
198+
199+
delay(100);
200+
}
201+
```
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# eeprom_get.ino
2+
```c
3+
/***
4+
eeprom_get example.
5+
6+
This shows how to use the EEPROM.get() method.
7+
8+
To pre-set the EEPROM data, run the example sketch eeprom_put.
9+
This sketch will run without it, however, the values shown
10+
will be shown from what ever is already on the EEPROM.
11+
12+
This may cause the serial object to print out a large string
13+
of garbage if there is no null character inside one of the strings
14+
loaded.
15+
16+
Modified to C for use with SDuino by Michael Mayer 2018
17+
Written by Christopher Andrews 2015
18+
Released under MIT licence.
19+
***/
20+
21+
#include <EEPROM.h>
22+
23+
void secondTest();
24+
25+
void setup() {
26+
27+
float f = 0.00f; //Variable to store data read from EEPROM.
28+
int eeAddress = 0; //EEPROM address to start reading from
29+
30+
Serial_begin(9600);
31+
while (!Serial) {
32+
; // wait for serial port to connect. Needed for native USB port only
33+
}
34+
Serial_print_s("Read float from EEPROM: ");
35+
36+
//Get the float data from the EEPROM at position 'eeAddress'
37+
EEPROM_get(eeAddress, f);
38+
Serial_println_fd(f, 3); //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float.
39+
40+
/***
41+
As get also returns a reference to 'f', you can use it inline.
42+
E.g: Serial.print( EEPROM.get( eeAddress, f ) );
43+
***/
44+
45+
/***
46+
Get can be used with custom structures too.
47+
I have separated this into an extra function.
48+
***/
49+
50+
secondTest(); //Run the next test.
51+
}
52+
53+
struct MyObject {
54+
float field1;
55+
byte field2;
56+
char name[10];
57+
};
58+
59+
void secondTest() {
60+
int eeAddress = sizeof(float); //Move address to the next byte after float 'f'.
61+
62+
struct MyObject customVar; //Variable to store custom object read from EEPROM.
63+
EEPROM_get(eeAddress, customVar);
64+
65+
Serial_println_s("Read custom object from EEPROM: ");
66+
Serial_println_f(customVar.field1);
67+
Serial_println_u(customVar.field2);
68+
Serial_println_s(customVar.name);
69+
}
70+
71+
void loop() {
72+
/* Empty loop */
73+
}
74+
```
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# eeprom_put.ino
2+
```c
3+
/***
4+
eeprom_put example.
5+
6+
This shows how to use the EEPROM.put() method.
7+
Also, this sketch will pre-set the EEPROM data for the
8+
example sketch eeprom_get.
9+
10+
Note, unlike the single byte version EEPROM.write(),
11+
the put method will use update semantics. As in a byte
12+
will only be written to the EEPROM if the data is actually
13+
different.
14+
15+
Modified to C for use with SDuino by Michael Mayer 2018
16+
Written by Christopher Andrews 2015
17+
Released under MIT licence.
18+
***/
19+
20+
#include <EEPROM.h>
21+
22+
struct MyObject {
23+
float field1;
24+
byte field2;
25+
char name[10];
26+
};
27+
28+
void setup() {
29+
Serial_begin(9600);
30+
while (!Serial) {
31+
; // wait for serial port to connect. Needed for native USB port only
32+
}
33+
34+
float f = 123.456f; //Variable to store in EEPROM.
35+
int eeAddress = 0; //Location we want the data to be put.
36+
37+
38+
//One simple call, with the address first and the object second.
39+
EEPROM_put(eeAddress, f);
40+
41+
Serial_println_s("Written float data type!");
42+
43+
/** Put is designed for use with custom structures also. **/
44+
45+
//Data to store.
46+
struct MyObject customVar = {
47+
3.14f,
48+
65,
49+
"Working!"
50+
};
51+
52+
eeAddress += sizeof(float); //Move address to the next byte after float 'f'.
53+
54+
EEPROM_put(eeAddress, customVar);
55+
Serial_print_s("Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!");
56+
}
57+
58+
void loop() {
59+
/* Empty loop */
60+
}
61+
```

0 commit comments

Comments
 (0)