STM32 EEPROM Blue Pill
STM32 EEPROM Emulation - EEPROM is an extension of Electrically Erasable Programmable Read-Only Memory, a memory chip that can store data even if power or resources are disconnected.
Generally every microcontroller already has an Internal EEPROM, this makes
the circuit simpler without having to add an external chip.
Unlike Arduino which has an internal non-volatile storage chip, some Blue
Pill devices do not have it. For this reason, if we want to save data to
Blue Pill, we need a method that can allocate program flash memory as
EEPROM.
In the official language of the ST datasheet, this memory allocation is
called STM32 EEPROM Emulation. I have never used this on Arduino, so from that I shared a little
program in this Article.
A. STM32 EEPROM Emulation
This emulation is done by considering the limitation of Flash memory and
some requirements. This approach requires at least two pages of flash
memory of the same size allocated for non-volatile data. For a more
complete explanation of this EEPROM Emulation, please read the
official ST document.
STM32 EEPROM Arduino |
Officially, to program this chip using software from the ST itself named
STM32CubeIDE. But because I'm not familiar with it, I just use Arduino IDE
because there are already many libraries available.
Well, because the Arduino IDE is basically an IDE for programming AVR,
someone developed a library board for this chip to be used in the Arduino
IDE. This is very useful.
B. Library for STM32 Emulation Arduino
The library board to support this chip to be programmed using the Arduino
IDE has several options. However, the library board that I use on this
project is
STM32 Arduino Core.
This Arduino Core STM32 tries to emulate this non-volatile storage access
way as in Arduino. STM32 Arduino Core provides this library which I
managed to try.
If we use arduino, to write data just use "EEPROM.write (address, data)"
and read with "EEPROM.read (address)".
Whereas what I use to write is "EEPROMwrite (address, data)" and reads
with "EEPROMread (address, data_data)".
The STM32 program is to use ST-LINK V2 Clone (China) and for serial
monitor communication I connect FTDI on pins A9 and A10.
Below is the program code that I have tested and succeeded. Please upload
the following
STM32 EEPROM
code to your STM32 and open Serial Monitor to see the stored data and the
results of reading the data.
C. Schematic For Testing
To program this Blue Pill, I use ST Link V2. For serial communication, using FTDI, please follow the following table
STM32 | FTDI |
A9 | RX |
A10 | TX |
D. Progam Code STM32 EEPROM Emulation
Program:
#include <EEPROM.h> const int addressEEPROM_min = 0; // Specify the address restrictions you want to use. const int addressEEPROM_max = 4095; // For example, the maximum is 4095, which means we allocate 4KB of memory (4096 bytes) for the Virtual EEPROM. float latitude = 4.158919; // This is an example of data that you want to save to EEPROM. float longitude = 96.124843; // Coordinate data consisting of Latitude and Longitude. int addressLat = 0; // The number of characters in the latitude value is 8, so the address starts from 0 to 8. int addressLon = 9; // The number of characters in the longitude value is 9, so the address starts from 9 to 17. void setup() { Serial.begin(9600); delay(100); String lat = String (latitude, 6); // Data to be saved to EEPROM is a String. This line is used for the conversion of float to String. String lon = String (longitude, 6); // Value 6 shows how many digits behind the comma will be converted. // ------------------- Write Data Commands ------------------- Serial.println(" -----------------------------------------"); Serial.println("| Writing Latitude to EEPROM | Saved |"); EEPROMwrite(addressLat, lat); Serial.println("| Writing Longitude to EEPROM | Saved |"); EEPROMwrite(addressLon, lon); Serial.println(" -----------------------------------------"); Serial.println("\n"); delay(1000); //---------------------------------------------------------- // ------------------- Read Data Commands ------------------- Serial.println("Baca data dari EEPROM....."); Serial.print("Latitude : "); Serial.println(EEPROMread(addressLat, 8)); // Get data from address 0 with 8 characters. Serial.print("Longitude : "); Serial.println(EEPROMread(addressLon, 9)); // Get data from address 9 with a total of 9 characters. Serial.println("\n"); delay(1000); //---------------------------------------------------------- Serial.println("Now, please COMMENT *Write Data Commands* to deactivate data write commands to EEPROM."); delay(5000); Serial.println("Then, please press the reset button or remove STM32 from the computer to see whether the data from the EEPROM is still stored or not."); } void loop() { } String EEPROMread(int StartAddr, int StringLength) { char buf[StringLength + 1]; eeprom_read_string(StartAddr, buf, StringLength + 1); String dataStr = buf; return dataStr; } void EEPROMwrite(int StartAddr, String DataString) { int val = DataString.length() + 1; char StringChar[val]; char buff[val]; DataString.toCharArray(StringChar, val); strcpy(buff, StringChar); eeprom_write_string(StartAddr, buff); } boolean eeprom_is_addr_ok(int addr) { return ((addr >= addressEEPROM_min) && (addr <= addressEEPROM_max)); } boolean eeprom_write_bytes(int startAddr, const byte* array, int numBytes) { int i; if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) { return false; } for (i = 0; i < numBytes; i++) { EEPROM.write(startAddr + i, array[i]); } return true; } boolean eeprom_write_string(int addr, const char* string) { int numBytes; // number of actual bytes to be written numBytes = strlen(string) + 1; // Write string content plus byte terminator string (0x00) return eeprom_write_bytes(addr, (const byte*)string, numBytes); } boolean eeprom_read_string(int addr, char* buffer, int bufSize) { byte ch; // read bytes from eeprom int bytesRead; // number of bytes read so far if (!eeprom_is_addr_ok(addr)) // check the starting address { return false; } if (bufSize == 0) // how can we store bytes in an empty buffer? { return false; } if (bufSize == 1) { buffer[0] = 0; return true; } bytesRead = 0; // initialize a byte counter ch = EEPROM.read(addr + bytesRead); // read the next byte from eeprom buffer[bytesRead] = ch; // save it in the user's buffer bytesRead++; // if no stop conditions are met, read the next byte from the eeprom while ( (ch != 0x00) && (bytesRead < bufSize) && ((addr + bytesRead) <= addressEEPROM_max) ) { ch = EEPROM.read(addr + bytesRead); buffer[bytesRead] = ch; // save it in the user's buffer bytesRead++; } if ((ch != 0x00) && (bytesRead >= 1)) // make sure the user buffer has the string terminator, (0x00) as the last byte { buffer[bytesRead - 1] = 0; } return true; }
Results:
Result from STM32 EEPROM |
May be useful.