ATMEGA328P - AVRgcc, hoe zorg ik dat data in EEPROM komt

Hier kom ik even niet uit.
Een programma voor een ATMEGA328P, compileert en werkt.

Maar, hoe definieer ik een array van bytes die de compiler in een .EEP stopt zodat ik die ook kan programmeren (initiele waarden).

Wat ik ook probeer, ik blijf een "Firmware.eep" krijgen met deze inhoud :
:00000001FF

De normale route is dat je in C aangeeft dat die array in een sectie "eeprom" (oid) komt (met __attritbute(section,"eeprom") oid, giyf).

Daarna heb je een regeltje in je makefile die de eeprom-sectie uit de ELF haalt en in een aparte hex zet, en die kan AVRdude in de eeprom zetten.

Ik heb er 2 geprobeerd, die heb ik ook maar ergens gevonden :

__attribute__((section(".eeprom"))) uint8_t eepContent[6] = {0,1,0xFF,3,4,5};

en

static const uint16_t shutter1[] EEMEM = {
    // header
    0x8060, 0x0018,
    // data
    0x8030, 0x0018, 0x8018, 0x0018, 0x8030, 0x0018, 0x8030, 0x0018, // B
    0x8018, 0x0018, 0x8030, 0x0018, 0x8018, 0x0018, 0x8018, 0x0018, // 4
    0x8030, 0x0018, 0x8018, 0x0018, 0x8030, 0x0018, 0x8030, 0x0018, // B
    0x8030, 0x0018, 0x8018, 0x0018, 0x8018, 0x0018, 0x8018, 0x0018, // 8
    0x8030, 0x0018, 0x8030, 0x0018, 0x8030, 0x0018, 0x8030, 0x01c8, // F
    0x0000,
};

Daarna heb je een regeltje in je makefile die de eeprom-sectie uit de ELF haalt en in een aparte hex zet, en die kan AVRdude in de eeprom zetten.

Daar zal het vast mis gaan
Overigens heb ik (voor zover ik weet) in PlatformIO geen make file.

PlatformIO genereerd een makefile onder water.

Maar had je al in de documentatie van PlatformIO gekeken?

https://docs.platformio.org/en/latest/platforms/atmelavr.html#upload-e…

PlatformIO heeft ook een actief forum, waar veel specifieke kennis aanwezig is

Aanmaken van hexfile uit een elf file doe ik zo:


avr-objcopy -O ihex -j.eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 <Elf-File> <Eeprom-HexFile>

Ooit eens uitgezocht en nooit meer naar gekeken.

Op vrijdag 2 februari 2024 12:00:24 schreef blurp:
PlatformIO genereerd een makefile onder water.

Maar had je al in de documentatie van PlatformIO gekeken?

https://docs.platformio.org/en/latest/platforms/atmelavr.html#upload-e…

PlatformIO heeft ook een actief forum, waar veel specifieke kennis aanwezig is

Ja had ik gekeken (maar ook iets met bomen en bos), en hij genereert ook een .eep file, maar er staat verder niets in.

Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/ATmega328.html
PLATFORM: Atmel AVR (5.0.0) > ATmega328
HARDWARE: ATMEGA328 16MHz, 2KB RAM, 32KB Flash       
DEBUG: Current (avr-stub) External (avr-stub, simavr)
PACKAGES:
 - framework-arduino-avr-minicore @ 3.0.0
 - toolchain-atmelavr @ 1.70300.191015 (7.3.0)       
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 8 compatible libraries
Scanning dependencies...
Dependency Graph
|-- Wire @ 1.1  
|-- EEPROM @ 2.0
Building in release mode
Compiling .pio\build\program_via_ArduinoISP\src\main.cpp.o
Compiling .pio\build\program_via_ArduinoISP\libd24\Wire\Wire.cpp.o
Compiling .pio\build\program_via_ArduinoISP\libd24\Wire\utility\twi.c.o
Archiving .pio\build\program_via_ArduinoISP\libFrameworkArduinoVariant.a
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\CDC.cpp.o
src\main.cpp: In function 'void DumpEEPROM()':
src\main.cpp:287:8: warning: unused variable 'EEPROMChecksum' [-Wunused-variable]
    int EEPROMChecksum = 0;
        ^~~~~~~~~~~~~~
