Hallo,
Ich arbeite mit dem STM32F107VCT6 und dem uVision von Keil.
Ich habe 2 uPs die per CAN-Bus miteinander kommunizieren. Jetzt möchte
ich zyklisch einen Request von A nach B senden und wenn B antwortet,
zeige ich auf dem Display von "Verbindung OK" an. Sendet B nichts
zurück, steht auf dem Display "Keine Verbindung".
Wie mache ich das: Ich setze eine Variable auf false und sende den
Request. Sendet B eine Antwort, wird die Variable auf true gesetzt.
Jetzt habe ich eine Flackern auf dem Display zwischen "Verbindung OK"
und "Keine Verbindung". Jetzt wollte ich dies mit einem MUTEX lösen und
habe mir das Beispiel auf der KEIL Webside angeschaut und gleich
aufgebaut. Jetzt empfängt A gar nichts mehr, weil wahrscheinlich der CAN
Controller verstopft wird!?
Nachtrag:
Anderst Formuliert: Ich möchte eine sporadische Verbindungskontrolle
durchführen.
Ich habe meinen Code gegenüber dem Beispiel abgeändert und auf den
Rückgabewert des os_mut_wait geprüft.
Ich habe beobachtet kurz nach dem Einschalten funktionierts, aber
plötzlich empfängt A nichts mehr.
A ist meine Testeinheit und B ist das eigentliche
Produkt(EC-Motorensteuerung).
Ich habe für die MUTEX Funktionen extra unabhängige Task aufgesetzt,
damit der CAN-Task verschont bleibt. Aber trotzdem verstopft irgendwie
der CAN-Bus!?
Danke und Gruss!
M.B.
Es gibt RTOS-Kernels, in denen eine Task eine bereits besitzende Mutex
erneut anfordern darf, ohne dass eine Blockade auftritt (interner
Zähler). Und solche, bei denen das nicht zulässig ist, sondern direkt in
den Deadlock führt. Zu welcher Gattung dieses gehört weiss ich nicht.
Hier: reset_CAN_connection holt sich die Mutex und ruft in diesem
Zustand request_CAN_connection auf - das sich aber auch erst die Mutex
holt. Sinn ergibt das wenig, weil direkt rqstConnection aufgerufen
werden könnte.
Wie ich schon schrieb: Ich kenne Keil nicht, das war eine eher
allgemeine Aussage zu RTOS-Kernels. Das Beispiel - habs jetzt erst
gelesen - legt allerdings nahe, dass es bei Keil zulässig ist.
Danke!
Ich denke, das Example ist eben sehr allgemein. Ich muss noch paar
Überlegungen investieren.
Der reset darf nur erfolgen wenn der request den Mutex freigegeben hat.
Anderes Thema: Es ist nicht sonderlich sauber, in einer Task eine
Semaphore zu initialisieren, die in einer konkurrierenden Task ebenfalls
verwendet wird. Das mag hier zwar aufgrund der Reihenfolge und der Prios
kein Problem sein, es bleibt aber unsauber und fehlerträchtig.
Task-übergreifende Resourcen sollten initialisiert werden, bevor diese
Tasks in Verlegenheit kommen könnten, sich drum zu streiten. Also hier
sinnvollerweise bevor die Tasks überhaupt existieren.
Ja, das steht so ebenfalls im Keil Beispiel, aber das machts auch nicht
besser.
A. K. schrieb:> Hier: reset_CAN_connection holt sich die Mutex und ruft in diesem> Zustand request_CAN_connection auf - das sich aber auch erst die Mutex> holt. Sinn ergibt das wenig, weil direkt rqstConnection aufgerufen> werden könnte.
rqstConnection wird in diesem Fall nie aufgerufen da os_mut_wait in den
Timeout läuft. Ich verstehe nicht wie bei einem fehlgeschlagenen
os_mut_wait direkt os_mut_release aufgerufen werden kann ohne in
Probleme zu laufen, ist alles etwas verwirrend ohne sich die
API-Referenz angeschaut zu haben ...
Quellcode vom ARTX:
http://read.pudn.com/downloads92/sourcecode/embed/359226/Kernel/AR_Mutex.c__.htm
Wenn eine Task die Mutex bereits besitzt, dann wird in os_mut_wait nicht
blockiert, sondern inkrementiert. os_mut_release gibt passend dazu erst
beim letzten Aufruf wieder frei. Das ist also sauber und entspricht dem
Beispiel in der Referenz (siehe Link im 1. Beitrag).
Wenn os_mut_release auf eine nicht im Besitz befindliche Mutex
aufgerufen wird, geschieht nichts. Besser wäre natürlich trotzdem
if(os_mut_wait (&mutex1, 0xFFFE) != OS_R_TMO)
{
rqstConnection();
os_mut_release (&mutex1);
}
NB: os_mut_wait ist etwas unschön konzipiert. Im erfolgreichen Fall gibt
es zwei verschiedene Return-Codes (mit/ohne Wait), im Fehlerfall aber
nur einen, und der betrifft einen speziellen Fall (Timeout) und heisst
auch entsprechend.
Folglich wird natürlich wie oben auf den speziellen Fehler getestet,
nicht auf den Erfolg. So ist es per Design quasi unmöglich, diesem API
irgendwann einen weiteren speziellen Error-Return hinzu zu fügen, ohne
haufenweise existierenden Code zu schrotten.