-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: Zeiger auf eine Funktion im Flash.

  1. #1
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236

    Zeiger auf eine Funktion im Flash.

    Anzeige

    Hallo,
    irgendwie verstehe ich das jetzt mit den Pointern auf Flashspeicher nicht

    Als Beispiel hier ein Miniprogramm in C:

    Code:
    #include<stdio.h>
    
    void zeige(void) {
    
      printf("Hallo, hier  bin ich\n");
    }
    
    void zeige2(void) {
      printf("und hier noch einmal\n");
    }
    
    int main(void) {
      typedef void (*funktion) (void);
    
      funktion feld[] = {&zeige,&zeige2};  
    
      feld[0]();
      feld[1]();
      return 0;
    }
    Es hat nicht viel Sinn, soll einfach nur deutlich machen, wo mein Problem liegt.

    Auf dem PC klappt es ja Prima, auf dem AVR hol ich mir ja irgendwelche RAM Adressen .

    Ich weiß daß es an der Harvard Architektur und an den getrennten RAM/FLASH/EEPROM Adressräumen liegt, es ist auch kein Problem Daten zu lesen, nur halt mit Zeigern krieg ich das nicht hin
    Aus der Doku zu avr-gcc werde ich auch nicht schlauer...


    Könnte mir mal jemand unter die Arme greifen und mir mal sagen wie ich das Miniprogramm in AVR implementiere ?

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    07.07.2006
    Ort
    Mannheim
    Beiträge
    454
    Die Daten im Flash sind 16 Bit, ein Character aber nur 8 Bit. Du mußt die Pointer adresse * 2 nehmen.

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo JonnyP,

    würden wir hier von AVR Pointern sprechen, würde ich Dir recht geben, es geht sich aber um die C Zeiger und die haben damit nichts zu tun.

    Trotzdem danke für die Antwort, ich komme schon langsam selber auf die Lösung
    Software is like s e x: its better when its free.
    Linus Torvald

  4. #4
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Ich hab da ein beispiel, da läuft das so:
    Code:
    void HeartbtAct(UNIT* pUnit, unsigned char Cmd, unsigned short Param)
    {
    }
    // --------------------------------------------------- 
    UNIT* HeartbtBuild(UNIT* pUnit, unsigned char UnitClass,  unsigned char UnitIdent)
    {
    	pUnit->iVect	= (int)HeartbtAct;  //SETZEN VECTOR
    }
    
    .....
    
    später dann:
    
    union {void (*vVec)(UNIT* pUnit, unsigned char Cmd, unsigned short Param);
    	int iVec;
    	} Vec;
    
    UNIT* 	pUnit	= (UNIT*)pMsg->iUnit;    
    		Vec.iVec = pUnit->iVect;   // HOLEN VECTOR
    
    		(*Vec.vVec)(pUnit, pMsg->bCommand, pMsg->wParam);
                 // und aufrufen
    Sieht wüst aus, aber du siehst, eigentlich brauch ich da nix tricksen

    Ich hoff', Du kannst Dir das ausdeutschen ?
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801

    Re: Zeiger auf eine Funktion im Flash.

    Code:
    typedef void (*function_t) (void);
    
    extern void zeige  (void);
    extern void zeige2 (void);
    
    function_t feld[] = {zeige, zeige2};  
    
    void caller (int addr, function_t zeige3) 
    {
    
      feld[0]();
      feld[1]();
      zeige3();
      ((void(*)(void)) addr) ();
    }
    Zitat Zitat von izaseba
    Könnte mir mal jemand unter die Arme greifen und mir mal sagen wie ich das Miniprogramm in AVR implementiere?

    Gruß Sebastian
    Geht genauso.

    Obiger Code assemblier avr-gcc so:
    Code:
    	.file	"foo.c"
    	.arch atmega8
    __SREG__ = 0x3f
    __SP_H__ = 0x3e
    __SP_L__ = 0x3d
    __tmp_reg__ = 0
    __zero_reg__ = 1
    	.global __do_copy_data
    	.global __do_clear_bss
    .global	feld
    	.data
    	.type	feld, @object
    	.size	feld, 4
    feld:
    	.word	pm(zeige)
    	.word	pm(zeige2)
    	.text
    .global	caller
    	.type	caller, @function
    caller:
    /* prologue: frame size=0 */
    	push r14
    	push r15
    	push r16
    	push r17
    /* prologue end (size=4) */
    	movw r14,r24
    	movw r16,r22
    	lds r30,feld
    	lds r31,(feld)+1
    	icall
    	lds r30,feld+2
    	lds r31,(feld+2)+1
    	icall
    	movw r30,r16
    	icall
    	movw r30,r14
    	icall
    /* epilogue: frame size=0 */
    	pop r17
    	pop r16
    	pop r15
    	pop r14
    	ret
    /* epilogue end (size=5) */
    /* function caller size 25 (16) */
    	.size	caller, .-caller
    /* File "adc.c": code   25 = 0x0019 (  16), prologues   4, epilogues   5 */
    Disclaimer: none. Sue me.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo,
    Danke erstmal.

    Ich glaube, ich hab mich falsch ausgedrückt.

    Sprinter, bei Deinem Beispiel klappt das, weil der Compiler die Adressen direkt einsetzen kann ? Kann das sein ?

    Ich meine Hier:
    Code:
    feld[0]();
    feld[1]();
    Die Adressen stehen zu Kompilierzeit fest und müßen nicht im laufendem Betrieb geholt werden.
    Ich glaube, wenn man eine Variable bei dem Arrays verwenden würde würde es nicht klappen ?

    Aber nochmal ein Beispiel:

    Ich habe ein paar Strings in Flash gelegt:
    Code:
     const char menuhauptstr[] PROGMEM = "Hauptmenu"; 
     const char menukontstr[] PROGMEM = "Kontrast";
     const char menuhellstr[] PROGMEM = "Helligkeit";
     const char menufrage[] PROGMEM = "Speichern ? ";
    dann eine Struktur :
    Code:
    struct MENU  {
      const char *Menu_Name;
      uint8_t Entrie_up;
      uint8_t Entrie_down;
      uint8_t Entrie_right;
      uint8_t Entrie_left;
      void(*Menu_Funkt)(void);
    };
    Zum Schluß ein Array mit diesen Strukturen im Flash:
    Code:
    const struct MENU menu[] PROGMEM = {
      {menuhauptstr,3,1,10,15,Draw_Main},
      {menuhellstr,0,2,10,15,Draw_Hell},
      {menukontstr,1,3,10,15,NULL},
      {menufrage,2,0,1,0,NULL}
    };
    Will ich jetzt z.B. mit:
    Code:
    menu[i].Menu_Funkt();
    Meine Funktion aufrufen, klappt das nicht.
    Ich habe gelesen, daß man sich die Adresse zuerst mit (const char *)pgm_read_word(menu) holen muß, nur irgendwie krieg ich das nicht hin

    Ich hab es jetzt so gelöst, daß ich mein Array in RAM gelegt habe, dann geht alles wunderbar.

    Ich glaub, entweder hab ich den Kapitel über Pointer bei Kernighan u. Ritchie oder die Harvald Architektur nicht verstanden.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Dei Adresse muss nicht bekannt sein. Zwei Adressen in meinem Beispiel ergeben sich werst zur Laufzeit, andere zur Linkzeit (extern...). Woher die Adressen sind ist ja egal.

    Code:
    function_t func = (function_t) pgm_read_word (& menu[i].Menu_Funkt);
    func();
    oder
    Code:
    ((function_t) pgm_read_word (& menu[i].Menu_Funkt))();
    Das Problem mit der Harvard-Architektur und GCC ist, daß man Flash-Adressen (dito EEPROM) als Attribut angibt, und nicht wie es sein müsste als Qualifier (so wie const, volatile, unsigned, ...). Das macht vielerorts Probleme. U.a weiß GCC beim zugriff nicht, wie er darauf zugreifen soll. Etwa wenn ein Zeiger in eine Funktion run kommt: ist es RAM-Adresse? EEPROM? oder Flash? Deshalb muss man umständlich mit den pgm_read/write Zeug arbeiten.

    Für andere Architekturen (linearere Adressraum) hätte man einfach sagen können
    #define pgm_read_byte(addr) (*((uint8_t*) addr))
    bzw
    #define pgm_read_byte(addr) (* addr)
    wenn addr ein Zeiger aud uint8_t ist.

    Wenn du eine Struktur im Flash hast musst du eben die Komponenten per pgm_xxx holen/schreiben:

    x = a.b; --> pgm_read_block (&x, &a.b, sizeof (a.b));
    x = a->b; --> pgm_read_block (&x, &a->b, sizeof (a->b));
    Disclaimer: none. Sue me.

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Beachte auch, daß du für die Strings zwei Induirektionen via pgm_xxx drinne hast (die zeite wohl in deiner out-Routine, die nen Zeiger ins Flash bekommt.

    Code:
    void foo (uint8_t i)
    {
    	((void(*)(void)) pgm_read_word (& menu[i].Menu_Funkt)) ();
    }
    ergibt übrigens

    Code:
    foo:
    	mov r30,r24
    	clr r31
    	ldi r24,3
    1:	lsl r30
    	rol r31
    	dec r24
    	brne 1b
    	subi r30,lo8(-(menu+6))
    	sbci r31,hi8(-(menu+6))
    /* #APP */
    	lpm r24, Z+
    	lpm r25, Z
    /* #NOAPP */
    	movw r30,r24
    	icall
    	ret
    Disclaimer: none. Sue me.

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Danke,
    ich glaub es hat klick gemacht
    function_t func = (function_t) pgm_read_word (& menu[i].Menu_Funkt);
    func();
    Ich habe hier immer auf (const char) gecastet warum auf immer , jetzt hab ich wieder was zum probieren

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Ich hab den entsprechenden Abschnitt im C-Tutorial mal ausgefüllt. Hätte nicht gedacht, daß jemand Funktionszeiger benutzt

    http://www.roboternetz.de/wissen/ind...auf_Funktionen

    Ein Beispiel haz's auch in

    http://www.roboternetz.de/wissen/ind...#Sprungtabelle
    Disclaimer: none. Sue me.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •