-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow 1020 bytes of EEPROM + add standard Arduino EEPROM API #64
Conversation
It was only possible to use 512 bytes of EEPROM despite space for 1024 bytes were reserved. ( Note that the EEPROM controler of the LGT8Fx32p will reserve 2048 bytes from the flash. )
I removed the EEARH masks so we will be able to change the size of EEPROM at compile time. The E2PCTL inside the LGT8Fx38p will do the rest.
Do we have a writeup of how the EEPROM works on these chips? It would be nice to keep documenting some of these 'features' that we're running into. |
Is this backed by example code? I'm sorry I don't understand what the EEARH mask is for anyways. 😅 |
@dwillmore : I've found information into the databook v1.0.5-english. They say the EEPROM is stored into the main Flash, and that it will uses twice the size of the EEPROM. They say that to write into the fake EEPROM, they first have to erase the full flash page which are 1KB long. However, they also explain that this technique require the controller to uses the 2 lasts bytes of each page, which mean that over the 1024 bytes of EEPROM, only 1022 are actually available. Though, because the flash memory works in 32bits patterns, that's the 4 last bytes that might be unusable, and only 1020 bytes are actually available. <==== edit : I'll have to double check this though. In the original code, If you apply my patch, the actual size of the EEPROM can be confirmed using this example code : // EDIT : YOU MUST APPLY THE PATCH TO EEPROM.c
#include <EEPROM.h>
void setup()
{
Serial.begin(9600);
Serial.println(F("Hello!"));
delay(1000);
//#define DATA(a) (( a )&0xff) // <==== change this to change the data pattern written to the EEPROM
#define DATA(a) (( (a)>>5 )&0xff) // <==== change this to change the data pattern written to the EEPROM
Serial.println(F("Writing to EEPROM : "));
for(uint16_t a=0; a<1024; a++)
{
byte b = DATA(a);
Serial.print( a );
Serial.print(F(":"));
Serial.print( b );
EEPROM.write( a, b );
Serial.println(F("."));
}
Serial.println(F("Reading from EEPROM : "));
for(uint16_t a=0; a<1024; a++)
{
byte b = DATA(a);
Serial.print( a );
Serial.print(F(":"));
Serial.print( b );
byte r = EEPROM.read( a );
if ( b != r )
{
Serial.print(F("<=== ERR : "));
Serial.print( r );
}
Serial.println(F("."));
}
}
void loop()
{
}
EDIT : extra notes regarding the way EEPROM works on LGT8F328p : how to disable EEPROM so we have the full 32KB of flash for the sketch ?the fake EEPROM can be disabled by setting bit 6 of the how to choose the size of the EEPROM ?the size of the EEPROM can be set using bits 0 and 1 of the
Note : the EEPROM size actually available to user is EEPROM size minus 2 bytes per 1KB page. TODO : verify that when the size of the emulated EEPROM is increased at run-time, the space of the EEPROM does not overlap with the space of the bootloader (I got the bootloader corrupted when I was playing with the size of the EEPROM). warning : dont confuse
|
Yes, the example above (but you must apply the modification to your Also, you can use my version of LarduinoISP with AVRdude in terminal mode to PS : regarding EEARH, it is the register of the EEPROM controller that stores the high part of the address to which we want to read or write. If we apply a 0x1 mask, the maximum addressable space is limited to 512. If we apply a 0x3 mask, the limit is 1024. |
Thanks for the explanation.
So, can we access 1024 bytes (like in your example) or not? |
You can read 1024 bytes, but you can write only 1020 bytes. (PS : if you apply my patch indeed ... else 512 rw) |
I tried your example from above. It writes from 0 to 1023 and reads from 0 to 1023. I'm not receiving any ERR. I did not apply the patch. I guess this is not the expected result without the patch right? I should get ERR after 512? |
Yes, if you don't apply the patch, writing from 512 to 1023 will overwrite 0 to 511. (that's because of the 0x1 bitmask in EEPROM.c which keeps the address rolling between 0 and 511). If you change That's also why some sketches directly ported from ATmega328p will not work if they expect 1024 bytes of EEPROM. |
Confirmed, after the |
first, you must understand that i wrote this example for when the patch is applied to show it is possible to actually write from 512 to 1020 or 1022, and that the two last bytes are used by the eeprom controller like it is explained into the datasheet. If you run this example without the patch, addresses from 512 to 1023 are bitmasked with 0x1FF by the inner code of I can't do better explanation. If you don't understand I'm sorry. |
Makes perfect sense now since the read is also affected the same way as the write. Thanks for the explanation. ✌🏻 |
Well, this afternoon I implemented a It was working, except that my bootloader got somehow corrupted. |
I'd think it would be sufficient when EEPROM size can be set at compile time. On a different note: Are you also planning adding template <class T> int EEPROM_put(int ee, const T& value)
{
const byte* p = (const byte*)(const void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++) EEPROM.write(ee++, *p++);
return i;
}
template <class T> int EEPROM_get(int ee, T& value)
{
byte* p = (byte*)(void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++) *p++ = EEPROM.read(ee++);
return i;
} Last not least, what about template <class T> void EEPROM_update(int ee, const T& value)
{
EEPROM.read(ee) != value ? EEPROM.write(ee, value) : delay(0);
} |
Agreed. Though I have absolutely no clue about how to make it possible, mainly because I've seen that the size of the EEPROM is defined into the bootloaders : https://github.com/dbuezas/lgt8fx/search?q=ECCR That's why I was thinking of making Also, AVRdude expect 1024 of EEPROM since the LGT8F328p pretends to be an ATmega328p.
Yes, the API of the LGT Access as array I'll try to add them tomorrow. |
I rewrote the whole EEPROM.h file to incorporate the full standard Arduino EEPROM API. The LGT EEPROM API will remain available using a I'm going to try to update this pull request with these changes .... |
@SuperUserNameMan That sounds awesome! |
- add support for standard Arduino EEPROM API - add C-like lgt_eeprom_xxxx() API - put everything into a single EEPROM.h header file - old projects can keep using the original LGT EEPROM API by defining USE_LGT_EEPROM_API - add comments documenting how EEPROM emulation works with LGT8F328p TODO : add better support for LGT8F8, LGT8F16, LGT8F328d and LGT8F328e ?
not useful anymore. Everything is into EEPROM.h
I've made some tests, but I think more testing are welcome. Also, since I'm updating Github using copy/paste, I hope everything is up to date ....... Here is a test of #include <EEPROM.h>
void setup()
{
Serial.begin(9600);
while(!Serial);
Serial.print(F("EEPROM size : ")); Serial.println( EEPROM.size() );
Serial.println(F("Writing using EEPROM[] = xx : "));
for( int a=0; a< EEPROM.size(); a++ )
{
EEPROM[a] = ((a>>4)&0xFF);
Serial.print(F("."));
if ( ( a % 64 ) == 63 ) Serial.println();
}
Serial.println("done");
Serial.println(F("Writing using EEPROM[]++ : "));
for( int a=0; a< EEPROM.size(); a++ )
{
EEPROM[a]++;
Serial.print(F("."));
if ( ( a % 64 ) == 63 ) Serial.println();
}
Serial.println("done");
Serial.println(F("Reading using --EEPROM[] : "));
int err = 0;
for( int a=0; a< EEPROM.size(); a++ )
{
if ( (--EEPROM[a]) == ((a>>4)&0xFF) )
{
Serial.print(F("."));
}
else
{
Serial.print(F("!"));
err++;
}
if ( ( a % 64 ) == 63 ) Serial.println();
}
if ( err )
{
Serial.print("Errors : ");
Serial.println( err );
}
else
{
Serial.println("OK");
}
}
void loop()
{
}
|
Fail.I tried to upload a simple blink skech before the EEPROM test, but brick the broard. Not working any more. And this is the second what I ruined. No effect on RESET or RESET with power on. LED lighting with half brightness. Amen. |
The Blink sketch brick your board ? or the EEPROM sketch ? |
BTW, there is a donations function in github, we could activate it specifically for the contributors to get 10 boards to brick while developing. |
so there are at least two possibilities: either a) something killed the bootloader and the half brightness LED is just due to the code going hay-wire or b) some important initialisation parameters (fuses?) might be located in "eeprom" ... |
The Blink sketch brick my board. After this happened, I tried to find more information about this red Wemos XI 1.0.0 board, but I found almost nothing. Strange thing is, when I view on Aliexpress a few sellers, all of these boards has no feedback at all. Only at one seller, in the Question section find this: So my idea is most of the the boards is a scam or without bootloader. |
I think ISP can not fix it. I tried to powerig up, while RESET was hold down, but the LED was lighting half bright while the RESET still pressed down. So it is dead. I already ordered a Massduino nano. |
Oh wow... maybe it internally shorted the pins that are connected to 2 ports. |
@LaZsolt : I see the XI board has a place to solder external oscillator. Could it be an issue with thedefault clock source or the clock speed ? if you have a spare Wemos XI, maybe you could try the official SDK to see if it works better ... |
@5chufti :
F88-A uses the last 8 bytes of its 512 eeprom as fuses. But Fx8-D datasheet make no mention of fuses (熔丝). |
@dbuezas : I think it's ready for review. I documented everything in the wiki. I trried to update the readme.md like you mentioned, with a "in next release : Arduino EEPROM API", but I failed : Github wanted me to make a separate pull requesst, so I let you do that if you want. Regarding compatibility with |
Wow @SuperUserNameMan. Just Wow. |
added mention to standard Arduino EEPROM API by SuperUserNameMan in #64
is eeprom ok for 328d?I can help you to test{only in 1020 bytes, no isp}.now I found it has 512 limit in 1.06 version with eeprom demo.the addr is reset to zero after 511. if I use your new code I must pay attention 1020 address limits if I dont wannt to destroy bootloader? |
The new EEPROM library still needs tests for 328d. But there might be an other unrelated bug with 328d : @LaZsolt and @jg1uaa mentioned issues when uploading the "Blink test" example to 328d.
With the new code, by default, you will be limited to 1020 bytes. The bootloader will be damaged ONLY if you increase the size of the EEPROM using But if you stick to default, there is nothing to worry about. (except maybe a bug into the new code). |
a bland new, first time do not why success
and then disconnexion reconnexion and press reset:
run clear demo and read demo, proved all zero.
write test again!
so the test is ok when the eeprom is clear.is this the test's bug or the lib's bug? write to a clear eeprom is ok, write to a dirty eeprom is wrong! 328p is not test. |
Well, I confirm there is at least one bug in the lib with the implementation of EEPROM.cpp, line 375 : void lgt_eeprom_writeSWM( uint16_t address, uint32_t *pdata, uint16_t len)
{
// Emulation :
lgt_eeprom_read_block( (uint8_t*)pdata, address, len*sizeof(uint32_t) );
}
void lgt_eeprom_readSWM( uint16_t address, uint32_t *pdata, uint16_t len)
{
// Emulation :
lgt_eeprom_read_block( (uint8_t*)pdata, address, len*sizeof(uint32_t) );
} This |
I opened a new PR : #129 |
@youxiaojie : Thanks for the tests already. This part of your test result here is bizarre :
It started the test, and it was interrupted quickly. Could you tell me what board and serial adapter you are using ? |
@youxiaojie : |
it is mostly because of mcu and wch340 are not using crystal there exist inaccuracy. Chip of usb-ttl, ch340,according to the ch340's engineer, the baud of ch340 to mcu is 1% tolerance; mcu to ch340 is 2% tolerance. when runing demo "characteranalysis" is obviously, sending from mcu to computer is all correct, but the received "input character" are bizarre. this situation is better in linux than in windows. maybe this is why the bootloader using 19200, a lower speed. I hope to test common communication in a high speed, to see is there bizarre. in the test, when the bizarre, I redo all, but the screen is not clear.copy and paste from the serial monitor. |
what is SWM here? |
@youxiaojie :
On the LGT8F328-P, it is the most optimized and fastest way to write a buffer to the EEPROM. SWM does not exist on LGT8Fx8-D. |
It was only possible to use 512 bytes of EEPROM despite space for
10241020 bytes was reserved.( Note that the EEPROM controler of the LGT8Fx32p will keep using 2048 bytes from the flash to store these 1024 bytes. )
PS : for more details, see explanations
in discussion belowIN THE DEDICATED WIKI PAGEUPDATE 20210208 : PLEASE HELP - MORE TESTING REQUIRED
TODO ( for me ) :
UPDATE 20201106 :
Agreeing with @seisfeld, I took this opportunity to add full support of the standard Arduino EEPROM API.
I've done some test, but you may want to test it more extensively and report eventual bugs.
Note about the old LGT EEPROM API :
By default, EEPROM will use the Arduino EEPROM API.
The old LGT EEPROM API remains available this way :
I've updated LGT EEPROM examples.
Note about the standard Arduino EEPROM API :
EEPROM.length()
will return the actual available size of the EEPROM, but you can also use theE2END
macro to get the last address of theEEPROM[]
.E2END
was normally defined into<AVR/io.h>
as an integer, but is now redefined as(lgt_eeprom_size()-1)
so it always match the current size of the emulated EEPROM.On LGT8F328p, the actual available size of the emulated EEPROM is 1020. (not 1024)
On LGT8F88a, it is 508 (not 512).
On LGT8Fx8e and LGT8Fx8d : TODO
The size of the emulated EEPROM can be changed at your own risks using :
void lgt_eeprom_init( uint8_t number_of_1KB_pages );
. (increasing the size of the emulated EEPROM will overwrite the bootloader if you use one, or a part of your program depending of its size).You can also use
EEPROM.change_size( uint8_t number_of_1KB_pages )
in the Arduino EEPROM API.Note : On LGT8Fx8a/e/d it will have no effect.
Because of the way EEPROM is emulated, if we increase the size of the emulated EEPROM to 2KB, 4KB or 8KB, every lasts 4 bytes of each 1KB blocks will be read only. Because of that, there will be "holes" into the continuous address space.
That's why I added an extra
bool real_address_mode = false
parameter to the 8bits read/write functions and methods of the C API and of the LGT EEPROM API.When this parameter is set to false (default), the address will be automatically recalculated to skip each one of these read-only 4 bytes.
So, by default, you don't have to care about these 4bytes holes into your EEPROM address space.
However, you have to keep in mind that because of these holes, the actual size of the available EEPROM is slightly smaller than what one would expect (1020 instead of 1024, 2040 instead of 2048, etc).
To know the available space of the EEPROM, you can use the
EEPROM.length()
method of the Arduino EEPROM API, or theEEPROM.size()
method of the LGT EEPROM API, or thelgt_eeprom_size()
of the C/C++ API.Also, the
E2END
macro, which was normally defined into<AVR/io.h>
, is redefiend to make use of thelgt_eeprom_size()
so it will always matches the current size of the emulated EEPROM if you change it usinglgt_eeprom_init()
.WARNING when changing the size of the emulated EEPROM :
The size of the emulated EEPROM can be changed anytime at run-time using
lgt_eepom_init( uint8_t number_of_1KB_pages = 1 )
.However, you have to keep in mind that the EEPROM emulation will take twice the size of the EEPROM from the end of the main Flash memory. This mean that increasing the size of the EEPROM might overwrite the bootloader and a part of your program.
The default bootloader is stored from
0x7400
to0x77ff
.So, increasing the size of the EEPROM above 1KB will overwrite this bootloader.
The only way to restore the bootloader is using an ISP.
But if you have an ISP, you don't need the bootloader anymore.