Hallo, ich versuche gerade, beide CAN-Kanäle eines UC3C parallel in Betrieb zu nehmen. Ich habe jeden Kanal einzeln betrieben können. Nun versuche ich aber beide Kanäle parallel zu initialisieren und zunächst nur mit Kanal zwei zu Empfangen und zu Senden. Auf eine Empfangene Nachricht soll das Programm mit einer gesendeten Nachricht antworten. Das Problem ist jetzt, dass nur genau 16 Nachrichten von dem Programm gesendet werden, danach reagiert es nicht mehr. Es kommt aber zu keinem ACK-Fehler, d.h. empfangen werden die weiteren Nachrichten vermutlich, nur verarbeitet werden Sie nicht Hat jemand eine Idee, die mir auf die Sprünge helfen kann? Grüße, dionysos
ich stehe immernoch auf dem Schlauch. Scheinen hier aber nicht viele Leute zu sein, die sich mit AVR32 auskennen?! Mittlerweile kann ich auf zwei Kanälen Senden um Empfangen, aber jeweils nur 16 Nachrichten. Ich vermute, dass irgendein Speicher wieder freigegeben werden muss um weitere Nachrichten senden zu können.
ich meine, das Problem liegt in meiner falschen Verwendung der Funktion "can_out_callback_channel" bzw. daran, dass ich nur den Fall des Empfangens abdecke. In einem anderen Beispiel sieht die Funktion nämlich so aus: void can_out_callback_channel0(U8 handle, U8 event) { // Reception of Wakeup frame if (handle == NO_MOB) { // Disable Wake-Up Mode CANIF_disable_wakeup(CAN_CHANNEL_EXAMPLE); // Clear Interrupt Flag CANIF_clr_interrupt_status(CAN_CHANNEL_EXAMPLE); gpio_clr_gpio_pin(LED0_GPIO); } else { // Reception of Data frame appli_rx_msg.can_msg->data.u64 = can_get_mob_data(CAN_CHANNEL_EXAMPLE,handle).u64; appli_rx_msg.can_msg->id = can_get_mob_id(CAN_CHANNEL_EXAMPLE,handle); appli_rx_msg.dlc = can_get_mob_dlc(CAN_CHANNEL_EXAMPLE,handle); appli_rx_msg.status = event; can_mob_free(CAN_CHANNEL_EXAMPLE,handle); nb_message_received_on_channel0 = 1; gpio_clr_gpio_pin(LED1_GPIO); } } Allerdings ist dieses Beispiel für den Empfang einer Wakeup-Message. Ich bräuchte eine Unterscheidung des callbacks, ob ich nun enden oder Empfangen will. Aber wie kann ich diese Unterscheidung realisieren?
Ich habe mittlerweile unterschiedliche callback-Funktionen für beide Kanäle jeweils für das Senden und Empfangen eingerichtet. Der jeweile Kanal hängt sich aber dennoch nach dem Absetzen von 16 Nachrichten reproduzierbar ab. Der andere Kanal funktioniert weiterhin solange, bis auch er 16 Nachrichten abgesetzt hat. Hat niemand eine Idee, wo ich den Fehler suchen könnte?
ich hab jetzt nochmal mein Programm mit zwei Kanälen mit einer früheren Version verglichen, bei der ich nur einen Kanal verwendet habe. die Hauptschleife beinhaltet in der frühen Version folgendes: while(true) { if ((nb_message_received_on_channel1 == 1)) { send_ch1(); print_dbg("Nachricht da\r\n"); //send_ch1(); can_example_prepare_data(1); nb_message_received_on_channel1= 0; } } In dieser Form kann ich unbegrenzt Nachrichten empfangen und beantworten. Tausche ich jedoch die Position, an der "send_ch1()" aufgerufen wird, bleibt er nach 16 Nachrichten hängen.
Hallo, ich habe jetzt nicht versucht deine Code-Schnipsel im einzelnen nachzuvollziehen. Aber einige Anmerkungen, Ideen oder Denkanstöße habe ich dennoch: - Hast du inzwischen eine Interrupt-Handler registriert? - Hast du nachdem du eine Nachricht verarbeitet hast, das Message-Objekt mit can_mob_free( CAN_Interface, handle ) wieder freigegeben? - Hast du einmal versucht die Anzahl der Msg-Objekte zu verändern? Das waren jetzt einfach mal so ein paar Schüsse aus der Hüfte. Vielleicht hats ja geholfen. Gruß
Hi, danke für deine Gedankenanstöße. Also ich verwende noch die Interrupt-Routine aus dem ASF-Beispiel. (In dem Beispiel funktioniert die anscheinend). Die MOB's werden in can_out_callbacks freigegeben. An der Anzahl der MOB's habe ich noch nicht gedreht. Dafür habe ich mir das "CAN Software Stack Example 2" nochmal angesehen. Ich habe das Mainroutine dahingehend verändert, dass auf eine Nachricht gewartet wird und falls eine eintrifft, diese mit einer anderen Nachricht "beantwortet" wird. (Die Statemachine muss gefüttert werden, da sie im Originalprogramm vorhanden war) Das sieht nun also so aus: while(1) { if (nb_message_received_on_channel0 == 1) { state_machine = 120; can_example_prepare_data(0); print_dbg("Nachricht da\r\n"); nb_message_received_on_channel0 = 0; state_machine = 220; can_example_prepare_data(1); } } In diesem Zustand funktioniert das Programm, ich kann unbegrenzt Nachrichten empfangen. Der Knaller ist aber: Kommentiere ich die Debug-Ausgabe AUS, bleibt das Programm Nach 16 gesendeten Nachrichten hängen! Wird die Debug-Ausgabe getätigt, läuft das Programm.
Das könnte doch sicher etwas mit den Interrupts zu tun haben, da die serielle Schnittstelle ( USART ) sicher auch interruptgesteuert implementiert ist. Versuche doch einmal, die CAN-Interrupts nach dem Verarbeiten der Pakete explizit neu zu aktivieren per can_enable_interrupt()... Ich denke, du solltest dir die Interruptverarbeitung nocheinmal genau anschauen. Gruß
danke für den Tipp, aber ein einfaches can_enable_interrupt() behebt das Problem leider nicht. Ich schaue mir die Interrupts trotzdem nochmal genauer an.
Ich konnte das Problem eingrenzen: Zum Senden und zum Empfangen werden Message Objekte allokiert. Diese müssen wieder freigegeben werden. Das geschiet mit den Funktionen can_mob_alloc und can_mob_free Ich habe mir dazu jedes Mal debug-Nachrichten ausgeben lassen. Wenn das Programm funktioniert, wird ein MOB allokiert, die Nachricht empfangen, die Inhalte in Variablen abgelegt, das MOB freigegeben. Dann wird ein neues MOB allokiert, zum senden der CAN-Nachricht verwendet und freigegeben. In einer Konstellation, in der sich das Porgramm aufhängt, werden zwei MOBs allokiert, aber nur eins davon freigegeben. Irgendwann können dann keine neuen mehr alokiert werden. Jetzt ist die Frage, was hat die Stelle, an der in der main() debug Ausgaben gemacht werden damit zutun, dass nicht beide MOBs freigegeben werden können?! Edit: anscheinend wird mein Empfangs-Callback nicht ausgeführt, in dem das MOB freigegeben werden soll.
:
Bearbeitet durch User
auch wenn das hier ein Selbstgespräch ist, halte ich mal den Zwischenstand fest: Das Problem liegt darin, dass die send-callbacks nicht aufgerufen werden, um MOBs freizugeben. Das klappt allerdings nur in der if-Verzweigung meiner main-Schleife nicht. In dieser Verzweigung wird abgefragt, ob einer der beiden Kanäle eine Nachricht empfangen hat. while(4>2) { if ((nb_message_received_on_channel0 == 1)) { ... } else if ((nb_message_received_on_channel1 == 1)) { ... } } wird meine Send-Funktion vor der if-Verzweigung aufgerufen, wird auch der Send-callback einwandfrei abgearbeitet. Worann kann das nun wieder liegen?
Hallo dionysos 328, habe das selbe Problem und habe auch rausgefunden, dass beim Empfangen die Call-Back Methode nicht aufgerufen wird. Senden und Empfangen geht aber. Leider kann ich nicht auf die Daten der empfangenen Botschaft reagieren, da wie gesagt die Call-Back Methode nicht aufgerufen wird. Hast du schon rausgefunden, an was das liegt? Würde mich über deine Hilfe freuen. Beste Grüße, Sinuslive
Hi Sinuslive, ja ich konnte das Problem in der Zwischenzeit lösen. Ich hatte auch rausgefunden, dass die Callbacks nach dem Senden nicht aufgerufen werden, und deshalb die erzeugten Messageobjekte nicht freigegeben werden. Und das lag an der Struktur, wie ich meine Hauptverzweigung aufgebaut hatte. Wenn eine Nachricht auf einem Kanal empfangen wurde, wurde der Empfangs-Callback ausgelöst, die Nachricht abgeholt und dann eine Variable gesetzt "Nachricht da Kanal X". In der Main-Schleife wurde dann in einer Verzweigung in einen Zweig gesprungen, in der die "Nachricht Empfangen"-Variable zurückgesetzt wurde. Anschließen wurde die "Send"-Funktion aufgerufen und daraufhin eine Variable gesetzt: "Nachricht gesendet Kanal X". In einem weiteren Zweig wurde auf diese Variable reagiert und der Kanal wieder für das Empfangen vorbereitet("prepare_data_to_receive"). Das Problem dabei ist das setzen der Variable "Nachricht gesendet Kanal X". Dies geschah zwar rein logisch an der richtigen Stelle, allerdings war der Zeitpunkt, an dem das Rücksetzten geschah nicht immer gleich. Je nach dem, durch welchen Interrupt das Programm unterbrochen wurde (Stichwort print_dbg). Die sichere Variante ist daher, das setzten der Variable „gesendet“ mit den den Send-Callback zu integrieren, weil dort nichts den Ablauf unterbricht. Jetzt werden Send Callbacks immer zuende ausgeführt. Hoffe das hat geholfen, Grüße, dionysos
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.