Archiving .pio\build\program_via_ArduinoISP\libd24\libWire.a
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\HardwareSerial.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\HardwareSerial0.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\HardwareSerial1.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\HardwareSerial2.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\HardwareSerial3.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\IPAddress.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\PluggableUSB.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\Print.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\Stream.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\Tone.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\USBCore.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\WInterrupts.c.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\WMath.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\WString.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\abi.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\hooks.c.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\main.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\new.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\wiring.c.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\wiring_analog.c.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\wiring_digital.c.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\wiring_extras.cpp.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\wiring_pulse.S.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\wiring_pulse.c.o
Compiling .pio\build\program_via_ArduinoISP\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\program_via_ArduinoISP\libFrameworkArduino.a
Linking .pio\build\program_via_ArduinoISP\firmware.elf
[b]Building .pio\build\program_via_ArduinoISP\firmware.eep[/b]
Checking size .pio\build\program_via_ArduinoISP\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [====      ]  37.0% (used 757 bytes from 2048 bytes)
Flash: [==        ]  15.2% (used 4968 bytes from 32768 bytes)
Building .pio\build\program_via_ArduinoISP\firmware.hex

Ik los het nu op door te controleren of er data in de EEPROM staat zo niet schrijf ik het er in via mijn programma.

Dat is het leuke met die geintegreerde omgevingen. Als het niet werkt heb je geen enkele clue waar het misgaat.

Je zou een aparte "uploadeep" target moeten hebben. Wat doet die?

EDIT: je wil dit ook effe lezen denk ik:
https://community.platformio.org/t/eep-file-empty-unless-also-read/264…

[Bericht gewijzigd door blurp op (25%)]

Hier wat help: https://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

Maar dat had je waarschijnlijk al gelezen.

Of dit: https://www.edaboard.com/blog/write-read-the-internal-eeprom-in-avr-us…

if you want to store some data in the eeprom when you compile the code (so they are added to the eep file and use them to fill the avr eeprom when you program the device),
you need to use the EEMEM and initialize it with a value like the following example:

Code:

//

uint8_t EEMEM eeprombyte=0x10;		[COLOR="red"]//store initial byte to eeprom, eep file will include this[/COLOR]

uint16_t EEMEM eepromword=0x5555;	[COLOR="red"]//store initial word to eeprom, eep file will include this[/COLOR]

uint8_t EEMEM eepromstring[5]={"Test\0"}; 	[COLOR="red"]//store string to eeprom, eep file will include this[/COLOR]

int main(void)
{
 uint8_t RAMbyte;		//RAM byte variable
 uint16_t RAMword;		//RAM word variable
 uint8_t RAMstring[5];		//RAM array of bytes

 RAMbyte = read_eeprom_byte(&eeprombyte);	    //read byte from EEPROM and store to RAM 
 RAMword = read_eeprom_word(&eepromword);	    //read word from EEPROM and store to RAM
 read_eeprom_array(&eepromstring,&RAMstring,5);		//copy string from EEPROM to RAM
....
}

Groetjes,
eSe

[Bericht gewijzigd door eSe op (79%)]

ofwel volatile declareren. Doe dit ook altijd met variabelen die je enkel in ISR's schrijft en in de main loop uitleest. De compiler zit geen enkele gerelateerde call naar de ISR functie en denk dus, die variabele wordt toch nergens geschreven. vervang die maar door een constant. Wellicht zijn modernere compilers iets slimmer en kijken iets verder dan hun neus lang is, maar bij de avr compilers die ik hebt gebruikt (IAR en gcc) was dit altijd het geval

