www.mikrocontroller.net

Forum: Compiler & IDEs Dynamischer Funktionsaufruf mit struct als call by value funktioniert nicht.


Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

ich bastle gerade an einen recht universellen Kommunikationsstack für 
verschiedene Plattformen.
Prinzipiell wird über ein zu definierendes Interface ein Paket empfangen 
(und vom Stack zusammengesetzt). Wenn der Empfang soweit erfolgreich war 
(versch. Checksummen etc. stimmen) wird das Paket an das "Protokoll" an 
das es adressiert ist, weitergereicht. Das "Protokoll" besteht aus einer 
Funktion, die beim Stack (in Form eines Funktionspointers in einem Array 
aus Handles (s.u.)) registriert wird. Diese Funktion übernimmt als 
Parameter (in der non-dynamic-memory-version des Stacks) das Paket (in 
Form eines structs) als call by value (by reference ist nicht möglich; 
der Empfangsbuffer ist nach der Übergabe wieder freigegeben...) der 
Funktion übergeben.
Soweit die Theorie. Problem: Die Übergabe funktioniert nicht.
Ich habe den Code soweit getestet, das Programm kommt beim dynamischen 
Aufruf an; die Funktion wird aber nicht aufgerufen...

Der Code ist sehr umfangreich und in x Dateien verteilt ich versuche das 
relevante herauszufiltern...
(Außer ihr wollt das gesamte Projekt in seinem gesamten Umfang haben; 
das wären dann 62 Dateien und ~2700 Zeilen nur Code...)

Typen:
///the packet itself
struct _com_packet{
    uint16_t partner_lla;
    uint8_t partner_hla;
    uint8_t protocol;
    uint8_t data[com_max_payload_data+1];
    uint8_t size, filled;
    uint8_t sequence;
    com_packet_FrameMode mode; //simple enum
    com_packet_broadcast bc; //simple enum
};
typedef struct _com_packet com_packet;


///The com protocol takeover function pointer
typedef void (* com_FPTR) (com_packet);


//der handle-array-typ
struct com_struct_protocol_handle {
    uint8_t     protocol;
    com_FPTR    function;
};
typedef struct com_struct_protocol_handle com_protocol_handle;


//zu guterletzt das protokoll-lookup-array, nothing special:
com_protocol_handle com_rx_protocol_handles[com_rx_protocol_handle_size];

Die Funktion zum Registrieren der Protokolle:
/**
Function to register a protocol object. When you use a protocol object, you have to register it with this function.
It will "familiarize" COM with the object (it MUST be derivated from com_protocol) and link it to its UPID (used protocol id)
    @param[in,out] *p pointer to the protocol object
    @param[in] id the upid
    @return bool (allways true)

*/
bool com_RegisterProtocol(com_FPTR p, uint8_t id){    //registers a protocol to the interface.

    uint8_t i = 0;

    for(i = 0; i < com_rx_protocol_handle_size ; i++){
        if(com_rx_protocol_handles[i].protocol == 255){
            com_rx_protocol_handles[i].protocol = id;
            com_rx_protocol_handles[i].function = p;
            com_rx_protocol_handle_amount++;
            return true;
        }
    }

    return false;
}

//Beispielaufruf:

com_RegisterProtocol(rfCMD_TakePacket, rfCMD_pid);


Eine Protokoll-Funktion:
/**
Function which takes the packet.
    @param *p the packet to work with.
    @return bool success / fail
*/
void rfCMD_TakePacket(com_packet p){

    uint8_t *data;

    data = p.data;

    PORTB |= (1<<4);
    PORTB ^= (1<<3);

    switch(data[0]){

        case rfcmd_report_in:
            PORTB |= (1<<2);
        break;
    }

}
(Die LEDs an PortB gehen NICHT an...)

