## c't-Projekte - Mailinglisten

[Voriger (Datum)] [Nächster (Datum)] [Voriger (Thread)] [Nächster (Thread)]
[Nach Datum][Nach Thread]

### Re: AW: AW: [ct-bot] EEPROM-Emu... -> Bug gefunden !

Absender: Achim Pankalla
Datum: Mo, 17.09.2007 19:01:53
In-reply-to: <46EC2190.1060306@xxxxxx>
References: <000601c7f702$605cacb0$fe78a8c0@mexpnew> <FAAB09B3-2B6D-4A53-96F7-3AEAF1C2563E@xxxxxxxxxxxxxxx> <46EC2190.1060306@xxxxxx>

    hallo,
    hier nun das update für die eeprom-emulation. :-)

`bei einen modus-wechsel wird nun die datei des alten modus gelöscht und` `eine neue, gültige, angelegt. da die debug-ausgaben, an der man den` `erreichten modus erkennen kann, normalerweise aus sind. habe ich es so` `geändert, das man für jeden modus einen dateinamen angeben kann.` `vorgegeben sind mcu_eeprom.bin und pc_eeprom.bin. das macht es doch` `schön offensicht, im welchen modus die emulation ist oder ? ;-)`

    anbei auch die angepasste docu.

    Mit freundlichen Grüßen

    achim

    Index: E:/eclipse/ct-bot devel/ct-Bot/pc/eeprom-emu_pc.c
    ===================================================================
    --- E:/eclipse/ct-bot devel/ct-Bot/pc/eeprom-emu_pc.c	(revision 1247)
    +++ E:/eclipse/ct-bot devel/ct-Bot/pc/eeprom-emu_pc.c	(working copy)
    @@ -1,510 +1,518 @@
    -/*
    - * c't-Bot
    - *
    - * This program is free software; you can redistribute it
    - * and/or modify it under the terms of the GNU General
    - * Public License as published by the Free Software
    - * Foundation; either version 2 of the License, or (at your
    - * option) any later version.
    - * This program is distributed in the hope that it will be
    - * useful, but WITHOUT ANY WARRANTY; without even the implied
    - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    - * PURPOSE. See the GNU General Public License for more details.
    - * You should have received a copy of the GNU General Public
    - * License along with this program; if not, write to the Free
    - * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    - * MA 02111-1307, USA.
    - *
    - */
    -
    -/*!
    - * @file 	eeprom-emu_pc.c
    - * @brief 	Low-Level Routinen fuer den Zugriff auf das emulierte EEPROM des Sim-c't-Bots
    - * @author 	Achim Pankalla (achim.pankalla@xxxxxx)
    - * @date 	07.06.2007
    - */
    -
    -//	Post-Build AVR:
    -//	avr-objcopy -O ihex -R .eeprom ct-Bot.elf ct-Bot.hex; avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex ct-Bot.elf ct-Bot.eep; avr-size ct-Bot.elf; avr-objdump -t ct-Bot.elf | grep "O \.eeprom" >  eeprom_mcu.map
    -
    -//	Post-Build Linux:
    -//	objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary ct-Bot.elf ct-Bot.eep; objdump -t -j .eeprom -C ct-Bot.elf | grep "g" > eeprom_pc.map
    -
    -//	Post-Build Mac OS X:
    -//	objcopy -j LC_SEGMENT.__DATA..eeprom --change-section-lma LC_SEGMENT.__DATA..eeprom=0 -O binary ct-Bot ct-Bot.eep; objdump -t -j LC_SEGMENT.__DATA..s2eeprom -C ct-Bot | grep "g" > eeprom_pc.map
    -
    -//	Post-Build Windows:
    -//	objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary ct-Bot.exe ct-Bot.eep;objdump -t ct-Bot.exe | grep "(sec  5)" | grep "(nx 0)" > eeprom_pc.map
    -
    -
    -#include "ct-Bot.h"
    -
    -#ifdef PC
    -
    -#include <stdlib.h>
    -#include <stdio.h>
    -#include <string.h>
    -
    -#include "log.h"
    -#include "gui.h"
    -
    -//#define DEBUG_EEPROM		// Schalter um LOG-Ausgaben anzumachen
    -
    -#ifndef DEBUG_EEPROM
    -	#undef LOG_INFO
    -	#define LOG_INFO(a, ...) {}
    -#endif
    -
    -extern uint8 __attribute__ ((section (".s1eeprom"),aligned(1))) _eeprom_start1__;
    -extern uint8 __attribute__ ((section (".s2eeprom"),aligned(1))) _eeprom_start2__;
    -
    -/*! Normiert PC EEPROM Adressen*/
    -#define EEPROM_ADDR(x) ((uint32)x - (uint32)&_eeprom_start2__ - ((uint32)&_eeprom_start2__ - (uint32)&_eeprom_start1__))
    -/*! Makros zum Mitloggen von EEPROM Zugriffen*/
    -#define LOG_LOAD 	if(addrconv) {LOG_DEBUG("LOAD:%s : %u", ctab[lastctabi].varname, eeprom[address]);}\
    -					else {LOG_DEBUG("load-addr=0x%x/%u", address, eeprom[address]);}
    -#define LOG_STORE 	if(addrconv) {LOG_DEBUG("STORE:%s : %d", ctab[lastctabi].varname, value);}\
    -					else {LOG_DEBUG("load-addr=0x%x/%d", address, value);}
    -
    -/*! Positionen der Daten in den Map-Dateien */
    -#ifdef WIN32
    -	#define SADDR_POS 54	/*!< Pos. der Adresse in PC Map Datei */
    -	#define SNAME_POS 60	/*!< Pos. des Variablennamen ohne _ */
    -	#define BADDR_POS  0	/*!< Pos. der Adresse in MCU Map Datei */
    -	#define BNAME_POS 34	/*!< Pos. des Variablennamen in MCU Map */
    -	#define BSIZE_POS 28	/*!< Pos. der Variablengroesse in MCU Map */
    -#endif
    -#ifdef __linux__
    -	#define SADDR_POS  0	/*!< Pos. der Adresse in PC Map Datei */
    -	#define SNAME_POS 46	/*!< Pos. des Variablennamen ohne _ */
    -	#define BADDR_POS  0	/*!< Pos. der Adresse in MCU Map Datei */
    -	#define BNAME_POS 34	/*!< Pos. des Variablennamen in MCU Map */
    -	#define BSIZE_POS 28	/*!< Pos. der Variablengroesse in MCU Map */
    -#endif
    -#ifdef __APPLE__
    -	#define SADDR_POS  0	/*!< Pos. der Adresse in PC Map Datei */
    -	#define SNAME_POS 45	/*!< Pos. des Variablennamen ohne _ */
    -	#define BADDR_POS  0	/*!< Pos. der Adresse in MCU Map Datei */
    -	#define BNAME_POS 34	/*!< Pos. des Variablennamen in MCU Map */
    -	#define BSIZE_POS 28	/*!< Pos. der Variablengroesse in MCU Map */
    -#endif
    -
    -#ifdef __AVR_ATmega644__  // Dieser Prozessor hat 2048 Bytes EEPROM
    -	#define EE_SIZE 2048
    -#else
    -	#define EE_SIZE 1024
    -#endif
    -
    -#define EEPROM_FILENAME	"./eeprom.bin" 		/*!< Name und Pfad der EEPROM Datei. Verzeichnis muss existieren. Backslash doppeln!*/
    -#define MAX_VAR 200  						/*!< Maximale Anzahl von Variablen*/
    -#define EEMAP_PC  "./eeprom_pc.map"			/*!< Pfad fuer PC-MAP Datei */
    -#define EEP_PC    "./ct-Bot.eep"			/*!< Pfad fuer PC-EEP Datei */
    -#ifdef WIN32
    -	/* Windows */
    -	#define EEMAP_MCU "../debug-mcu-w32/eeprom_mcu.map"		/*!< Pfad fuer MCU MAP Datei */
    -#else
    -	/* Linux und OS X */
    -	#define EEMAP_MCU "../Debug-MCU-Linux/eeprom_mcu.map"	/*!< Pfad fuer MCU MAP Datei */
    -#endif
    -
    -typedef struct addrtab {
    -	char varname[30];
    -	size_t simaddr;
    -	size_t botaddr;
    -	uint16_t size;
    -//	uint32 access;	// ??? wird nie ausgewertet
    -} AddrCTab_t;								/*!< Spezieller Datentyp fuer Adresskonvertierung */
    -
    -static AddrCTab_t ctab[MAX_VAR]; 			/*!< Adresskonvertierungstabelle */
    -static uint16 tsize=0; 						/*!< Anzahl Eintraege in der Tabelle */
    -static uint16 esize=0;						/*!< Summe der EEPROM Variablen */
    -static uint8 addrconv = 0;                  /*!< Adresskonvertierung ein-/ausschalten */
    -static uint16 lastctabi = 0;                /*!< Letzter Zugriffsindex auf ctab */
    -static uint8 eeprom[EE_SIZE];               /*!< EEPROM Speicher im RAM */
    -static FILE * ee_file;						/*!< Zeiger auf EEPROM-Datei */
    -
    -/*!
    - * Diese Funktion konvertiert die Adressen der EEPROM Variablen des PC so,
    - * dass sie den Adressen im realen ct-Bot entsprechen. Dafuer wird mit der Funktion
    - * create_ctab ein Adresstabelle angelegt, diese nutzt diese Funktion.
    - * @param addr	Adresse im EEPROM zwischen 0 und EE_SIZE-1
    - * @return 		Die neue Adresse fuer den realen Bot
    - */
    -static uint32 conv_eeaddr(uint32 addr){
    -	int8 i;
    -	int32 adiff;
    -
    -	if(!addrconv) //Keine Adresskonvertierung
    -		return(addr);
    -	for(i=0; i<tsize; i++){
    -		adiff = addr - ctab[i].simaddr;
    -		if(adiff < 0)
    -			return(0xfffffffe);
    -		if(adiff < ctab[i].size){
    -			lastctabi = i; //Letzer guelten Index merken
    -			return(ctab[i].botaddr + adiff);
    -		}
    -	}
    -	return(0xffffffff);
    -}
    -
    -/*!
    - * Diese Funktion uberprueft das vorhanden sein der eeprom.bin und initialisiert sie
    - * gegebenenfalls mit der Initwerten der eep Datei.
    - * Es wird dabei die Adresskovertierung benutzt, wenn die EEPROM Simulation im MCU-Modus
    - * ist.
    - * -----
    - *  0 = EEPROM Datei OK
    - *  1 = Fehler aufgetreten
    - * -----
    - * @param initfile		EEP-Datei des PC Codes
    - * @param eeprom_init	Flag fuer Initialisierung (1 ja, 0 nein)
    - * @return 				Status der Funktion
    - */
    -static uint16 check_eeprom_file(char *initfile, uint8_t eeprom_init){
    -	FILE *fpr, *fpw; //Filepointer fuer Dateizugriffe
    -	uint16 i; //Laufvariable
    -	char data[2]; //Datenspeicher
    -
    -	/*eeprom file vorhanden*/
    -	if(!(fpw = fopen(EEPROM_FILENAME, "r+b"))){ //Testen, ob Datei vorhanden ist.
    -		if(!(fpw = fopen(EEPROM_FILENAME, "w+b"))){ //wenn nicht, dann erstellen
    -			LOG_INFO("->Kann EEPROM-Datei nicht erstellen");
    -			return(1);
    -		}
    -		if(!addrconv) {
    -			/* EEPROM mit .eeprom-Section des .elf-Files initialisieren, wenn PC Modus */
    -			uint8_t * ram_dump = (uint8_t *)(&_eeprom_start2__ + (&_eeprom_start2__ - &_eeprom_start1__));
    -			fwrite(ram_dump, EE_SIZE, 1, fpw);
    -		} else {
    -			/* alternativ: leeres EEPROM erstellen und init setzen bei MCU Modus*/
    -			for(i = 0; i < EE_SIZE; i++)
    -				fwrite("\377", 1, 1, fpw);
    -			eeprom_init = 1;
    -		}
    -
    -		fclose(fpw);
    -		LOG_INFO("->Leere EEPROM-Datei erstellt");
    - 	}
    -
    -	/*Initialsieren der eeprom.bin, wenn gewuenscht*/
    -	if(eeprom_init){
    -		if(!(fpr = fopen(initfile, "rb"))){ //Datei oeffnen
    -			LOG_INFO("->EEP nicht gefunden");
    -			return(1);
    -		}
    -		if(!(fpw = fopen(EEPROM_FILENAME, "rb+"))){ //Datei oeffnen
    -			LOG_INFO("->EEPROM-Datei kann nicht beschrieben werden");
    -			return(1);
    -		}
    -
    -		/*EEP-Datei in EEPROM-Datei kopieren*/
    -		for(i=0; i<EE_SIZE; i++){
    -			/*Daten kopieren*/
    -			if(!fread(data, 1, 1, fpr))
    -				break;
    -			if(addrconv){ //EEPROM-Datei im MCU-Modus
    -				uint32 naddr;//Konvertierte Adresse
    -
    -				naddr = conv_eeaddr((uint32)i);
    -				if(naddr < 0xfffffffe){
    -					fseek(fpw, (int32)naddr, SEEK_SET);
    -				}
    -				else{
    -					continue; //Nichts schreiben Adresse nicht belegt
    -				}
    -			}
    -			fwrite(data, 1, 1, fpw);
    -		}
    -		fclose(fpr);
    -		fclose(fpw);
    -		LOG_INFO("->EEPROM-Datei mit Daten init.");
    -	}
    -	return(0);
    -}
    -
    -/*!
    - * Diese Funktion erstellt aus den beiden im Post erstellten MAP Dateien eine Tabelle
    - * zum umrechnen der PC-Adressen in die des avr-Compilers. Dadurch kann die EEPROM
    - * Datei in einen zum EEPROM des Bot kompatiblen Format gehalten werden.
    - * Wichtige Informationen werden ueber LOG_INFO angezeigt.
    - * ----
    - * Ergebniscodes der Funktion
    - * 0 = Fehlerfrei
    - * 1 = Sim Mapfile nicht vorhanden
    - * 2 = Bot Mapfile nicht vorhanden
    - * 3 = Unterschiedlicher Variablenbestand
    - * 4 = Zuviele Variablen
    - * 5 = EEPROM voll
    - * 6 = Unterschiedliche Variablenanzahl
    - *
    - * @param simfile	MAP mit den Adressen der EEPROM-Variablen in der PC exe/elf
    - * @param botfile	MAP mit den Adressen der EEPROM-Variablen im MCU elf
    - * @return 			Statuscode
    - */
    -static uint16 create_ctab(char *simfile, char *botfile){
    -	FILE *fps, *fpb;
    -	char sline[250], bline[250]; //Textzeilen aus Dateien
    -	char vname_s[30], vname_b[30]; //Variablennamen
    -	size_t addr_s, addr_b; //Adressen der Variablen
    -	uint16_t size; //Variablengroesse
    -	uint16 vc = 0; //Variablenzaehler
    -	size_t first_botaddr = 0xffffffff; //Erste ct-bot EEPROM Adressse
    -
    -	/*Dateien oeffnen*/
    -	if(!(fps=fopen(simfile,"r"))){
    -		LOG_INFO("->EEPROM-MAP fuer PC fehlt");
    -		return(1);
    -	}
    -	if(!(fpb=fopen(botfile,"r"))){
    -		LOG_INFO("->EEPROM-MAP fuer MCU fehlt");
    -		return(2);
    -	}
    -
    -	/*Anzahl Variablen vergleichen*/
    -	while(fgets(sline, 249, fps)) vc++;
    -	while(fgets(sline, 249, fpb)) vc--;
    -	if(vc){
    -		fclose(fps);
    -		fclose(fpb);
    -		LOG_INFO("->Unterschiedliche Variablenanzahl");
    -		return(6);
    -	}
    -	rewind(fps);
    -	rewind(fpb);
    -
    -	/*Tabelle erstellen*/
    -	while(fgets(sline, 249, fps)){
    -		rewind(fpb);
    -		sscanf(&sline[SNAME_POS], "%s", vname_s);
    -//		printf("vname_s=%s\n", vname_s);
    -		addr_s = strtol(&sline[SADDR_POS], NULL, 16);
    -//		printf("addr_s=0x%lx\n", addr_s);
    -		while(fgets(bline, 249, fpb)){
    -			/*Variablennamen suchen*/
    -			sscanf(&bline[BNAME_POS], "%s", vname_b);
    -//			printf("vname_b=%s\n", vname_b);
    -			addr_b = strtol(&bline[BADDR_POS], NULL, 16);
    -//			printf("addr_b=0x%lx\n", addr_b);
    -			if(addr_b < first_botaddr)//Kleinste ct-bot Adresse bestimmen
    -				first_botaddr = addr_b;
    -			size = strtol(&bline[BSIZE_POS], NULL, 16);
    -//			printf("size=0x%x\n", size);
    -
    -			if(!strcmp(vname_s, vname_b)){
    -				/*Daten kopieren*/
    -				strcpy(ctab[tsize].varname, vname_b);
    -				ctab[tsize].simaddr = addr_s;
    -				ctab[tsize].botaddr = addr_b;
    -				ctab[tsize++].size    = size;
    -				//ctab[tsize++].access  = 0;	// ??? wird nie ausgewertet
    -				esize += size;
    -				/*Fehlerabbrueche*/
    -				if(tsize == MAX_VAR){
    -					LOG_INFO("->Mehr als %n Variablen",MAX_VAR);
    -					return(4);
    -				}
    -				if(esize > EE_SIZE){
    -					LOG_INFO("->EEPROM voll");
    -					return(5);
    -				}
    -
    -				/*Erfolg markieren*/
    -				addr_b = -1;
    -				break;
    -			}
    -		}
    -		if(addr_b > -1){ //Keine passende Variable gefunden
    -			LOG_INFO("->Unterschiedliche Variablen");
    -			return(3);
    -		}
    -	}
    -
    -	/*Dateien schliessen*/
    -	fclose(fps);
    -	fclose(fpb);
    -
    -	/*Tabelle nach Sim-Adressen sortieren*/
    -	uint16_t i, j;
    -	for(j=tsize-1; j > 0; j--){
    -		for(i=0; i < j; i++){
    -			if(ctab[i].simaddr > ctab[i+1].simaddr){
    -				size_t simaddr, botaddr, size;
    -				char vname[30];
    -
    -				/*Daten umkopieren*/
    -				strcpy(vname, ctab[i+1].varname);
    -				simaddr = ctab[i+1].simaddr;
    -				botaddr = ctab[i+1].botaddr;
    -				size    = ctab[i+1].size;
    -
    -				strcpy(ctab[i+1].varname, ctab[i].varname);
    -				ctab[i+1].simaddr = ctab[i].simaddr;
    -				ctab[i+1].botaddr = ctab[i].botaddr;
    -				ctab[i+1].size    = ctab[i].size;
    -
    -				strcpy(ctab[i].varname, vname);
    -				ctab[i].simaddr = simaddr;
    -				ctab[i].botaddr = botaddr;
    -				ctab[i].size    = size;
    -			}
    -		}
    -	}
    -
    -	/*Die EEPROM-Startadressen vom ct-bot und/oder Ct-Sim auf Null normieren*/
    -	size_t first_simaddr = ctab[0].simaddr;
    -	if(first_simaddr || first_botaddr) {
    -		LOG_INFO("->Adressen werden normiert");
    -		for(i=0; i<tsize; i++){
    -			if(first_simaddr) ctab[i].simaddr -= first_simaddr;
    -			if(first_botaddr) ctab[i].botaddr -= first_botaddr;
    -//			printf("addr_b=0x%x addr_b=0x%x\n", ctab[i].botaddr, ctab[i].simaddr);
    -		}
    -	}
    -
    -//	for (i=0; i<tsize; i++) {
    -//		printf("i=%u\n", i);
    -//		printf("varname=%s\n", ctab[i].varname);
    -//		printf("simaddr=0x%lx\n", ctab[i].simaddr);
    -//		printf("botaddr=0x%lx\n", ctab[i].botaddr);
    -//		printf("size=0x%x\n\n", ctab[i].size);
    -//	}
    -	return(0);
    -}
    -
    -/*!
    - * Diese Funktion initialisiert die eeprom-emulation. Sie sorgt fuer die Erstellung der
    - * eeprom.bin, falls nicht vorhanden und erstellt ueber eine Hilfsfunktion eine Adress-
    - * konvertierungstabelle fuer die EEPROM-Adressen, wenn die benoetigten Daten vorliegen.
    - * Statusinformationen werden ueber DEBUG_INFO angezeigt.
    - * @param init	gibt an, ob das EEPROM mit Hilfer einer eep-Datei initialisiert werden soll (0 nein, 1 ja)
    - * @return		0: alles ok, 1: Fehler
    - */
    -uint8_t init_eeprom_man(uint8_t init) {
    -	uint16 status;	//Status von create_ctab
    -	uint16 sflag;	//Sectionstatus
    -
    -	LOG_INFO("EEPROM-Manager");
    -
    -	/*Adresskonvertierungstabelle anlegen*/
    -	if((status=create_ctab(EEMAP_PC, EEMAP_MCU))){
    -			LOG_INFO("->EEPROM im PC-Modus");
    -	}
    -	else {
    -			LOG_INFO("->EEPROM im MCU-Modus");
    -			addrconv = 1;
    -	}
    -
    -	/*Sections ueberpruefen*/
    -	if((&_eeprom_start2__ - &_eeprom_start1__) > 0 && (&resetsEEPROM - &_eeprom_start2__) >0){
    -		LOG_INFO("->Sections liegen wohl korrekt");
    -		LOG_INFO("->Section Abstand 0x%X", (&_eeprom_start2__ - &_eeprom_start1__));
    -		sflag = 0;
    -	}
    -	else{
    -		LOG_INFO("->Sections liegen falsch");
    -		sflag = 1;
    -	}
    -
    -	/*eeprom.bin checken*/
    -	if(sflag || check_eeprom_file(EEP_PC, init)){
    -		LOG_INFO("EEPROM-Emulation fehlerhaft");
    -		return 1;
    -	}
    -	else{
    -		LOG_INFO("->EEPROM Groesse: %d Bytes", EE_SIZE);
    -		if(addrconv)
    -			LOG_INFO("->Belegter EEPROM Speicher: %d Bytes", esize);
    -		LOG_INFO("EEPROM-Emulation einsatzbereit");
    -	}
    -
    -	if((ee_file = fopen(EEPROM_FILENAME, "r+b")) == NULL) return 1;
    -	if (fread(eeprom, 1, EE_SIZE, ee_file) != EE_SIZE) return 1;
    -	return 0;
    -}
    -
    -/*!
    - * Schreibt den kompletten Inhalt des EEPROM-Caches in die Datei zurueck
    - */
    -static inline void flush_eeprom_cache(void) {
    -	fseek(ee_file, 0, SEEK_SET);
    -	fwrite(eeprom, 1, EE_SIZE, ee_file);
    -	fflush(ee_file);
    -}
    -
    -/*!
    - * Laedt ein Byte aus dem EEPROM.
    - * @param addr	Adresse im EEPROM zwischen 0 und 1023
    - * @return 		Wert der Speicheraddresse im EEPROM
    - */
    -uint8_t eeprom_read_byte(const uint8_t * addr) {
    -	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    -	if (address >= EE_SIZE) return 0xff;
    -	return eeprom[address];
    -}
    -
    -/*!
    - * Laedt ein Word aus dem EEPROM.
    - * @param addr	Adresse im EEPROM zwischen 0 und 1023
    - * @return 		Wert der Speicheraddresse im EEPROM
    - */
    -uint16_t eeprom_read_word(const uint16_t * addr) {
    -	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    -	if (address >= EE_SIZE-1) return 0xffff;
    -	uint8_t * ptr = eeprom + address;
    -	return *(uint16_t *)ptr;
    -}
    -
    -/*!
    - * Kopiert einen Block aus dem EEPROM ins RAM
    - * @param pointer_ram		Adresse im RAM
    - * @param pointer_eeprom	Adresse im EEPROM
    - * @param size				Groesse des Blocks in Byte
    - */
    -void eeprom_read_block(void *pointer_ram, const void *pointer_eeprom, size_t size) {
    -	uint16_t address = conv_eeaddr(EEPROM_ADDR(pointer_eeprom));
    -	if (address+size >= EE_SIZE) return;
    -	uint8_t * ptr = eeprom + address;
    -	memcpy(pointer_ram, ptr, size);
    -}
    -
    -/*!
    - * Speichert ein Byte im EEPROM.
    - * @param addr	Adresse im EEPROM zwischen 0 und 1023
    - * @param value	Das abzulegende Byte
    - */
    -void eeprom_write_byte(uint8_t * addr, uint8_t value) {
    -	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    -	if (address >= EE_SIZE) return;
    -	eeprom[address] = value;
    -	flush_eeprom_cache();
    -}
    -
    -/*!
    - * Speichert ein Word im EEPROM.
    - * @param addr	Adresse im EEPROM zwischen 0 und 1023
    - * @param value	Das abzulegende Word
    - */
    -void eeprom_write_word(uint16_t * addr, uint16_t value) {
    -	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    -	if (address >= EE_SIZE-1) return;
    -	uint8_t * ptr = eeprom + address;
    -	*(uint16_t *)ptr = value;
    -	flush_eeprom_cache();
    -}
    -
    -/*!
    - * Kopiert einen Block vom RAM in das EEPROM
    - * @param pointer_ram		Adresse im RAM
    - * @param pointer_eeprom	Adresse im EEPROM
    - * @param size				Groesse des Blocks in Byte
    - */
    -void eeprom_write_block(const void *pointer_ram, void *pointer_eeprom, size_t size) {
    -	uint16_t address = conv_eeaddr(EEPROM_ADDR(pointer_eeprom));
    -	if (address+size >= EE_SIZE) return;
    -	uint8_t * ptr = eeprom + address;
    -	memcpy(ptr, pointer_ram, size);
    -	flush_eeprom_cache();
    -}
    -
    -#endif	// PC
    +/*
    + * c't-Bot
    + *
    + * This program is free software; you can redistribute it
    + * and/or modify it under the terms of the GNU General
    + * Public License as published by the Free Software
    + * Foundation; either version 2 of the License, or (at your
    + * option) any later version.
    + * This program is distributed in the hope that it will be
    + * useful, but WITHOUT ANY WARRANTY; without even the implied
    + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    + * PURPOSE. See the GNU General Public License for more details.
    + * You should have received a copy of the GNU General Public
    + * License along with this program; if not, write to the Free
    + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    + * MA 02111-1307, USA.
    + *
    + */
    +
    +/*!
    + * @file 	eeprom-emu_pc.c
    + * @brief 	Low-Level Routinen fuer den Zugriff auf das emulierte EEPROM des Sim-c't-Bots
    + * @author 	Achim Pankalla (achim.pankalla@xxxxxx)
    + * @date 	07.06.2007
    + */
    +
    +//	Post-Build AVR:
    +//	avr-objcopy -O ihex -R .eeprom ct-Bot.elf ct-Bot.hex; avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex ct-Bot.elf ct-Bot.eep; avr-size ct-Bot.elf; avr-objdump -t ct-Bot.elf | grep "O \.eeprom" >  eeprom_mcu.map
    +
    +//	Post-Build Linux:
    +//	objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary ct-Bot.elf ct-Bot.eep; objdump -t -j .eeprom -C ct-Bot.elf | grep "g" > eeprom_pc.map
    +
    +//	Post-Build Mac OS X:
    +//	objcopy -j LC_SEGMENT.__DATA..eeprom --change-section-lma LC_SEGMENT.__DATA..eeprom=0 -O binary ct-Bot ct-Bot.eep; objdump -t -j LC_SEGMENT.__DATA..s2eeprom -C ct-Bot | grep "g" > eeprom_pc.map
    +
    +//	Post-Build Windows:
    +//	objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary ct-Bot.exe ct-Bot.eep;objdump -t ct-Bot.exe | grep "(sec  5)" | grep "(nx 0)" > eeprom_pc.map
    +
    +
    +#include "ct-Bot.h"
    +
    +#ifdef PC
    +
    +#include <stdlib.h>
    +#include <stdio.h>
    +#include <string.h>
    +
    +#include "log.h"
    +#include "gui.h"
    +
    +//#define DEBUG_EEPROM		// Schalter um LOG-Ausgaben anzumachen
    +
    +#ifndef DEBUG_EEPROM
    +	#undef LOG_INFO
    +	#define LOG_INFO(a, ...) {}
    +#endif
    +
    +extern uint8 __attribute__ ((section (".s1eeprom"),aligned(1))) _eeprom_start1__;
    +extern uint8 __attribute__ ((section (".s2eeprom"),aligned(1))) _eeprom_start2__;
    +
    +/*! Normiert PC EEPROM Adressen*/
    +#define EEPROM_ADDR(x) ((uint32)x - (uint32)&_eeprom_start2__ - ((uint32)&_eeprom_start2__ - (uint32)&_eeprom_start1__))
    +/*! Makros zum Mitloggen von EEPROM Zugriffen*/
    +#define LOG_LOAD 	if(addrconv) {LOG_DEBUG("LOAD:%s : %u", ctab[lastctabi].varname, eeprom[address]);}\
    +					else {LOG_DEBUG("load-addr=0x%x/%u", address, eeprom[address]);}
    +#define LOG_STORE 	if(addrconv) {LOG_DEBUG("STORE:%s : %d", ctab[lastctabi].varname, value);}\
    +					else {LOG_DEBUG("load-addr=0x%x/%d", address, value);}
    +
    +/*! Positionen der Daten in den Map-Dateien */
    +#ifdef WIN32
    +	#define SADDR_POS 54	/*!< Pos. der Adresse in PC Map Datei */
    +	#define SNAME_POS 60	/*!< Pos. des Variablennamen ohne _ */
    +	#define BADDR_POS  0	/*!< Pos. der Adresse in MCU Map Datei */
    +	#define BNAME_POS 34	/*!< Pos. des Variablennamen in MCU Map */
    +	#define BSIZE_POS 28	/*!< Pos. der Variablengroesse in MCU Map */
    +#endif
    +#ifdef __linux__
    +	#define SADDR_POS  0	/*!< Pos. der Adresse in PC Map Datei */
    +	#define SNAME_POS 46	/*!< Pos. des Variablennamen ohne _ */
    +	#define BADDR_POS  0	/*!< Pos. der Adresse in MCU Map Datei */
    +	#define BNAME_POS 34	/*!< Pos. des Variablennamen in MCU Map */
    +	#define BSIZE_POS 28	/*!< Pos. der Variablengroesse in MCU Map */
    +#endif
    +#ifdef __APPLE__
    +	#define SADDR_POS  0	/*!< Pos. der Adresse in PC Map Datei */
    +	#define SNAME_POS 45	/*!< Pos. des Variablennamen ohne _ */
    +	#define BADDR_POS  0	/*!< Pos. der Adresse in MCU Map Datei */
    +	#define BNAME_POS 34	/*!< Pos. des Variablennamen in MCU Map */
    +	#define BSIZE_POS 28	/*!< Pos. der Variablengroesse in MCU Map */
    +#endif
    +
    +#ifdef __AVR_ATmega644__  // Dieser Prozessor hat 2048 Bytes EEPROM
    +	#define EE_SIZE 2048
    +#else
    +	#define EE_SIZE 1024
    +#endif
    +
    +#define MCU_EEPROM_FN	"./mcu_eeprom.bin" 		/*!< Name und Pfad der EEPROM Datei fuer MCU-Modus*/
    +#define PC_EEPROM_FN	"./pc_eeprom.bin" 		/*!< Name und Pfad der EEPROM Datei fuer PC-Modus*/
    +#define MAX_VAR 200  						/*!< Maximale Anzahl von Variablen*/
    +#define EEMAP_PC  "./eeprom_pc.map"			/*!< Pfad fuer PC-MAP Datei */
    +#define EEP_PC    "./ct-Bot.eep"			/*!< Pfad fuer PC-EEP Datei */
    +#ifdef WIN32
    +	/* Windows */
    +	#define EEMAP_MCU "../debug-mcu-w32/eeprom_mcu.map"		/*!< Pfad fuer MCU MAP Datei */
    +#else
    +	/* Linux und OS X */
    +	#define EEMAP_MCU "../Debug-MCU-Linux/eeprom_mcu.map"	/*!< Pfad fuer MCU MAP Datei */
    +#endif
    +
    +typedef struct addrtab {
    +	char varname[30];
    +	size_t simaddr;
    +	size_t botaddr;
    +	uint16_t size;
    +//	uint32 access;	// ??? wird nie ausgewertet
    +} AddrCTab_t;								/*!< Spezieller Datentyp fuer Adresskonvertierung */
    +
    +static AddrCTab_t ctab[MAX_VAR]; 			/*!< Adresskonvertierungstabelle */
    +static uint16 tsize=0; 						/*!< Anzahl Eintraege in der Tabelle */
    +static uint16 esize=0;						/*!< Summe der EEPROM Variablen */
    +static uint8 addrconv = 0;                  /*!< Adresskonvertierung ein-/ausschalten */
    +static uint16 lastctabi = 0;                /*!< Letzter Zugriffsindex auf ctab */
    +static uint8 eeprom[EE_SIZE];               /*!< EEPROM Speicher im RAM */
    +static FILE * ee_file;						/*!< Zeiger auf EEPROM-Datei */
    +
    +/*!
    + * Diese Funktion konvertiert die Adressen der EEPROM Variablen des PC so,
    + * dass sie den Adressen im realen ct-Bot entsprechen. Dafuer wird mit der Funktion
    + * create_ctab ein Adresstabelle angelegt, diese nutzt diese Funktion.
    + * @param addr	Adresse im EEPROM zwischen 0 und EE_SIZE-1
    + * @return 		Die neue Adresse fuer den realen Bot
    + */
    +static uint32 conv_eeaddr(uint32 addr){
    +	int8 i;
    +	int32 adiff;
    +
    +	if(!addrconv) //Keine Adresskonvertierung
    +		return(addr);
    +	for(i=0; i<tsize; i++){
    +		adiff = addr - ctab[i].simaddr;
    +		if(adiff < 0)
    +			return(0xfffffffe);
    +		if(adiff < ctab[i].size){
    +			lastctabi = i; //Letzer guelten Index merken
    +			return(ctab[i].botaddr + adiff);
    +		}
    +	}
    +	return(0xffffffff);
    +}
    +
    +/*!
    + * Diese Funktion uberprueft das vorhanden sein der eeprom.bin und initialisiert sie
    + * gegebenenfalls mit der Initwerten der eep Datei.
    + * Es wird dabei die Adresskovertierung benutzt, wenn die EEPROM Simulation im MCU-Modus
    + * ist.
    + * -----
    + *  0 = EEPROM Datei OK
    + *  1 = Fehler aufgetreten
    + * -----
    + * @param initfile		EEP-Datei des PC Codes
    + * @param eeprom_init	Flag fuer Initialisierung (1 ja, 0 nein)
    + * @param fn			Dateiname der EEPROM-Datei
    + * @return 				Status der Funktion
    + */
    +static uint16 check_eeprom_file(char *initfile, uint8_t eeprom_init, char *fn){
    +	FILE *fpr, *fpw; //Filepointer fuer Dateizugriffe
    +	uint16 i; //Laufvariable
    +	char data[2]; //Datenspeicher
    +
    +	/*eeprom file vorhanden*/
    +	if(!(fpw = fopen(fn, "r+b"))){ //Testen, ob Datei vorhanden ist.
    +		if(!(fpw = fopen(fn, "w+b"))){ //wenn nicht, dann erstellen
    +			LOG_INFO("->Kann EEPROM-Datei nicht erstellen");
    +			return(1);
    +		}
    +		if(!addrconv) {
    +			/* EEPROM mit .eeprom-Section des .elf-Files initialisieren, wenn PC Modus */
    +			uint8_t * ram_dump = (uint8_t *)(&_eeprom_start2__ + (&_eeprom_start2__ - &_eeprom_start1__));
    +			fwrite(ram_dump, EE_SIZE, 1, fpw);
    +			LOG_INFO("->Initialsierte EEPROM-Datei erstellt");
    +		} else {
    +			/* alternativ: leeres EEPROM erstellen und init setzen bei MCU Modus*/
    +			for(i = 0; i < EE_SIZE; i++)
    +				fwrite("\377", 1, 1, fpw);
    +			eeprom_init = 1;
    +			LOG_INFO("->Leere EEPROM-Datei erstellt");
    +		}
    +
    +		fclose(fpw);
    + 	}
    +
    +	/*Initialsieren der eeprom.bin, wenn gewuenscht*/
    +	if(eeprom_init){
    +		if(!(fpr = fopen(initfile, "rb"))){ //Datei oeffnen
    +			LOG_INFO("->EEP nicht gefunden");
    +			return(1);
    +		}
    +		if(!(fpw = fopen(fn, "rb+"))){ //Datei oeffnen
    +			LOG_INFO("->EEPROM-Datei kann nicht beschrieben werden");
    +			return(1);
    +		}
    +
    +		/*EEP-Datei in EEPROM-Datei kopieren*/
    +		for(i=0; i<EE_SIZE; i++){
    +			/*Daten kopieren*/
    +			if(!fread(data, 1, 1, fpr))
    +				break;
    +			if(addrconv){ //EEPROM-Datei im MCU-Modus
    +				uint32 naddr;//Konvertierte Adresse
    +
    +				naddr = conv_eeaddr((uint32)i);
    +				if(naddr < 0xfffffffe){
    +					fseek(fpw, (int32)naddr, SEEK_SET);
    +				}
    +				else{
    +					continue; //Nichts schreiben Adresse nicht belegt
    +				}
    +			}
    +			fwrite(data, 1, 1, fpw);
    +		}
    +		fclose(fpr);
    +		fclose(fpw);
    +		LOG_INFO("->EEPROM-Datei mit Daten init.");
    +	}
    +	return(0);
    +}
    +
    +/*!
    + * Diese Funktion erstellt aus den beiden im Post erstellten MAP Dateien eine Tabelle
    + * zum umrechnen der PC-Adressen in die des avr-Compilers. Dadurch kann die EEPROM
    + * Datei in einen zum EEPROM des Bot kompatiblen Format gehalten werden.
    + * Wichtige Informationen werden ueber LOG_INFO angezeigt.
    + * ----
    + * Ergebniscodes der Funktion
    + * 0 = Fehlerfrei
    + * 1 = Sim Mapfile nicht vorhanden
    + * 2 = Bot Mapfile nicht vorhanden
    + * 3 = Unterschiedlicher Variablenbestand
    + * 4 = Zuviele Variablen
    + * 5 = EEPROM voll
    + * 6 = Unterschiedliche Variablenanzahl
    + *
    + * @param simfile	MAP mit den Adressen der EEPROM-Variablen in der PC exe/elf
    + * @param botfile	MAP mit den Adressen der EEPROM-Variablen im MCU elf
    + * @return 			Statuscode
    + */
    +static uint16 create_ctab(char *simfile, char *botfile){
    +	FILE *fps, *fpb;
    +	char sline[250], bline[250]; //Textzeilen aus Dateien
    +	char vname_s[30], vname_b[30]; //Variablennamen
    +	size_t addr_s, addr_b; //Adressen der Variablen
    +	uint16_t size; //Variablengroesse
    +	uint16 vc = 0; //Variablenzaehler
    +	size_t first_botaddr = 0xffffffff; //Erste ct-bot EEPROM Adressse
    +
    +	/*Dateien oeffnen*/
    +	if(!(fps=fopen(simfile,"r"))){
    +		LOG_INFO("->EEPROM-MAP fuer PC fehlt");
    +		return(1);
    +	}
    +	if(!(fpb=fopen(botfile,"r"))){
    +		LOG_INFO("->EEPROM-MAP fuer MCU fehlt");
    +		return(2);
    +	}
    +
    +	/*Anzahl Variablen vergleichen*/
    +	while(fgets(sline, 249, fps)) vc++;
    +	while(fgets(sline, 249, fpb)) vc--;
    +	if(vc){
    +		fclose(fps);
    +		fclose(fpb);
    +		LOG_INFO("->Unterschiedliche Variablenanzahl");
    +		return(6);
    +	}
    +	rewind(fps);
    +	rewind(fpb);
    +
    +	/*Tabelle erstellen*/
    +	while(fgets(sline, 249, fps)){
    +		rewind(fpb);
    +		sscanf(&sline[SNAME_POS], "%s", vname_s);
    +//		printf("vname_s=%s\n", vname_s);
    +		addr_s = strtol(&sline[SADDR_POS], NULL, 16);
    +//		printf("addr_s=0x%lx\n", addr_s);
    +		while(fgets(bline, 249, fpb)){
    +			/*Variablennamen suchen*/
    +			sscanf(&bline[BNAME_POS], "%s", vname_b);
    +//			printf("vname_b=%s\n", vname_b);
    +			addr_b = strtol(&bline[BADDR_POS], NULL, 16);
    +//			printf("addr_b=0x%lx\n", addr_b);
    +			if(addr_b < first_botaddr)//Kleinste ct-bot Adresse bestimmen
    +				first_botaddr = addr_b;
    +			size = strtol(&bline[BSIZE_POS], NULL, 16);
    +//			printf("size=0x%x\n", size);
    +
    +			if(!strcmp(vname_s, vname_b)){
    +				/*Daten kopieren*/
    +				strcpy(ctab[tsize].varname, vname_b);
    +				ctab[tsize].simaddr = addr_s;
    +				ctab[tsize].botaddr = addr_b;
    +				ctab[tsize++].size    = size;
    +				//ctab[tsize++].access  = 0;	// ??? wird nie ausgewertet
    +				esize += size;
    +				/*Fehlerabbrueche*/
    +				if(tsize == MAX_VAR){
    +					LOG_INFO("->Mehr als %n Variablen",MAX_VAR);
    +					return(4);
    +				}
    +				if(esize > EE_SIZE){
    +					LOG_INFO("->EEPROM voll");
    +					return(5);
    +				}
    +
    +				/*Erfolg markieren*/
    +				addr_b = -1;
    +				break;
    +			}
    +		}
    +		if(addr_b > -1){ //Keine passende Variable gefunden
    +			LOG_INFO("->Unterschiedliche Variablen");
    +			return(3);
    +		}
    +	}
    +
    +	/*Dateien schliessen*/
    +	fclose(fps);
    +	fclose(fpb);
    +
    +	/*Tabelle nach Sim-Adressen sortieren*/
    +	uint16_t i, j;
    +	for(j=tsize-1; j > 0; j--){
    +		for(i=0; i < j; i++){
    +			if(ctab[i].simaddr > ctab[i+1].simaddr){
    +				size_t simaddr, botaddr, size;
    +				char vname[30];
    +
    +				/*Daten umkopieren*/
    +				strcpy(vname, ctab[i+1].varname);
    +				simaddr = ctab[i+1].simaddr;
    +				botaddr = ctab[i+1].botaddr;
    +				size    = ctab[i+1].size;
    +
    +				strcpy(ctab[i+1].varname, ctab[i].varname);
    +				ctab[i+1].simaddr = ctab[i].simaddr;
    +				ctab[i+1].botaddr = ctab[i].botaddr;
    +				ctab[i+1].size    = ctab[i].size;
    +
    +				strcpy(ctab[i].varname, vname);
    +				ctab[i].simaddr = simaddr;
    +				ctab[i].botaddr = botaddr;
    +				ctab[i].size    = size;
    +			}
    +		}
    +	}
    +
    +	/*Die EEPROM-Startadressen vom ct-bot und/oder Ct-Sim auf Null normieren*/
    +	size_t first_simaddr = ctab[0].simaddr;
    +	if(first_simaddr || first_botaddr) {
    +		LOG_INFO("->Adressen werden normiert");
    +		for(i=0; i<tsize; i++){
    +			if(first_simaddr) ctab[i].simaddr -= first_simaddr;
    +			if(first_botaddr) ctab[i].botaddr -= first_botaddr;
    +//			printf("addr_b=0x%x addr_b=0x%x\n", ctab[i].botaddr, ctab[i].simaddr);
    +		}
    +	}
    +
    +//	for (i=0; i<tsize; i++) {
    +//		printf("i=%u\n", i);
    +//		printf("varname=%s\n", ctab[i].varname);
    +//		printf("simaddr=0x%lx\n", ctab[i].simaddr);
    +//		printf("botaddr=0x%lx\n", ctab[i].botaddr);
    +//		printf("size=0x%x\n\n", ctab[i].size);
    +//	}
    +	return(0);
    +}
    +
    +/*!
    + * Diese Funktion initialisiert die eeprom-emulation. Sie sorgt fuer die Erstellung der
    + * eeprom.bin, falls nicht vorhanden und erstellt ueber eine Hilfsfunktion eine Adress-
    + * konvertierungstabelle fuer die EEPROM-Adressen, wenn die benoetigten Daten vorliegen.
    + * Statusinformationen werden ueber DEBUG_INFO angezeigt.
    + * @param init	gibt an, ob das EEPROM mit Hilfer einer eep-Datei initialisiert werden soll (0 nein, 1 ja)
    + * @return		0: alles ok, 1: Fehler
    + */
    +uint8_t init_eeprom_man(uint8_t init) {
    +	uint16 status;	//Status von create_ctab
    +	uint16 sflag;	//Sectionstatus
    +	char fn[30] = "";
    +
    +	LOG_INFO("EEPROM-Manager");
    +
    +	/*Adresskonvertierungstabelle anlegen*/
    +	if((status=create_ctab(EEMAP_PC, EEMAP_MCU))){
    +			LOG_INFO("->EEPROM im PC-Modus");
    +			strcat(fn, PC_EEPROM_FN);
    +			remove(MCU_EEPROM_FN);
    +	}
    +	else {
    +			LOG_INFO("->EEPROM im MCU-Modus");
    +			strcat(fn, MCU_EEPROM_FN);
    +			remove(PC_EEPROM_FN);
    +			addrconv = 1;
    +	}
    +
    +	/*Sections ueberpruefen*/
    +	if((&_eeprom_start2__ - &_eeprom_start1__) > 0 && (&resetsEEPROM - &_eeprom_start2__) >0){
    +		LOG_INFO("->Sections liegen wohl korrekt");
    +		LOG_INFO("->Section Abstand 0x%X", (&_eeprom_start2__ - &_eeprom_start1__));
    +		sflag = 0;
    +	}
    +	else{
    +		LOG_INFO("->Sections liegen falsch");
    +		sflag = 1;
    +	}
    +
    +	/*eeprom.bin checken*/
    +	if(sflag || check_eeprom_file(EEP_PC, init, fn)){
    +		LOG_INFO("EEPROM-Emulation fehlerhaft");
    +		return 1;
    +	}
    +	else{
    +		LOG_INFO("->EEPROM Groesse: %d Bytes", EE_SIZE);
    +		if(addrconv)
    +			LOG_INFO("->Belegter EEPROM Speicher: %d Bytes", esize);
    +		LOG_INFO("EEPROM-Emulation einsatzbereit");
    +	}
    +
    +	if((ee_file = fopen(fn, "r+b")) == NULL) return 1;
    +	if (fread(eeprom, 1, EE_SIZE, ee_file) != EE_SIZE) return 1;
    +	return 0;
    +}
    +
    +/*!
    + * Schreibt den kompletten Inhalt des EEPROM-Caches in die Datei zurueck
    + */
    +static inline void flush_eeprom_cache(void) {
    +	fseek(ee_file, 0, SEEK_SET);
    +	fwrite(eeprom, 1, EE_SIZE, ee_file);
    +	fflush(ee_file);
    +}
    +
    +/*!
    + * Laedt ein Byte aus dem EEPROM.
    + * @param addr	Adresse im EEPROM zwischen 0 und 1023
    + * @return 		Wert der Speicheraddresse im EEPROM
    + */
    +uint8_t eeprom_read_byte(const uint8_t * addr) {
    +	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    +	if (address >= EE_SIZE) return 0xff;
    +	return eeprom[address];
    +}
    +
    +/*!
    + * Laedt ein Word aus dem EEPROM.
    + * @param addr	Adresse im EEPROM zwischen 0 und 1023
    + * @return 		Wert der Speicheraddresse im EEPROM
    + */
    +uint16_t eeprom_read_word(const uint16_t * addr) {
    +	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    +	if (address >= EE_SIZE-1) return 0xffff;
    +	uint8_t * ptr = eeprom + address;
    +	return *(uint16_t *)ptr;
    +}
    +
    +/*!
    + * Kopiert einen Block aus dem EEPROM ins RAM
    + * @param pointer_ram		Adresse im RAM
    + * @param pointer_eeprom	Adresse im EEPROM
    + * @param size				Groesse des Blocks in Byte
    + */
    +void eeprom_read_block(void *pointer_ram, const void *pointer_eeprom, size_t size) {
    +	uint16_t address = conv_eeaddr(EEPROM_ADDR(pointer_eeprom));
    +	if (address+size >= EE_SIZE) return;
    +	uint8_t * ptr = eeprom + address;
    +	memcpy(pointer_ram, ptr, size);
    +}
    +
    +/*!
    + * Speichert ein Byte im EEPROM.
    + * @param addr	Adresse im EEPROM zwischen 0 und 1023
    + * @param value	Das abzulegende Byte
    + */
    +void eeprom_write_byte(uint8_t * addr, uint8_t value) {
    +	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    +	if (address >= EE_SIZE) return;
    +	eeprom[address] = value;
    +	flush_eeprom_cache();
    +}
    +
    +/*!
    + * Speichert ein Word im EEPROM.
    + * @param addr	Adresse im EEPROM zwischen 0 und 1023
    + * @param value	Das abzulegende Word
    + */
    +void eeprom_write_word(uint16_t * addr, uint16_t value) {
    +	uint16_t address = conv_eeaddr(EEPROM_ADDR(addr));
    +	if (address >= EE_SIZE-1) return;
    +	uint8_t * ptr = eeprom + address;
    +	*(uint16_t *)ptr = value;
    +	flush_eeprom_cache();
    +}
    +
    +/*!
    + * Kopiert einen Block vom RAM in das EEPROM
    + * @param pointer_ram		Adresse im RAM
    + * @param pointer_eeprom	Adresse im EEPROM
    + * @param size				Groesse des Blocks in Byte
    + */
    +void eeprom_write_block(const void *pointer_ram, void *pointer_eeprom, size_t size) {
    +	uint16_t address = conv_eeaddr(EEPROM_ADDR(pointer_eeprom));
    +	if (address+size >= EE_SIZE) return;
    +	uint8_t * ptr = eeprom + address;
    +	memcpy(ptr, pointer_ram, size);
    +	flush_eeprom_cache();
    +}
    +
    +#endif	// PC
    Index: E:/eclipse/ct-bot devel/ct-Bot/Changelog.txt
    ===================================================================
    --- E:/eclipse/ct-bot devel/ct-Bot/Changelog.txt	(revision 1247)
    +++ E:/eclipse/ct-bot devel/ct-Bot/Changelog.txt	(working copy)
    @@ -1,5 +1,7 @@
     CHANGELOG fuer c't-Bot
     ======================
    +2007-09-17 Achim Pankalla [achim.pankalla@xxxxxx]: EEPROM Datei wird nun nach Moduswechsel geloescht. Modus an Dateinamen erkennbar. (#143)
    +
     2007-09-16 Timo Sandmann [mail@xxxxxxxxxxxxxxx]: Bugfix fuer Liniensensoren

     2007-09-13 Timo Sandmann [mail@xxxxxxxxxxxxxxx]: Bugfix in log.h (#144)
    Index: E:/eclipse/ct-bot devel/ct-Bot/Documentation/eeprom-simulation.html
    ===================================================================
    --- E:/eclipse/ct-bot devel/ct-Bot/Documentation/eeprom-simulation.html	(revision 1247)
    +++ E:/eclipse/ct-bot devel/ct-Bot/Documentation/eeprom-simulation.html	(working copy)
    @@ -1,254 +1,455 @@
    -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    -<html>
    -<head>
    -  <meta http-equiv="CONTENT-TYPE" content="text/html; charset=windows-1252">
    -  <title></title>
    -  <meta name="GENERATOR" content="OpenOffice.org 2.2  (Win32)">
    -  <meta name="AUTHOR" content="Achim Pankalla">
    -  <meta name="CREATED" content="20060528;19455600">
    -  <meta name="CHANGEDBY" content="Achim Pankalla">
    -  <meta name="CHANGED" content="20070617;18142584">
    -  <style type="text/css">
    -	<!--
    -		@page { size: 21cm 29.7cm; margin: 2cm }
    -		P { margin-bottom: 0.21cm }
    -	-->
    -	</style>
    -</head>
    -
    -<body dir="ltr" lang="de-DE">
    -
    -<p style="margin-bottom: 0cm; font-family: Times New Roman;" align="center"><font size="+1"><b>EEPROM Emulation f&uuml;r
    -PC</b></font></p>
    -<p style="margin-bottom: 0cm; text-align: center;"><font size="3"><b><small>Version 1 18-Jul-2007</small></b><br>
    -Achim Pankalla
    -(achim.pankalla@xxxxxx)</font></p>
    -<p style="margin-bottom: 0cm; height: 0px;"><br>
    -</p>
    -
    -<p style="margin-bottom: 0cm; font-style: normal; text-align: justify;"></p>
    -<div style="text-align: center;"><b>Beschreibung</b><br>
    -<div style="text-align: justify;">Die
    -EEPROM Emulation f&uuml;r den PC stellt das EEPROM des <i>Atmel
    -MEGA32(644) Prozessors</i> auch dem ct-Sim zur Verf&uuml;gung.
    -Der Zugriff auf dieses EEPROM erfolgt &uuml;ber gleichnamige
    -Funktionen, wie sie auch die avr-libc bereitstellt und auch die
    -Variablendefinition erfolgt &uuml;ber die gleichen Konstrukte. Eine
    -Unterscheidung &uuml;ber <span style="font-style: italic;">#ifdef</span>'s ist also nicht notwendig.<br>
    -Durch
    -diese EEPROM-Emulation ist der ct-Sim dem realen Bot einen Schritt
    -n&auml;her gekommen und Programme mit EEPROM-Zugriffe k&ouml;nnen mit
    -der Simulation getestet werden. Mehr noch, Sie k&ouml;nnen auch den
    -Inhalt des emulierten EEPROM auf den ct-Bot &uuml;bertragen oder das
    -EEPROM vom
    -ct-Bot laden und f&uuml;r die Emulation nutzen.</div>
    -</div>
    -<p style="margin-bottom: 0cm;" align="left"><br>
    -</p>
    -
    -<p style="margin-bottom: 0cm; text-align: center;"><b>Implementierung</b><br>
    -</p>
    -<div style="text-align: justify;">Alle Funktionen und Einstellungen der
    -EEPROM Emulation findet Sie in den Dateien <i>pc/eeprom-emu_pc.c</i>
    -und <i>include/eeprom-emu.h</i>. Das EEPROM selbst wird durch eine
    -bin&auml;re Datei (genau 1 KB bzw. 2 KB gro&szlig;) repr&auml;sentiert&nbsp;und
    -kann so mit einen HexEditor bearbeitet werden. Der Pfad befindet sich in der
    -Konstanten <span style="font-style: italic;">EEPROM_FILENAME</span> in der C-Datei. Standard Pfad ist das Heimatverzeichnis des
    -ct-Bots.<font color="#000000"><font face="Courier New, monospace"><font size="2"></font></font></font>
    -<font face="Times New Roman, serif">Der Name </font><font face="Times New Roman, serif"><i>eeprom.bin</i></font>
    -<font face="Times New Roman, serif">sollte belassen werden.</font><br>
    -Die
    -Datei wird automatisch neu angelegt, wenn sie noch nicht existiert,
    -dann wird die Datei automatisch mit den aktuellen Zuweisung der
    -EEPROM-Variablen initialisiert (mit Hilfe von ct-Bot.eep). Ist schon
    -eine <span style="font-style: italic;">eeprom.bin</span> vorhanden, so wird diese nicht ver&auml;ndert, ausser die ct-Bot.exe wird mit dem Parameter <span style="font-style: italic;">-i</span> gestartet, dann wird auch eine schon vorhandene Datei mit den vorhandenen Zuweisungen &uuml;berschrieben.<br>
    -Damit die
    -EEPROM-Funktionen des PC korrekt auf die Datei zugreifen k&ouml;nnen
    -darf nur ein Adressraum von 0 bis 1023 (bzw. 2047) entstehen.&nbsp;Die
    -Emulation muss also wissen welche Speicheradresse die
    -erste Variable im EEPROM hat, um diesen Wert von allen anderen
    -abzuziehen. Daf&uuml;r bedarf es bei
    -der PC Implementierung (mit PC ist allgemein der Code f&uuml;r den
    -ct-Sim gemeint, mag das OS nun Win, Linux oder Mac OS X hei&szlig;en)
    -eines Tricks.&nbsp;<br>
    -Daf&uuml;r gibt es die beiden Variablen
    -<i>_eeprom_start1__</i> und <i>_eeprom_start2_</i><span style="font-style: normal;">_
    -in </span><i>1st_init.S</i><span style="font-style: normal;">. Diese
    -stehen dort, damit sie auf jeden Fall vor der ersten EEPROM Variable
    -definiert werden und damit ihre Sections (.</span><i>s1eeprom</i> <span style="font-style: normal;">+
    -.</span><i>s2eeprom</i><span style="font-style: normal;">) auf jeden
    -Fall vor der Section .</span><i>eeprom</i> <span style="font-style: normal;">liegen.</span><br>
    -Durch diesen Trick
    -kann die Speicheradresse der ersten EEPROM Variable auch ohne
    -Linkerscript ermittelt werden und auch verschiedene
    -Section-Alignments (im Moment bei MinGW und Linux unterschiedlich)
    -haben keine Auswirkung.<br>
    -Auch beim
    -Generieren einer neuen Datei ct-Bot.exe/elf wird eine EEP mit den
    -Initialisierungen der EEPROM-Variablen im Post-Build angelegt. Diese
    -Datei kann&nbsp; die EEPROM-Emulation auch als Initialisierung f&uuml;r die <span style="font-style: italic;">eeprom.bin</span> im MCU-Modus benutzen. Sollte keine <span style="font-style: italic;">eeprom.bin</span> existieren, wird sie auch daf&uuml;r genutzt. Arbeitet man im PC-Modus, kann diese Datei auch in eeprom.bin umbenannt werden.<br>
    -Damit die Emulation m&ouml;glichst effektiv und schnell arbeiten kann, wird nach dem Start die gesamte Datei <span style="font-style: italic;">eeprom.bin</span> im Hauptspeicher gecached und nach jedem Schreibzugriff komplett neu geschrieben.<br>
    -Damit man die EEPROM-Datei auch auf den ct-Bot einspielen kann, oder
    -einen EEPROM Abzug &nbsp;des ct-Bot als emuliertes EEPROM nutzen kann,
    -werden Post-Builds ben&ouml;tigt, die die Adressen der einzelnen
    -Variablen auf ct-Bot und ct-Sim aufzeigen. Der EEPROM Manager wird beim
    -Start eines Bots im ct-Sim dann eine (Adress)Konvertierungstabelle
    -erstellen, um die Zugriffe auf das EEPROM anzupassen. Diese Tabelle
    -wird nach aufsteigenden Adressen des ct-Sim sortiert und nur im
    -MCU-Modus genutzt.</div>
    -
    -<p style="margin-bottom: 0cm;"></p>
    -<div style="text-align: center;"><b>Nutzung der EEPROM Emulation</b><br>
    -<div style="text-align: justify;">Die EEPROM-Emulation unterscheidet
    -sich nur in ein paar Details von den Funktionen der avr-libc f&uuml;r den realen ct-Bot.
    -Nat&uuml;rlich hat der PC kein EEPROM, dieses wird durch
    -eine&nbsp;Datei im Bin&auml;rformat emuliert. Der Dateinamen und der Pfad
    -wird &uuml;ber die Konstante EEPROM_FILENAME in <i>eeprom</i>-<i>emu</i>_<i>pc</i>.<i>c</i>
    -festgelegt. <br>
    -Ein weiterer Unterschied ist, dass beim avr-gcc &uuml;ber
    -ein DEFINE der Prozessortyp festgelegt wird, entweder ATMega32 oder
    -ATMega644. Dieses DEFINE ist beim PC Compiler normalerweise nicht
    -gesetzt. Standardm&auml;&szlig;ig wird von einem ATMega32 mit
    -1024 Byte EEPROM ausgegangen, Die Emulation kennt aber die Konstante
    -f&uuml;r den ATMega644 und erh&ouml;ht den EEPROM Speicher auf 2048
    -Bytes. Sollte schon eine 1 KB Datei f&uuml;rs EEPROM bestehen, so muss
    -diese gel&ouml;scht werden, damit die Gr&ouml;&szlig;ere angelegt
    -wird. Wird direkt die erstellte <i>ct-bot.eep</i> Datei im PC-Modus genutzt, ist
    -dies nat&uuml;rlich nicht notwendig. <br>
    -Alle wichtigen Informationen werden
    -beim Start von ct-Bot.exe/elf im Log-Fenster angezeigt, vorrausgesetzt es ist in <span style="font-style: italic;">ct-bot.h</span> aktiviert ist (zus&auml;tzlich bitte in <span style="font-style: italic;">eeprom-emu_pc.c</span> die Konstante <span style="font-style: italic;">DEBUG_EEPROM</span>
    -aktivieren), dort sieht man
    -auch alle eventuellen Fehler, den erreichten Emulationsmodus und ob die
    -Emulation ordnungsgem&auml;&szlig;
    -arbeiten kann. Es erfolgt kein Beenden bei
    -Problemen, die Funktion des EEPROMs ist dann aber nicht gegeben. Bei
    -Auff&auml;lligkeiten sollte man dann die LOG Funktion aktivieren.</div>
    -</div>
    -<p style="margin-bottom: 0cm;">Generell unterscheidet die Emulation
    -zwei Modi:</p>
    -<ol>
    -	<li>
    -    <p style="margin-bottom: 0cm;">PC-Modus<br>
    -In diesen Modus entspricht die
    -	<span style="font-style: italic;">eeprom.bin</span> nicht dem EEPROM des realen ct-Bots und darf deshalb auch
    -	nicht auf ihn aufgespielt werden. Dieser Modus wird ohne jedes Zutun erreicht.
    -	Er ben&ouml;tigt keine weiteren Eintr&auml;ge im Post-Build.&nbsp;Wenn eine <span style="font-style: italic;">ct-bot.eep</span> im Bin&auml;rformat erstellt wird,
    -	so kann diese direkt benutzt werden.</p>
    -	</li>
    -  <li>
    -
    -   <p style="margin-bottom: 0cm;">MCU-Modus<br>
    -Ist dieser Modus erreicht, kann man
    -	als EEPROM-Datei einen EEPROM Abzug vom ct-Bot verwenden.
    -	Voraussetzung ist nat&uuml;rlich, dass der Bot auch mit zuletzt
    -	erstelltem Programm bespielt ist. Nat&uuml;lich kann man auch die
    -	EEPROM-Datei <span style="font-style: italic;">eeprom.bin</span> auf dem ct-Bot aufgespielen.<br>
    -Der MCU-Modus kann nur erreicht
    -	werden, wenn sowohl beim avr-gcc als auch unter dem ct-Sim
    -	eine map-Datei erstellt wird, daf&uuml;r m&uuml;ssen im Post-Build die Befehle aus dem Kommentarkopf aus <span style="font-style: italic;">eeprom-emu_pc.c</span> ausgef&uuml;hrt werden.</p>
    -In den Projekteinstellungen im SVN sind die n&ouml;tigen Post-Build-Einstellungen f&uuml;r alle Betriebssysteme bereits gemacht.
    -	<br>
    -  </li>
    -</ol>
    -
    -<p style="margin-bottom: 0cm; text-align: justify;">M&ouml;chte man die vorhandene EEPROM-Datei mit den Daten aus der EEP-Datei
    -initialisieren, so muss man die ct-Bot.exe/elf mit dem Parameter <i>-i
    -</i>starten, dabei spielt es keine Rolle in welchen Modus die
    -Emulation arbeitet. Der Pfad der EEP-Datei wird in der Konstante
    -<font color="#000000"><font face="Courier New, monospace"><font size="2">EEP_PC
    - </font></font></font><font color="#000000"><font face="Times New Roman, serif"><font size="3">und die Pfade f&uuml;r die MAP-Dateien werden in den Konstanten EEMAP_PC und EEMAP_MCU eingetragen.<br>
    -Die Variable MAX_VAR legt die Gr&ouml;&szlig;e der Tabelle fest und
    -beschr&auml;ngt damit die maximale Anzahl der Variablen. Sollte die
    -Fehlermeldung auftreten, dass es zu viele Variablen gibt, muss man
    -diesen Wert nur erh&ouml;hen. <br>
    -</font></font></font></p>
    -<font color="#000000"><font face="Times New Roman, serif"><font size="3">F&uuml;r
    -das Debuggen von Zugriffen auf das EEPROM stehen unter anderem die
    -DEFINES LOG_STORE und LOG_LOAD zur Verf&uuml;gung, die im MCU Modus
    -sogar den Variablennamen anzeigen. Andere Variationen sind auch noch
    -denkbar.</font></font></font>
    -<p style="margin-bottom: 0cm;"></p>
    -
    -<div style="text-align: center;"><b>Grenzen der
    -Implementierung</b><br>
    -<div style="text-align: justify;">Im Moment erstellen gleiche Compilerversionen (zu &uuml;berpr&uuml;fen
    -mit --version) auch (fast) gleiche EEPROM-Sections. Damit es
    -auch mit verschiedenen Compiler Version geht (und ich mich auch nicht
    -auf die gleichen Versionen verlasssen will) habe ich die
    -Adresskonvertierung eingef&uuml;hrt, damit dies kein Problem mehr
    -ist. Es gibt aber keine Garantien daf&uuml;r, dass zuk&uuml;nftige Compiler
    -Versionen nicht die Reihenfolge der Variablen im Code &auml;ndern.
    -Ein Einf&uuml;gen neuer EEPROM Variablen kann auch zu Verschiebungen
    -der Adressen f&uuml;hren. Nach solchen &Auml;nderungen (auch ein &auml;ndern der Compilerversion) ist man nur
    -auf der sicheren Seite, wenn das EEPROM initialisiert wird (sprich,
    -Sie Ihre alte <span style="font-style: italic;">eeprom.bin</span> bzw. auf dem Atmel das EEPROM l&ouml;schen) und f&uuml;r MCU und ct-Sim neue Exe generiert werden.
    -Einmal erstellte Werte sind dann nat&uuml;rlich futsch. Wenn man den
    -Einfluss von Codeerg&auml;nzungen kontrollieren will, kann man dies
    -vor und nach der &Auml;nderung mit <span style="font-style: italic;">objdump</span> machen (oder falls Sie
    -die Befehle f&uuml;r die MAP-Dateien im Post-Build benutzen, schauen
    -Sie in die MAP-Dateien), mit den richtigen Parametern kann man sich
    -die Adressverteilung anzeigen lassen. Sie k&ouml;nnen dann sehen, ob
    -die neuen Variablen nun hinten angeh&auml;ngt wurden (dann brauch das
    -EEPROM nicht gel&ouml;scht werden) oder sie dazwischen gelandet sind
    -(dann sind die alten Daten unbrauchbar), daf&uuml;r sollten sie aber
    -vorher in Eclipse <span style="font-style: italic;">Projekt-&gt;clean</span> aufrufen.<br>
    -Der Compiler kann aufgrund der Implementierung
    -des EEPROMs auf dem PC nicht kontrollieren, ob mehr als 1024/2048 Bytes
    -f&uuml;r die Variablen ben&ouml;tigt werden, er kennt diese Begrenzung
    -nicht. Der EEPROM-Manager meckert dann aber
    -im LOG. </div>
    -</div>
    -
    -<p style="margin-bottom: 0cm;"></p>
    -<div style="text-align: center;"><span style="font-weight: bold;">Verschiedenes</span><br>
    -<div style="text-align: justify;">Ein besonderer Dank an dieser Stelle
    -an Timo Sandmann unter anderem f&uuml;r das Testen unter MacOSX und
    -f&uuml;r verschiedene Anpassungen, Optimierungen und f&uuml;r den
    -Assemblercode in 1st_init.S ohne den wohl st&auml;ndige Probleme
    -unvermeidlich gewesen w&auml;ren.<br>
    -Dank auch an alle anderen f&uuml;r konstruktive Kritik, die die
    -jetzige, ich denke annehmbare, L&ouml;sung erst m&ouml;glich machte und
    -meiner Familie f&uuml;r ihre unendliche Geduld. <br>
    -M&ouml;ge sich jeder eingeladen f&uuml;hlen etwas zu verbessern oder erweitern.<br>
    -
    -</div>
    -</div>
    -
    -<p style="margin-bottom: 0cm;"><b>Funktionen</b><br>
    -init_eeprom_man() - Erledigt alle Arbeiten zur Aktivierung der EEPROM-Emulation<br>
    -</p>
    -<p style="margin-bottom: 0cm;"><b>Nur in eeprom-emu_pc.c sichtbare
    -Funktionen</b></p>
    -conv_eeaddr() - Wandelt PC Adresse in
    -ct-Bot Adresse<br>
    -create_ctab() - Erstellt
    -Adresskonvertierungstabelle<br>
    -check_eeprom_file() - Erstellt leeres
    -EEPROM, wenn n&ouml;tig und initialisiert es, wenn gew&uuml;nscht<br>
    -flush_eeprom_cache() - Schreibt ver&auml;nderte Daten in eeprom.bin<br>
    -
    -<p style="margin-bottom: 0cm;"><b>Zugriffsfunktionen f&uuml;r den PC
    -(identisch zu denen der avr-libc)</b><br>
    -eeprom_read_byte()<br>
    -eeprom_write_byte()<br>
    -eeprom_read_word()<br>
    -eeprom_write_word()<br>
    -eeprom_write_block()<br>
    -eeprom_read_block()</p>
    -
    -<p style="margin-bottom: 0cm;"><font size="3"><b>Dateien</b></font><br>
    -</p>
    -<div style="text-align: center;">
    -<div style="text-align: left;">eeprom-emu.h - Headerdatei mit den Deklarationen<br>
    -eeprom-emu_pc.c - Implementierung der Funktionen
    -f&uuml;r ct-Bot &amp; ct-Sim<br>
    -<font size="3">1st_init.S - Sorgt f&uuml;r das korrekte Anlegen der Hilfsvariablen in der Exe</font></div>
    -</div>
    -<p style="margin-bottom: 0cm;"><br>
    -</p>
    -<p style="margin-bottom: 0cm;"><br>
    -</p>
    -<p style="margin-bottom: 0cm;"><br>
    -</p>
    -</body>
    -</html>
    +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    +<html>
    +<head>
    +
    +
    +
    +
    +  <meta http-equiv="CONTENT-TYPE" content="text/html; charset=windows-1252">
    +
    +
    +
    +
    +
    +
    +  <title></title>
    +  <meta name="GENERATOR" content="OpenOffice.org 2.2  (Win32)">
    +
    +
    +
    +
    +  <meta name="AUTHOR" content="Achim Pankalla">
    +
    +
    +
    +
    +  <meta name="CREATED" content="20060528;19455600">
    +
    +
    +
    +
    +  <meta name="CHANGEDBY" content="Achim Pankalla">
    +
    +
    +
    +
    +  <meta name="CHANGED" content="20070617;18142584">
    +
    +
    +
    +
    +  <style type="text/css">
    +	<!--
    +		@page { size: 21cm 29.7cm; margin: 2cm }
    +		P { margin-bottom: 0.21cm }
    +	-->
    +	</style>
    +</head>
    +
    +
    +<body dir="ltr" lang="de-DE">
    +
    +
    +
    +<p style="margin-bottom: 0cm; font-family: Times New Roman;" align="center"><font size="+1"><b>EEPROM Emulation f&uuml;r
    +PC</b></font></p>
    +
    +
    +<p style="margin-bottom: 0cm; text-align: center;"><font size="3"><b><small>Version 1.1 17-Sep-2007</small></b><br>
    +
    +
    +Achim Pankalla
    +(achim.pankalla@xxxxxx)</font></p>
    +
    +
    +<p style="margin-bottom: 0cm; height: 0px;"><br>
    +
    +
    +</p>
    +
    +
    +
    +<p style="margin-bottom: 0cm; font-style: normal; text-align: justify;"></p>
    +
    +
    +<div style="text-align: center;"><b>Beschreibung</b><br>
    +
    +
    +<div style="text-align: justify;">Die
    +EEPROM Emulation f&uuml;r den PC stellt das EEPROM des <i>Atmel
    +MEGA32(644) Prozessors</i> auch dem ct-Sim zur Verf&uuml;gung.
    +Der Zugriff auf dieses EEPROM erfolgt &uuml;ber gleichnamige
    +Funktionen, wie sie auch die avr-libc bereitstellt und auch die
    +Variablendefinition erfolgt &uuml;ber die gleichen Konstrukte. Eine
    +Unterscheidung &uuml;ber <span style="font-style: italic;">#ifdef</span>'s ist also nicht notwendig.<br>
    +
    +
    +Durch
    +diese EEPROM-Emulation ist der ct-Sim dem realen Bot einen Schritt
    +n&auml;her gekommen und Programme mit EEPROM-Zugriffe k&ouml;nnen mit
    +der Simulation getestet werden. Mehr noch, Sie k&ouml;nnen auch den
    +Inhalt des emulierten EEPROM auf den ct-Bot &uuml;bertragen oder das
    +EEPROM vom
    +ct-Bot laden und f&uuml;r die Emulation nutzen.</div>
    +
    +
    +</div>
    +
    +
    +<p style="margin-bottom: 0cm;" align="left"><br>
    +
    +
    +</p>
    +
    +
    +
    +<p style="margin-bottom: 0cm; text-align: center;"><b>Implementierung</b><br>
    +
    +
    +</p>
    +
    +
    +<div style="text-align: justify;">Alle Funktionen und Einstellungen der
    +EEPROM Emulation findet Sie in den Dateien <i>pc/eeprom-emu_pc.c</i>
    +und <i>include/eeprom-emu.h</i>. Das EEPROM selbst wird durch eine
    +bin&auml;re Datei (genau 1 KB bzw. 2 KB gro&szlig;) repr&auml;sentiert&nbsp;und
    +kann so mit einen HexEditor bearbeitet werden. Der Pfad mit Dateinamen befindet sich in den
    +Konstanten MCU_(PC_)<span style="font-style: italic;">EEPROM_FN</span> in der C-Datei. Standard Pfad ist das Heimatverzeichnis des
    +ct-Bots.&nbsp;<font face="Times New Roman, serif"></font><br>
    +
    +
    +Die
    +Datei wird automatisch neu angelegt, wenn sie noch nicht existiert,
    +dann wird die Datei automatisch mit den aktuellen Zuweisung der
    +EEPROM-Variablen initialisiert (mit Hilfe von ct-Bot.eep). Ist schon
    +eine <span style="font-style: italic;">eeprom.bin</span> vorhanden, so wird diese nicht ver&auml;ndert, ausser die ct-Bot.exe wird mit dem Parameter <span style="font-style: italic;">-i</span> gestartet, dann wird auch eine schon vorhandene Datei mit den vorhandenen Zuweisungen &uuml;berschrieben.<br>
    +
    +
    +Damit die
    +EEPROM-Funktionen des PC korrekt auf die Datei zugreifen k&ouml;nnen
    +darf nur ein Adressraum von 0 bis 1023 (bzw. 2047) entstehen.&nbsp;Die
    +Emulation muss also wissen welche Speicheradresse die
    +erste Variable im EEPROM hat, um diesen Wert von allen anderen
    +abzuziehen. Daf&uuml;r bedarf es bei
    +der PC Implementierung (mit PC ist allgemein der Code f&uuml;r den
    +ct-Sim gemeint, mag das OS nun Win, Linux oder Mac OS X hei&szlig;en)
    +eines Tricks.&nbsp;<br>
    +
    +
    +Daf&uuml;r gibt es die beiden Variablen
    +<i>_eeprom_start1__</i> und <i>_eeprom_start2_</i><span style="font-style: normal;">_
    +in </span><i>1st_init.S</i><span style="font-style: normal;">. Diese
    +stehen dort, damit sie auf jeden Fall vor der ersten EEPROM Variable
    +definiert werden und damit ihre Sections (.</span><i>s1eeprom</i> <span style="font-style: normal;">+
    +.</span><i>s2eeprom</i><span style="font-style: normal;">) auf jeden
    +Fall vor der Section .</span><i>eeprom</i> <span style="font-style: normal;">liegen.</span><br>
    +
    +
    +Durch diesen Trick
    +kann die Speicheradresse der ersten EEPROM Variable auch ohne
    +Linkerscript ermittelt werden und auch verschiedene
    +Section-Alignments (im Moment bei MinGW und Linux unterschiedlich)
    +haben keine Auswirkung.<br>
    +
    +
    +Auch beim
    +Generieren einer neuen Datei ct-Bot.exe/elf wird eine EEP mit den
    +Initialisierungen der EEPROM-Variablen im Post-Build angelegt. Diese
    +Datei kann&nbsp; die EEPROM-Emulation auch als Initialisierung f&uuml;r die <span style="font-style: italic;">eeprom.bin</span> im MCU-Modus benutzen. Sollte keine <span style="font-style: italic;">eeprom.bin</span> existieren, wird sie auch daf&uuml;r genutzt. Arbeitet man im PC-Modus, kann diese Datei auch in eeprom.bin umbenannt werden.<br>
    +
    +
    +Damit die Emulation m&ouml;glichst effektiv und schnell arbeiten kann, wird nach dem Start die gesamte Datei <span style="font-style: italic;">eeprom.bin</span> im Hauptspeicher gecached und nach jedem Schreibzugriff komplett neu geschrieben.<br>
    +
    +
    +Damit man die EEPROM-Datei auch auf den ct-Bot einspielen kann, oder
    +einen EEPROM Abzug &nbsp;des ct-Bot als emuliertes EEPROM nutzen kann,
    +werden Post-Builds ben&ouml;tigt, die die Adressen der einzelnen
    +Variablen auf ct-Bot und ct-Sim aufzeigen. Der EEPROM Manager wird beim
    +Start eines Bots im ct-Sim dann eine (Adress)Konvertierungstabelle
    +erstellen, um die Zugriffe auf das EEPROM anzupassen. Diese Tabelle
    +wird nach aufsteigenden Adressen des ct-Sim sortiert und nur im
    +MCU-Modus genutzt.</div>
    +
    +
    +
    +<p style="margin-bottom: 0cm;"></p>
    +
    +
    +<div style="text-align: center;"><b>Nutzung der EEPROM Emulation</b><br>
    +
    +
    +<div style="text-align: justify;">Die EEPROM-Emulation unterscheidet
    +sich nur in ein paar Details von den Funktionen der avr-libc f&uuml;r den realen ct-Bot.
    +Nat&uuml;rlich hat der PC kein EEPROM, dieses wird durch
    +eine&nbsp;Datei im Bin&auml;rformat emuliert. Der Dateinamen und der Pfad
    +wird &uuml;ber die Konstanten MCU_EEPROM_FN und PC_EEPROM_FN in <i>eeprom</i>-<i>emu</i>_<i>pc</i>.<i>c</i>festgelegt,
    +je nach Modus wird die entsprechende Datei angelegt. So kann man auch
    +am Dateinamen den Aufbau des EEPROMs erkennen. Wechselt der Modus, wird
    +die vorherige Datei gel&ouml;scht. Dadurch liegen immer die
    +Initialsierten EEPROM Variablen an der richtigen Stelle und ein
    +fehlverhalten der Bots in der Simulation wird vermieden.<br>
    +
    +
    +Ein weiterer Unterschied ist, dass beim avr-gcc &uuml;ber
    +ein DEFINE der Prozessortyp festgelegt wird, entweder ATMega32 oder
    +ATMega644. Dieses DEFINE ist beim PC Compiler normalerweise nicht
    +gesetzt. Standardm&auml;&szlig;ig wird von einem ATMega32 mit
    +1024 Byte EEPROM ausgegangen, Die Emulation kennt aber die Konstante
    +f&uuml;r den ATMega644 und erh&ouml;ht den EEPROM Speicher auf 2048
    +Bytes. Sollte schon eine 1 KB Datei f&uuml;rs EEPROM bestehen, so muss
    +diese gel&ouml;scht werden, damit die Gr&ouml;&szlig;ere angelegt
    +wird. Wird direkt die erstellte <i>ct-bot.eep</i> Datei im PC-Modus genutzt, ist
    +dies nat&uuml;rlich nicht notwendig. <br>
    +
    +
    +Alle wichtigen Informationen werden
    +beim Start von ct-Bot.exe/elf im Log-Fenster angezeigt, vorrausgesetzt es ist in <span style="font-style: italic;">ct-bot.h</span> aktiviert ist (zus&auml;tzlich bitte in <span style="font-style: italic;">eeprom-emu_pc.c</span> die Konstante <span style="font-style: italic;">DEBUG_EEPROM</span>
    +aktivieren), dort sieht man
    +auch alle eventuellen Fehler, den erreichten Emulationsmodus und ob die
    +Emulation ordnungsgem&auml;&szlig;
    +arbeiten kann. Es erfolgt kein Beenden bei
    +Problemen, die Funktion des EEPROMs ist dann aber nicht gegeben. Bei
    +Auff&auml;lligkeiten sollte man dann die LOG Funktion aktivieren.</div>
    +
    +
    +</div>
    +
    +
    +<p style="margin-bottom: 0cm;">Generell unterscheidet die Emulation
    +zwei Modi:</p>
    +
    +
    +<ol>
    +
    +
    +	<li>
    +
    +
    +    <p style="margin-bottom: 0cm;">PC-Modus<br>
    +
    +
    +In diesen Modus entspricht die
    +	<span style="font-style: italic;">eeprom.bin</span> nicht dem EEPROM des realen ct-Bots und darf deshalb auch
    +	nicht auf ihn aufgespielt werden. Dieser Modus wird ohne jedes Zutun erreicht.
    +	Er ben&ouml;tigt keine weiteren Eintr&auml;ge im Post-Build.&nbsp;Wenn eine <span style="font-style: italic;">ct-bot.eep</span> im Bin&auml;rformat erstellt wird,
    +	so kann diese direkt benutzt werden.</p>
    +
    +
    +	</li>
    +
    +
    +  <li>
    +
    +
    +
    +    <p style="margin-bottom: 0cm;">MCU-Modus<br>
    +
    +
    +Ist dieser Modus erreicht, kann man
    +	als EEPROM-Datei einen EEPROM Abzug vom ct-Bot verwenden.
    +	Voraussetzung ist nat&uuml;rlich, dass der Bot auch mit zuletzt
    +	erstelltem Programm bespielt ist. Nat&uuml;lich kann man auch die
    +	EEPROM-Datei <span style="font-style: italic;">eeprom.bin</span> auf dem ct-Bot aufgespielen.<br>
    +
    +
    +Der MCU-Modus kann nur erreicht
    +	werden, wenn sowohl beim avr-gcc als auch unter dem ct-Sim
    +	eine map-Datei erstellt wird, daf&uuml;r m&uuml;ssen im Post-Build die Befehle aus dem Kommentarkopf aus <span style="font-style: italic;">eeprom-emu_pc.c</span> ausgef&uuml;hrt werden.</p>
    +
    +
    +In den Projekteinstellungen im SVN sind die n&ouml;tigen Post-Build-Einstellungen f&uuml;r alle Betriebssysteme bereits gemacht.
    +	<br>
    +
    +
    +  </li>
    +
    +
    +</ol>
    +
    +
    +
    +<p style="margin-bottom: 0cm; text-align: justify;">M&ouml;chte man die vorhandene EEPROM-Datei mit den Daten aus der EEP-Datei
    +initialisieren, so muss man die ct-Bot.exe/elf mit dem Parameter <i>-i
    +</i>starten, dabei spielt es keine Rolle in welchen Modus die
    +Emulation arbeitet. Der Pfad der EEP-Datei wird in der Konstante
    +<font color="#000000"><font face="Courier New, monospace"><font size="2">EEP_PC
    + </font></font></font><font color="#000000"><font face="Times New Roman, serif"><font size="3">und die Pfade f&uuml;r die MAP-Dateien werden in den Konstanten EEMAP_PC und EEMAP_MCU eingetragen.<br>
    +
    +
    +Die Variable MAX_VAR legt die Gr&ouml;&szlig;e der Tabelle fest und
    +beschr&auml;ngt damit die maximale Anzahl der Variablen. Sollte die
    +Fehlermeldung auftreten, dass es zu viele Variablen gibt, muss man
    +diesen Wert nur erh&ouml;hen. <br>
    +
    +
    +</font></font></font></p>
    +
    +
    +<font color="#000000"><font face="Times New Roman, serif"><font size="3">F&uuml;r
    +das Debuggen von Zugriffen auf das EEPROM stehen unter anderem die
    +DEFINES LOG_STORE und LOG_LOAD zur Verf&uuml;gung, die im MCU Modus
    +sogar den Variablennamen anzeigen. Andere Variationen sind auch noch
    +denkbar.</font></font></font>
    +<p style="margin-bottom: 0cm;"></p>
    +
    +
    +
    +<div style="text-align: center;"><b>Grenzen der
    +Implementierung</b><br>
    +
    +
    +<div style="text-align: justify;">Im Moment erstellen gleiche Compilerversionen (zu &uuml;berpr&uuml;fen
    +mit --version) auch (fast) gleiche EEPROM-Sections. Damit es
    +auch mit verschiedenen Compiler Version geht (und ich mich auch nicht
    +auf die gleichen Versionen verlasssen will) habe ich die
    +Adresskonvertierung eingef&uuml;hrt, damit dies kein Problem mehr
    +ist. Es gibt aber keine Garantien daf&uuml;r, dass zuk&uuml;nftige Compiler
    +Versionen nicht die Reihenfolge der Variablen im Code &auml;ndern.
    +<span style="color: rgb(0, 0, 0);">Ein Einf&uuml;gen neuer EEPROM Variablen kann auch zu Verschiebungen
    +der Adressen f&uuml;hren. Nach solchen &Auml;nderungen (auch ein &auml;ndern der Compilerversion) ist man nur
    +auf der sicheren Seite, wenn das EEPROM initialisiert wird (sprich,
    +Sie Ihre alte </span><span style="font-style: italic; color: rgb(0, 0, 0);">eeprom.bin</span><span style="color: rgb(255, 0, 0);"><span style="color: rgb(0, 0, 0);"> bzw. auf dem Atmel das EEPROM l&ouml;schen) und f&uuml;r MCU und ct-Sim neue Exe generiert werden</span>.</span>
    +Einmal erstellte Werte sind dann nat&uuml;rlich futsch. Wenn man den
    +Einfluss von Codeerg&auml;nzungen kontrollieren will, kann man dies
    +vor und nach der &Auml;nderung mit <span style="font-style: italic;">objdump</span> machen (oder falls Sie
    +die Befehle f&uuml;r die MAP-Dateien im Post-Build benutzen, schauen
    +Sie in die MAP-Dateien), mit den richtigen Parametern kann man sich
    +die Adressverteilung anzeigen lassen. Sie k&ouml;nnen dann sehen, ob
    +die neuen Variablen nun hinten angeh&auml;ngt wurden (dann brauch das
    +EEPROM nicht gel&ouml;scht werden) oder sie dazwischen gelandet sind
    +(dann sind die alten Daten unbrauchbar), daf&uuml;r sollten sie aber
    +vorher in Eclipse <span style="font-style: italic;">Projekt-&gt;clean</span> aufrufen.<br>
    +
    +
    +Der Compiler kann aufgrund der Implementierung
    +des EEPROMs auf dem PC nicht kontrollieren, ob mehr als 1024/2048 Bytes
    +f&uuml;r die Variablen ben&ouml;tigt werden, er kennt diese Begrenzung
    +nicht. Der EEPROM-Manager meckert dann aber
    +im LOG. </div>
    +
    +
    +</div>
    +
    +
    +
    +<p style="margin-bottom: 0cm;"></p>
    +
    +
    +<div style="text-align: center;"><span style="font-weight: bold;">Verschiedenes</span><br>
    +
    +
    +<div style="text-align: justify;">Ein besonderer Dank an dieser Stelle
    +an Timo Sandmann unter anderem f&uuml;r das Testen unter MacOSX und
    +f&uuml;r verschiedene Anpassungen, Optimierungen und f&uuml;r den
    +Assemblercode in 1st_init.S ohne den wohl st&auml;ndige Probleme
    +unvermeidlich gewesen w&auml;ren.<br>
    +
    +
    +Dank auch an alle anderen f&uuml;r konstruktive Kritik, die die
    +jetzige, ich denke annehmbare, L&ouml;sung erst m&ouml;glich machte und
    +meiner Familie f&uuml;r ihre unendliche Geduld. <br>
    +
    +
    +M&ouml;ge sich jeder eingeladen f&uuml;hlen etwas zu verbessern oder erweitern.<br>
    +
    +
    +
    +</div>
    +
    +
    +</div>
    +
    +
    +
    +<p style="margin-bottom: 0cm;"><b>Funktionen</b><br>
    +
    +
    +init_eeprom_man() - Erledigt alle Arbeiten zur Aktivierung der EEPROM-Emulation<br>
    +
    +
    +</p>
    +
    +
    +<p style="margin-bottom: 0cm;"><b>Nur in eeprom-emu_pc.c sichtbare
    +Funktionen</b></p>
    +
    +
    +conv_eeaddr() - Wandelt PC Adresse in
    +ct-Bot Adresse<br>
    +
    +
    +create_ctab() - Erstellt
    +Adresskonvertierungstabelle<br>
    +
    +
    +check_eeprom_file() - Erstellt leeres
    +EEPROM, wenn n&ouml;tig und initialisiert es, wenn gew&uuml;nscht<br>
    +
    +
    +flush_eeprom_cache() - Schreibt ver&auml;nderte Daten in eeprom.bin<br>
    +
    +
    +
    +<p style="margin-bottom: 0cm;"><b>Zugriffsfunktionen f&uuml;r den PC
    +(identisch zu denen der avr-libc)</b><br>
    +
    +
    +eeprom_read_byte()<br>
    +
    +
    +eeprom_write_byte()<br>
    +
    +
    +eeprom_read_word()<br>
    +
    +
    +eeprom_write_word()<br>
    +
    +
    +eeprom_write_block()<br>
    +
    +
    +eeprom_read_block()</p>
    +
    +
    +
    +<p style="margin-bottom: 0cm;"><font size="3"><b>Dateien</b></font><br>
    +
    +
    +</p>
    +
    +
    +<div style="text-align: center;">
    +<div style="text-align: left;">eeprom-emu.h - Headerdatei mit den Deklarationen<br>
    +
    +
    +eeprom-emu_pc.c - Implementierung der Funktionen
    +f&uuml;r ct-Bot &amp; ct-Sim<br>
    +
    +
    +<font size="3">1st_init.S - Sorgt f&uuml;r das korrekte Anlegen der Hilfsvariablen in der Exe</font></div>
    +
    +
    +</div>
    +
    +
    +<p style="margin-bottom: 0cm;"><br>
    +
    +
    +</p>
    +
    +
    +<p style="margin-bottom: 0cm;"><br>
    +
    +
    +</p>
    +
    +
    +<p style="margin-bottom: 0cm;"><br>
    +
    +
    +</p>
    +
    +
    +</body>
    +</html>

- Antworten:
  - Re: AW: AW: [ct-bot] EEPROM-Emu... -> Bug gefunden !
    - From: Timo Sandmann

- Referenzen:
  - AW: AW: [ct-bot] EEPROM-Emu... -> Bug gefunden !
    - From: Frank Menzel
  - Re: AW: AW: [ct-bot] EEPROM-Emu... -> Bug gefunden !
    - From: Timo Sandmann
  - Re: AW: AW: [ct-bot] EEPROM-Emu... -> Bug gefunden !
    - From: Achim Pankalla

- Voriger (Datum): Re: [ct-bot] Liniensensoren ?, Timo Sandmann
- Nächster (Datum): Re: AW: AW: [ct-bot] EEPROM-Emu... -> Bug gefunden !, Timo Sandmann
- Voriger (Thread): Re: [ct-bot] Liniensensoren ?, Timo Sandmann
- Nächster (Thread): Re: AW: AW: [ct-bot] EEPROM-Emu... -> Bug gefunden !, Timo Sandmann
- Indizes:
  - Datum
  - Thread