Volatile gaat nog verder dan alleen optimalisatie voor constanten.

Voorbeeld:


uint8_t teller;

ISR isr_routine() {
  teller++;
}

void main() {
  teller = 0;
  while(1) {
    if(teller==10) {
      prinftf("Hoera");
      teller = 0;
    }
    sleep_ms(1000);
    teller++;
  }
}

De compiler zal de teller-variabele niet weg-optimaliseren, want de main() code gebruikt en veranderd hem.

Maar als de ISR en main in verschillende C-files staan kan de compiler niet weten dat ze dezelfde variabele veranderen. En kan de compiler dus besluiten dat in de while-loop teller in een processor-register geplaatst kan worden.

Volatile verteld de compiler dat teller elke instructie anders kan zijn. En dus niet in een register mag.

Wat zijn de voordelen van het gebruik van PlatformIO t.o.v. Atmel Studio?

Op vrijdag 2 februari 2024 21:42:10 schreef Bobosje:
Wat zijn de voordelen van het gebruik van PlatformIO t.o.v. Atmel Studio?

https://dronebotworkshop.com/platformio/

Voor mij persoonlijk deze :
Visual Studio Code includes IntelliSense, an advanced auto-complete and syntax highlighting system that can assist you in creating better code without errors. This allows you to catch and correct coding errors before you compile your code.

Maar ik kom dan ook niet van Atmel Studio maar van Arduino IDE

ik ben daar destijds zelf ook niet aan uit geraakt en heb daar zelf een instructie voor geschreven.


 if (EEPROM.read(0)!=88){
    Serial.println("eeprom is empty, write new eeprom");
    writeEeprom(279,566,50,65,75,1000);  //default data
  }

en de "writeEeprom" code heeft als 1e instructie
EEPROM.write(0, 88);

als mijn programma draait, en die leest als eerste geheugenplaats GEEN 88 in, dan schrijft die alle default waardes in het geheugen. en start dan default op. in een menu structuur kan je dan wel waardes gaan aanpassen en die worden dan weer met die writeEeprom weggeschreven
bv
writeEeprom(200,800,55,65,75,1000);

steek ik die code in een nieuwe arduino, dan zal die zijn geheugen plaats ook weer de default waardes geven bij de eerste startup en werkt alles out of the box.

die ESP dingen dat ik nu gebruik, die werkt met een file structuur (filefs of zoiets). telkens ik de code aanpas en upload, moet ik ook die files altijd opnieuw uploaden. ga ik ook eens iets op uitzoeken, zou die bij de eerste run een path willen geven dat die ze standaard download)

[Bericht gewijzigd door fcapri op (15%)]

Ik gebruik liever EEPROM.put(x, y) dan wordt de waarde alleen geschreven als ze gewijzigd is. Hoef je niet zelf te kijken of een waarde wijzigt voor je schrijft.

LittleFS of FATFS (SPIFFS is deprecated) blijven die niet bestaan als je kiest alleen de code te wijzigen? De WiFi gegevens van WiFiManager blijven alleszins bestaan.

Default data in je code steken is goed als het geen al te grote hoeveelheid is. Anders vergroot het alleen je programma.

Visual Studio is wat mij betreft een draak van een programma. Helemaal niet intuïtief. Een tijd bezig geweest met CLION van JetBrains. Ook een Platformio variant. Maar dan krijg ik massa's foutmeldingen voor code fouten in de libraries. Als ik die allemaal moet rechtzetten ben ik dagen bezig. CLION is heel strikt in de code regels. Momenteel werkt de Arduino 2.x omgeving behoorlijk goed. Alleen kan je daar weer geen LittleFS of FATFS mee uploaden. Maar dat kan dan weer wel via browser en de update manager.

Visual Studio is wat mij betreft een draak van een programma. Helemaal niet intuïtief.