So. Nun die Handover-Funktion. Diese Funktion ist dafür zuständig das 
Protokoll-handle-array zu durchsuchen und die entsprechende Funktion zu 
callen:
/**
Function to hand over a received packet to the specified protocol (next_protocol field)
    @param[in] *p pointer to the packet
    @return code \li \c 0 = success \li \c 255 = failure (buffer full)
*/
uint8_t com_handover(com_packet p){
    uint8_t     i = 0, j = 255;

    for(i = 0 ; i < com_rx_protocol_handle_amount ; i++){
        if(com_rx_protocol_handles[i].protocol == p.protocol){
            //PORTB ^= (1<<3); //funktioniert
            com_rx_protocol_handles[i].function(p); //<- FUNKTIONIERT NICHT???
            j = 0;

            break;
        }
    }

    return j;
}

Ich weiß dass es nicht gerade praktisch ist, nicht den gesamten Code zu 
posten; aber ich habe - wie gesagt - das Problem bereits auf diesen 
Bereich eingegrenzt.

Ich habe mir gedacht dass es evtl. ein Stack-Problem sein könnte; finde 
aber keine Möglichkeit den Stack manuell zu vergrößern?
Irgendein Runtime-Problem...
Ich verwende WinAVR-20080610 mit Code::Blocks; mein Code compiliert 
völlig anstandslos.

Jemand ne Idee?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:


Hast du bereits mehrere Protokolle angemeldet und auch wieder entfernt?
Wenn ja, dann musst du eventuell beachten (je nachdem was du in der 
remove Funktion machst), dass der Wert in com_rx_protocol_handle_amount 
nicht bedeutet, dass die ersten com_rx_protocol_handle_amount Einträge 
gültig sind, sondern nur, dass es im Array insgesamt 
com_rx_protocol_handle_amount gültige Handler gibt.


Ergo:
> uint8_t com_handover(com_packet p){
>     uint8_t     i = 0, j = 255;
>
>     for(i = 0 ; i < com_rx_protocol_handle_amount ; i++){

      for(i = 0; i < com_rx_protocol_handle_size ; i++){

>         if(com_rx_protocol_handles[i].protocol == p.protocol){
>             //PORTB ^= (1<<3); //funktioniert
>             com_rx_protocol_handles[i].function(p); //<- FUNKTIONIERT
> NICHT???

Hier wäre eine Absicherung angebracht und versuch mal die 'schöne 
Funktion über Pointer rufen'-Syntax, auch wenn es eigentlich keinen 
Unterschied machen sollte:

              if( com_rx_protocol_handles[i].function )
                (*com_rx_protocol_handles[i].function)(p);


Das Handles Array hast du sauber initialisiert?

Du solltest dir auch noch überlegen, wieviele Kopien des Pakets du noch 
machen möchtest (kostet ja alles Zeit und Speicher). In com_handover 
wird schon 1 Kopie erzeugt und beim Aufruf der Protokollfunktion wird 
die nächste Kopie erzeugt. Wenn du so weiter machst, wird dir ziemlich 
schnell, vor allem auf kleineren µC, der Speicher ausgehen, zumal 
com_max_payload_data ja wohl auch nicht gerade klein sein wird.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

die Möglichkeit Protokolle zu entfernen gibt es (noch) nicht (es könnten 
u.A. auch Lücken im Lookup entstehen etc.). Daher sollte 
com_rx_protocol_handle_amount immer up to date sein ... eigentlich.

Ja, die Arrays werden initialisiert:

void com_init_internal(uint16_t myLLA, uint8_t myHLA, uint8_t netmask, uint16_t gatewayLLA){
    uint8_t i = 0;

    com_IF_init();
    com_IF_stop_time();

    com_in_state = 0;
    com_in_count = 0;
    com_in_error = 0;

    com_out_buffer_count = 0;

    com_my_hla = myHLA;
    com_my_hla_netmask = netmask;

    com_my_lla = myLLA;

    com_my_gateway_lla = gatewayLLA;

    for(i = 0 ; i < com_tx_frame_buffer_size ; i++){
        com_tx_frame_buffer_index[i] = 0xFF; // initialize index array
        com_tx_frame_buffer[i].sequence = 0;
        com_tx_frame_buffer[i].protocol = 255;
    }

//Initialisierung des Handle-arrays; protocol == 255 -> "leeres" handle
    for(i = 0 ; i < com_rx_protocol_handle_size ; i++){
        com_rx_protocol_handles[i].protocol = 255;
    }

    com_RegisterProtocol(p0_TakePacket, 0);
}

Diese Funktion wird in der globalen Innitialisierungsmaloche aufgerufen, 
und danach gleich die Protokolle registriert:
//[...]
com_init_internal(LLA, HLA, NETMASK, GATEWAY); //see settings.h
com_RegisterProtocol(rfDATA_TakePacket, rfDATA_pid);
com_RegisterProtocol(rfCMD_TakePacket, rfCMD_pid);
//[...]

Ich hab deinen Rat mal in die Tat umgesetzt:
/**
Function to hand over a received packet to the specified protocol (next_protocol field)
    @param[in] *p pointer to the packet
    @return code \li \c 0 = success \li \c 255 = failure (buffer full)
    @todo uC: check for EXISTENT protocol 0...!
    @todo check
*/
uint8_t com_handover(com_packet p){
    uint8_t     i = 0, j = 255;

    for(i = 0 ; i < com_rx_protocol_handle_amount ; i++){
        if(com_rx_protocol_handles[i].protocol == p.protocol){
            //PORTB ^= (1<<2);

            if( com_rx_protocol_handles[i].function ){
                (*com_rx_protocol_handles[i].function)(p);
            }else{
                PORTB |= (1<<2);
            }

            j = 0;

            break;
        }
    }

    return j;
}
Leider bleibt PortB2 LOW und sonst auch alles beim Alten. An einem 
fehlerhaften Pointer liegts also wohl auch nicht...

Es wäre evtl. noch zu erwähnen, dass meine Display-Menu-Library ( 
http://www.tobias-schlegel.de/?page_id=382 ), die auch mit dynamischen 
Funktionscalls arbeitet (allerdings ohne Übergabeparameter), auf dem 
selben System anstandslos funktioniert.

Tjoa. Ich bin ratlos.
Danke auf jeden Fall!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:


Mach da mal ganz schnell ...

> //Initialisierung des Handle-arrays; protocol == 255 -> "leeres" handle
>     for(i = 0 ; i < com_rx_protocol_handle_size ; i++){
>         com_rx_protocol_handles[i].protocol = 255;

          com_rx_protocol_handles[i].function = NULL;

>     }

... rein.
Einen Pointer lässt man nicht auf irgendeinem Wert rumstehen.


> uint8_t com_handover(com_packet p){
>     uint8_t     i = 0, j = 255;
>
>     for(i = 0 ; i < com_rx_protocol_handle_amount ; i++){

Noch mal.
Hier nicht über amount gehen.
Wenn der Wert aus irgendeinem Grund nicht stimmt, bist du angeschmiert.
Dein Array ist com_rx_protocol_handle_size gross, also solltest du auch 
das ganze Array abgrasen, egal in welchem Zustand es ist.

Über die size zu gehen ist weder schneller noch langsamer. Aber du hast 
die Sicherheit, dass der Handler auf jeden Fall gefunden wird, wenn der 
eigentliche Eintrag stimmt. Die amount Variable braucht im Grunde kein 
Mensch und ist 'nice to have' aber ansonsten ist es nur ein Wert der 
falsch sein kann.

Aber das wird jetzt, zu diesem Zeitpunkt, nicht dein eigentliches 
Problem sein.

> Leider bleibt PortB2 LOW und sonst auch alles beim Alten. An einem
> fehlerhaften Pointer liegts also wohl auch nicht...

Extrahiere einmal den ganzen Handler-Teil in ein eigenständiges Projekt, 
damit du erst mal den ganzen restlichen Overhead zum Testen los wirst. 
Dann kann man auch auf dieser Seite des Schirms den kompletten Code 
untersuchen anstatt immer nur Fragmente.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich sehe da auch keinen Fehler, außer wie bereits genannt
die Übergabe als Kopie auf dem Stack.

Hilfreich wäre es, ein vollständiges und möglichst kleines
komplettes Programm mit dem Fehler zu sehen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Über die size zu gehen ist weder schneller noch langsamer. Aber du hast
> die Sicherheit, dass der Handler auf jeden Fall gefunden wird, wenn der
> eigentliche Eintrag stimmt. Die amount Variable braucht im Grunde kein
> Mensch und ist 'nice to have' aber ansonsten ist es nur ein Wert der
> falsch sein kann.

Pikanterweise sehe ich zb. in deiner Init Funktion nirgends, das dieser 
Wert irgendwann einmal auf 0 gesetzt worden wäre.

Also: Komm ohne ihn aus. Du brauchst ihn nicht. Und wenn du ihn 
tatsächlich mal für irgendetwas benötigst (zb Anzeigen), kannst du 
genausogut im Array die belegten Plätze abzählen. Ist sicherer. Alte 
Datenbankweisheit: Speichere niemals denselben Sachverhalt zweimal ab. 
Im besten Fall hast du einfach nur Redundanz. Im schlimmsten Fall hast 
du widersprüchliche Werte.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Ok, ich verwende jetzt ..._size .. auch ohne Erfolg. Der Pointer wird 
jetzt auch initialisiert.
Ich hab euch alles mal in ein kleines (20 Files und ~900 Zeilen code 
only) funktionsfähiges (incl. Fehler) Beispiel zusammengepfercht (-> 
Anhang). (Einfach alle Files compilieren und dann alles zammenlinken...)

Ich habe das File auch auf meinen AVR überspielt; der Fehler tritt auch 
hier auf (ich kann die LED aus der handover-Funktion ein und aus 
schalten, aber den Rest nicht); was sehr gegen den Stack spricht, da 
jetzt das halbe AVR-Ram leer sein dürfte (Korrektur >90% sind leer).

Ich versuche jetzt mal eine Übergabe by Reference mit anschließender 
Kopie des Inhalts...

hm hm hm.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:

> Ok, ich verwende jetzt ..._size .. auch ohne Erfolg. Der Pointer wird
> jetzt auch initialisiert.
> Ich hab euch alles mal in ein kleines (20 Files und ~900 Zeilen code
> only) funktionsfähiges (incl. Fehler) Beispiel zusammengepfercht (->
> Anhang).

Sei mir nicht böse.
Aber das ist nicht klein.

Klein ist
void foo( com_packet p )
{
  ;
}

int main()
{
  com_packet p;

  p.protocoll = 8;

  com_init_internal( ... );
  com_RegisterProtocol( foo, 8 );

  com_handover( p );
}

Und alles, was nichts mit diesen 3 Zeilen in main zu tun hat (Frames und 
sonstiges) fliegt erst mal raus oder wird auskommentiert oder mittels 
#define/#ifdef stillgelegt.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das Ding halt so gehalten um es auch auf der Zielhardware 
testen zu können...

Puh. Ich seh mal was man da machen kann...

Please hold the line...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:
> Ich habe das Ding halt so gehalten um es auch auf der Zielhardware
> testen zu können...

Nur haben wir die hier nicht.
Zuerst müssen wir sicherstellen, dass der Effekt real ist und nicht 
durch irgendwelche Nebeneffekte von Code, der erst mal nichts mit deinen 
Handlern zu tun hat, entsteht (ein Array Overflow irgendwo kömmt mir da 
zb ganz schnell in den Sinn)

Bau in foo von mir aus eine LED Ausgabe rein, das ist schon ok.
Irgendwas, damit du auf deiner Zielhardware mit der absoluten 
Mindestsoftware den Effekt überprüfen kannst.

Aber es muss soviel wie möglich abgespeckt werden! Natürlich nur soviel, 
dass der Effekt noch da ist. Wenn obiges mit einer LED-Ausgabe in foo 
funktioniert, dann gibt es höchst wahrscheinlich irgendeine ungewollte 
Interaktion mit einem anderen Softwaremodul. Das wird dann schwieriger 
zu finden. Aber zumindest hat man dann einen kleinen Anhaltspunkt wonach 
man suchen muss. Aber 20 Files aufs Geratewohl zu durchforsten, ist 
nicht sehr zielführend.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch eines noch:
Auf welchem AVR testest du?

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also, so abgespeckt wie nur geht.

Lustiger Weise schient die hier Sache zu funktionieren...

Ein überlaufenes Array o.ä. ist denk ich tatsächlich ein guter Kandidat.

stand by...

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Atmega32 @16Mhz

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mir dein großes Projekt ins AVR Studio gezogen. Aber da pasiert 
einfach zuviel und das Faken einer Übertragung im Debugger ist dort 
extrem mühsam.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:
> Also, so abgespeckt wie nur geht.
>
> Lustiger Weise schient die hier Sache zu funktionieren...
>
> Ein überlaufenes Array o.ä. ist denk ich tatsächlich ein guter Kandidat.

OK. Das ist schon mal was.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Ich hab mir dein großes Projekt ins AVR Studio gezogen. Aber da pasiert
> einfach zuviel und das Faken einer Übertragung im Debugger ist dort
> extrem mühsam.


Wenn du es so hinkriegen könntest, dass von gefakten UART-Funktionen die 
richtigen Bytes in der richtigen Reihenfolge in die Übertragungskette 
eingespeist werden, wäre das extrem hilfreich (jetzt bezogen auf dein 
'großes' Testprojekt)

Sowas in der Art
static unsigned char Fake[] = "was auch immer über die Schnittstelle kommen"
                              "muss um letztendlich den Call auszulösen";
static int nextByte = 0;

bool com_IF_check_byte_ready()
{
  return true;
}

unsigned char com_IF_read_byte()
{
  nextByte++;
  return Fake[NextByte];
}

Du könntest auch bei den uart Funktionen (also noch tiefer) diesen Fake 
aufsetzen.

Im Idealfall brauch ich mich um nichts kümmern, setz mir einen 
Breakpoint in die handle Funktion, lass das Teil laufen und lande 
irgendwann beim Breakpoint. So ein Fake ist sowieso sehr hilfreich, weil 
du dann bei jedem Testlauf identische Bedingungen hast (und ich 
dieselben Daten habe, die du auch benutzt)

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier eine com_interface.c mit gefaketem Interface; wie bestellt.

Das Paket ist ein low-level Broadcast mit dem Befehl 1 an das Protokoll 
1... sollte funktionieren.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:
> Hier eine com_interface.c mit gefaketem Interface; wie bestellt.
>
> Das Paket ist ein low-level Broadcast mit dem Befehl 1 an das Protokoll
> 1... sollte funktionieren.

Hmm.
Habs im AVR Studio für einen Mega16 compiliert und ... funktioniert so 
wie gedacht. Die Funktion wird aufgerufen. Habe beides -O0 und -Os 
ausprobiert.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmmm ... ich hab den Simulator auch mal installiert...

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, im Simulator gehts; im Reallife gehts nicht.
Somit fängts hiermit an, kompliziert zu werden... oder..?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:
> Gut, im Simulator gehts; im Reallife gehts nicht.
> Somit fängts hiermit an, kompliziert zu werden... oder..?

Jep.
Tut mir leid, dass ich dir nicht weiter helfen kann, aber ohne reale 
Hardware ist das jetzt sauschwer, wenn in der Simulation der Fehler 
nicht passiert.

Wenn du kannst:
  lass dir am Anfang die Adresse der Funktion irgendwo ausgeben (UART?)
  lass sie dir beim indirekten Aufruf noch einmal ausgeben

Und dann kann man eigentlich nur hoffen, dass die beiden Ausgaben nicht 
identisch sind. Sind sie identisch und wird die Funktion trotzdem nicht 
ausgeführt, tippe ich auf Stack-Unordnung.
Aber ich hoffe mal, dass sie nicht übereinstimmen. Denn dann kann man 
zusätzliche Ausgaben an 'stategischen Stellen' einbauen und rausfinden, 
wo sie verändert wird und so den Bug immer weiter einkreisen.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm viel mehr fällt mir da auch nicht ein; ich lass mal die Adressen 
ausgeben.
Und sollte das immernoch nicht klappen, vergleiche ich mal die 
nano-variante mit der anderen. Da muss es einen signifikanten 
Unterschied geben...

Kann man irgendwo am Stack rumspielen ohne im Linkerscript zu drehen?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einen hab ich noch.

Es geht um das File com_interface.c
#include <inttypes.h>
#include <avr/interrupt.h>
#include "com.h"
#include "com_interface.h"
#include "com_settings.h"

#include "uart.h"
//#include "watches.h"

#define com_watch   7

extern com_protocol_handle com_rx_protocol_handles[com_rx_protocol_handle_size];


uint8_t com_IF_read_byte(void);
bool com_IF_check_byte_ready(void);
bool com_IF_write_byte(uint8_t b);
uint16_t com_IF_get_time(void);
void com_IF_start_time(void);
void com_IF_stop_time(void);


Hmm. Wenn com_rx_protocol_handles hier extern ist (überraschenderweise), 
wo befindet sich dann die Definition dieses Arrays, ich kann sie nicht 
finden? (Irgendwo muss es ein com_rx_protocol_handles geben, das nicht 
als extern markiert ist)

Wenn com_IF_read_byte nur in diesem File benutzt wird, dann mach dieses 
Funktion besser static. Wenn auch von ausserhalb diese Funktion 
aufgerufen werden soll, warum ist ihr Prototyp dann nicht im Header 
File? (Dito natürlich für alle anderen Funktionen)

Aber das hat jetzt nicht wirklich was mit deinem Problem zu tun. Denke 
ich mal.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

schlechte Nachrichten:
Die Adressen:
12 103 //init (RegisterProtocol)

12 103 //vor com_handover()
12 103 //vor dem call

12 103 
12 103 

12 103 
12 103 

12 103 
12 103 

com_rx_protocol_handles[com_rx_protocol_handle_size] wird in com.c 
definiert.

Das ist so; die Files die du hast sind ein Port der C++-Variante des 
Stacks (die wiederum ein Port dieser Variante ist). Das ist also alles 
ein bisschen hin und her portiert. Sprich manche Funktionsdeklarationen 
kommen sowohl in der Datei als auch in den Headern vor. Das Chaos ist 
mir bekannt; allerdings hast du recht, das ist gerade auf meiner 
to-do-list recht weit unten (solange es funktioniert) ;)

§=%("=( warum geht das nicht...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tobias Schlegel schrieb:

> §=%("=( warum geht das nicht...

Gibt es irgendeine Chance, wie ich den Fehler bei mir reproduzierbar 
nachstellen kann?

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm ich sehe keine Chance ausser du hast zufällig einen Mega16/32 
rumliegen...

Hm Hm Hm. Ich versuch mal die Variante mit call by reference.

Es bleibt spannend ;)

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kurios:
/**
Function to hand over a received packet to the specified protocol (next_protocol field)
    @param[in] *p pointer to the packet
    @return code \li \c 0 = success \li \c 255 = failure (buffer full)
    @todo uC: check for EXISTENT protocol 0...!
    @todo check
*/
uint8_t com_handover(com_packet p){
    uint8_t     i = 0, j = 255;

    com_FPTR f;

    f = rfCMD_TakePacket;
    (*f)(p);

    for(i = 0 ; i < com_rx_protocol_handle_size -1 ; i++){
        if(com_rx_protocol_handles[i].protocol == p.protocol){
            PORTB ^= (1<<2);

            if( com_rx_protocol_handles[i].function ){
                (*com_rx_protocol_handles[i].function)(p);
            }else{
                PORTB |= (1<<3);
            }

            j = 0;

            break;
        }
    }

    return j;
}

Das funktioniert; es scheint also nicht am dynamischen Call zu liegen... 
die Frage ist... an was liegt es dann?!
Soll ich mal meinen WinAVR updaten und schauen obs dann geht?
Irgendwas ist hier gewaltig faul...

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Problem durch Erkennen der Nichtexistenz gelöst...

Ich habe festgestellt, dass genau die Funktion des anderen Protokolls 
aufgerufen wurde.
Und warum?
Die Protokolle des C++-Stacks (auf dem PC) hatten zwar die gleichen 
PIDs, allerdings vertauscht. Also kam Das Paket immer beim falschen 
Protokoll an.

Oh mannn so blöd muss man erstmal sein.
Sorry für dieses Riesentheater und den Aufwand. Und danke für die 
tatkräftige Unterstützung (@Karl heinz Buchegger!) !!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.