Intuiitief is denk ik net als beauty : "In the eye of the beholder". Velen hier vinde Eagle voor PCB intuitief, dat is mij nooit gelukt terwijl ik met Protel en nu Kicad aardig uit de voeten kan.

Of misschien scheelt het dat ik voor mijn werk.hobby af en toe al Microsoft Visual studio (BASIC) gebruik.

Overigens is "Visual Studio Code" in basis geen ontwikkel omgeving maar alleen een intelligente editor.
https://code.visualstudio.com/

Op zaterdag 3 februari 2024 06:47:37 schreef fcapri:
ik ben daar destijds zelf ook niet aan uit geraakt en heb daar zelf een instructie voor geschreven.


 if (EEPROM.read(0)!=88){
    Serial.println("eeprom is empty, write new eeprom");
    writeEeprom(279,566,50,65,75,1000);  //default data
  }

en de "writeEeprom" code heeft als 1e instructie
EEPROM.write(0, 88);

als mijn programma draait, en die leest als eerste geheugenplaats GEEN 88 in, dan schrijft die alle default waardes in het geheugen. en start dan default op. in een menu structuur kan je dan wel waardes gaan aanpassen en die worden dan weer met die writeEeprom weggeschreven
bv
writeEeprom(200,800,55,65,75,1000);

steek ik die code in een nieuwe arduino, dan zal die zijn geheugen plaats ook weer de default waardes geven bij de eerste startup en werkt alles out of the box.

die ESP dingen dat ik nu gebruik, die werkt met een file structuur (filefs of zoiets). telkens ik de code aanpas en upload, moet ik ook die files altijd opnieuw uploaden. ga ik ook eens iets op uitzoeken, zou die bij de eerste run een path willen geven dat die ze standaard download)

Zo los ik het nu ook (tijdelijk ?) op.

Op vrijdag 2 februari 2024 22:33:23 schreef bprosman:
[...]

https://dronebotworkshop.com/platformio/

Voor mij persoonlijk deze :
Visual Studio Code includes IntelliSense, an advanced auto-complete and syntax highlighting system that can assist you in creating better code without errors. This allows you to catch and correct coding errors before you compile your code.

Maar ik kom dan ook niet van Atmel Studio maar van Arduino IDE

Heeft PlatformIO ook ondersteuning voor de verschillende AVR (JTAG) debuggers zoals dat Atmel Studio heeft voor o.a. het plaatsen van software / hardware breakpoints in je code tijdens debuggen bijvoorbeeld?

Op vrijdag 2 februari 2024 21:42:10 schreef Bobosje:
Wat zijn de voordelen van het gebruik van PlatformIO t.o.v. Atmel Studio?

PlatformIO werkt ook voor ESP32, STM32, RP2040 en nog een paar. Dus je hoeft maar een enviroment te gebruiken. En het heeft een actieve gebruikers/developers community waar je met vragen terecht kunt.

Visual Studio Code is een editor die vaak in combinatie met PlatformIO gebruikt word, maar het staat er in principe los van.

Visual Studio Code staat ook los van Visual Studio.

Ik ben er zelf wel van te spreken want met Visual Studio Code kan ik:
- C code maken voor ESP32
- Python code maken voor Windows
- Lambda functies maken voor Amazon
- Op Windows
- Op Linux

En dat allemaal in een omgeving, die altijd en overal hetzelfde is, en de beste intelli-sense ondersteuning heeft die ik ooit gezien heb (beter dan Visual Studio (waar Atmel Studio op gebaseerd is), of Eclipse (waar ST's ontwikkelomgeving op gebaseerd is)

Op zaterdag 3 februari 2024 11:38:52 schreef Bobosje:
[...]

Heeft PlatformIO ook ondersteuning voor de verschillende AVR (JTAG) debuggers zoals dat Atmel Studio heeft voor o.a. het plaatsen van software / hardware breakpoints in je code tijdens debuggen bijvoorbeeld?

Yep

Heb je om te kunnen debuggen (al dan niet via JTAG) een PlatformIO Account nodig (zoiets lees ik op de site) of werkt alles in PlatformIO zonder Account?

Alles kan zonder account. Allen om te posten op het PlatformIO forum heb je een account nodig.

Op zaterdag 3 februari 2024 08:16:04 schreef buckfast_beekeeper:
LittleFS of FATFS (SPIFFS is deprecated) blijven die niet bestaan als je kiest alleen de code te wijzigen? De WiFi gegevens van WiFiManager blijven alleszins bestaan.

Default data in je code steken is goed als het geen al te grote hoeveelheid is. Anders vergroot het alleen je programma.

data is bij mij altijd weg (html paginas).
de data size valt ook wel mee met arduino. denk dat uno/nano maar 512 of 1024 bytes kunnen opslaan.
programma code mag 32K zijn, dus die gegevens in de code maakt weinig uit. ik gebruik ze toch maar voor instel variabele in op te slaan en hoef dan geen speciale handelingen te doen met een vervang arduino

Op vrijdag 2 februari 2024 13:48:25 schreef blurp:
En dus niet in een register mag.

Dat gaat net te ver. Omdat moderne CPUs niet meer "memory instructies" hebben, maar alleen load/store, MOET een variabele soms wel in een register.

Een teller++ bijvoorbeeld is op een moderne processor iets als:

   ld teller, r0
   inc r0
   st r0, teller

Als bewijs heb ik twee test-functies gecompileerd die een externe variabele ophogen, een volatile de andere niet:


testa:
        endbr64
        addl    $1, vara(%rip)
        ret
testb:
        endbr64
        movl    varb(%rip), %eax
        addl    $1, %eax
        movl    %eax, varb(%rip)
        ret

Dit is op een 64bit x86. (ik weet niet wat endbr64 is of doet). Anyway, je ziet dat een CISC dus nog wel memory instructies heeft: Hij kan de vara variabele in memory ophogen. Maar je ziet dus ook wat op een RISC niet anders kan: laad in register, ophogen en weer wegschrijven.
En dan de kicker:

extern int vara;
extern volatile int varb;

void testa (void)
{
vara++;
}
void testb (void)
{
varb++;
}

Op x86-64 kan je maar beter de variabele NIET als volatile declareren....
Op arm genereert hij identieke code voor beide functies.

edit: Voor degenene die niet vaker met dit bijltje gehakt hebben: als je een interrupt krijgt tussen het laad-variabele-in-register en het weer wegschrijven... ben je de sjaak. Dit vooral als de teller ook in de interrupt verandert wordt. Stel dit is "ruimte-in-de-buffer". ISR stopt er wat in, verlaagt de variabele, maincode haalt er wat uit en verhoogt hem. Als de ISR hem dan verlaagt terwijl de variabele in de maincode in het register verblijft omm opgehoogd te gaan worden... Tja, dan is er een verlaging die verloren gaat.

ZELFS met volatile declaraties mag je NOOIT vanuit twee plekken (ISR/MAIN) in 1 variabele schrijven. OF in de ISR schrijven en in main alleen lezen, of andersom.

[Bericht gewijzigd door rew op (21%)]

Wat Blurp m.i. bedoelt, is dat de compiler die variabele niet vanuit een register mag hergebruiken, en echt elke lees- en schrijfactie van en naar het geheugen moet doen. Als je dat niet doet, kan de compiler die variabele in een register houden, en pas veel later, of zelfs helemaal niet, naar het geheugen schrijven. Als je alleen een simpele loop hebt, besluit de compiler "die variabele heb ik nog van daarnet, dus het is zinloos om die opnieuw uit het geheugen te lezen", omdat hij niet weet dat die variabele in de tussentijd door een ISR veranderd kan zijn.