Hallo,
ich stehe gerade vor einem Problem, und habe erst einmal keine andere
Möglichkeit gefunden als die AVR-LibC dafür ein wenig zu modifizieren.
Ich wollte nun einmal abklopfen, ob es vielleicht noch andere
Möglichkeiten gibt, oder ob man das schöner machen könnte...
Also, ausschlaggebend ist folgendes Problem.
Ich nutze FreeRTOS auf einem ATMega und habe nun kleine Treiber
geschrieben. Zuerst für I²C (Interrupt-getrieben), anschließend für eine
RTC (RV3029). Dann dachte ich mir, seit der AVR-LibC v2.0.0 ist eine
Time-Lib mit an Board. Diese würde ich gerne nutzen. Nur um das Rad
nicht neu zu erfinden.
Auf FreeRTOS nutze ich einen Kernel-Task. Dieser initialisiert mit die
Hardware und anschließend werden aus einer Tabelle im Flash die weiteren
Tasks erstellt. Das klappt alles bisher ganz gut. Bei ca. 13kB ROM und
1,2kB RAM habe ich 4 Tasks zu laufen, und ein paar Treiber so wie ich
sie brauche. Wenn nix zu tun ist, dann nutze ich den Tickless Idle von
FreeRTOS.
So, nun wollte ich halt die time.h aus der AVR-LibC nutzen und das
klappt auch erst einmal ganz gut. Bis ich nun auf folgendes Problem
stieß.
Kommt der Controller aus dem Sleep, so sende ich noch aus der Funktion
vApplicationSleep an den Kernel Task ein KERN_CLOCK_SYNC. Das wird dann
anschließend auch aufgerufen.
Also fragt der Kernel-Task die RTC ab um die system_time wieder zu
synchronisieren. Das Abfragen geht via I²C (Interrupt getrieben) und ich
gebe Rechenzeit ab, sobald der I²C-Treiber auf die ISR warten muss. Also
kommt ein anderer Task an die Reihe und rechnet was. Fragt dieser nun
via time( NULL ) die Zeit ab, so ist diese falsch!
1
switch(action){
2
caseKERN_CLK_SYNC:{
3
structtmtime;
4
ioctl(rtcFile,RTC_RD_TIME,&time);// <-- Hier wird Rechenzeit abgegeben
5
time.tm_isdst=0;
6
set_system_time(mk_gmtime(&time));
7
}break;
8
default:break;
9
}
So... Mein erster naiver Ansatz war gewesen, dass ich den Scheduler
vorübergehend abschalte mit vTaskSuspendAll... Jedoch verwende ich im
I²C Treiber ein xQueueReceive mit einer Wartezeit, was dort nicht
zulässig ist. (Also wenn der Scheduler deaktiviert ist. Wohin soll auch
abgegeben werden.. :D) Also scheidet diese Möglichkeit aus...
Dann war ich am überlegen... Und bei dem Symbol __system_time aus der
time.h handelt es sich um eine shared ressource. Diese muss also
geschützt werden. Jedoch habe ich dazu nur die Möglichkeit, wenn ich die
AVR-LibC ändere... :/
Und das habe ich nun getan. Ich habe die Funktionen welche auf
__system_time zugreifen nun als weak definiert. So habe ich die
Möglichkeit die __system_time per Semaphore vor konkurrierenden
Zugriffen zu schützen. Wenn man sich den angehangenen Patch anschaut
würde mein Code dann ähnlich wie in dem nächsten Bsp ausschauen:
1
voidset_system_time(time_tt){
2
externvolatiletime_t__system_time;
3
// xSemaphoreTake
4
sys_atomic(){
5
__system_time=t;
6
}
7
// xSemaphoreGive
8
}
9
10
time_ttime(time_t*tm){
11
time_tret;
12
// xSemaphoreTake
13
externtime_t__time_libc(time_t*);
14
ret=__time_libc(tm);
15
// xSemaphoreGive
16
returnret;
17
}
Was haltet ihr davon? Hier gab es doch auch welche die an der avr-libc
mit entwickelt haben... ...
Ich würde mich dort über Rückmeldungen freuen, weil ich mir darüber
lange den Kopf zerbrochen habe und irgendwie keine andere Möglichkeit
gesehen habe.
Danke und Viele Grüße
Sep
sep schrieb:> Also fragt der Kernel-Task die RTC ab um die system_time wieder zu> synchronisieren. Das Abfragen geht via I²C (Interrupt getrieben) und ich> gebe Rechenzeit ab, sobald der I²C-Treiber auf die ISR warten muss.
Das halte ich für nicht günstig. Ich würde an dieser Stelle wohl lieber
warten, bis die aktuelle Zeit verfügbar ist.
> So... Mein erster naiver Ansatz war gewesen, dass ich den Scheduler> vorübergehend abschalte mit vTaskSuspendAll... Jedoch verwende ich im> I²C Treiber ein xQueueReceive mit einer Wartezeit, was dort nicht> zulässig ist.
Hmm, hmm, verstehe.
> Und das habe ich nun getan. Ich habe die Funktionen welche auf> __system_time zugreifen nun als weak definiert. So habe ich die> Möglichkeit die __system_time per Semaphore vor konkurrierenden> Zugriffen zu schützen.
Naja, eigentlich kannst du den entsprechenden Teil auch gleich neu
schreiben. Diese Sachen sind doch völlig unabhängig vom Rest der
time-Bibliothek. Du kannst also komplett deine eigene Idee von
system_time und time() implementieren und dennoch den Rest aus der
avr-libc benutzen.
Die time-Bibliothek ist m.E. ausreichend gut modularisiert, als dass da
aus der libc.a nur die Dinge gelinkt werden, die du nicht schon selbst
definiert hast – ganz und gar bereits ohne "weak".
Du kannst mich natürlich gern korrigieren, falls das nicht der Fall sein
sollte. Das ist jetzt nur mein Eindruck nach dem ersten Blick auf den
Sourcecode.
Jörg W. schrieb:> sep schrieb:>> Also fragt der Kernel-Task die RTC ab um die system_time wieder zu>> synchronisieren. Das Abfragen geht via I²C (Interrupt getrieben) und ich>> gebe Rechenzeit ab, sobald der I²C-Treiber auf die ISR warten muss.>> Das halte ich für nicht günstig. Ich würde an dieser Stelle wohl lieber> warten, bis die aktuelle Zeit verfügbar ist.
Das ist ja die Frage, wie soll die aktuelle Zeit verfügbar gemacht
werden. Der Kernel Task hat an sich die höchste Priorität im System.Das
der I²C-Treiber zwar für den Task blockiert, aber die Rechenzeit abgibt,
wenn er die Message sendet ist ja so gewollt. Man könnte das System
komplett blockieren. Das wäre aber, so denke ich ziemlich ungünstig.
Weil nicht jeder Task ist auf eine Uhrzeit angewiesen...
Jörg W. schrieb:>> So... Mein erster naiver Ansatz war gewesen, dass ich den Scheduler>> vorübergehend abschalte mit vTaskSuspendAll... Jedoch verwende ich im>> I²C Treiber ein xQueueReceive mit einer Wartezeit, was dort nicht>> zulässig ist.>> Hmm, hmm, verstehe.
Eine andere Möglichkeit wäre es die "User-Tasks" zu blockieren... Wobei
dort aber auch kein unterschied besteht zu dem ersten Ansatz. Denn in
der Zeit wo der Controller sendet und empfängt, können andere Tasks
arbeiten, welche nicht auf time.h angewiesen sind.
Jörg W. schrieb:>> Und das habe ich nun getan. Ich habe die Funktionen welche auf>> __system_time zugreifen nun als weak definiert. So habe ich die>> Möglichkeit die __system_time per Semaphore vor konkurrierenden>> Zugriffen zu schützen.>> Naja, eigentlich kannst du den entsprechenden Teil auch gleich neu> schreiben. Diese Sachen sind doch völlig unabhängig vom Rest der> time-Bibliothek. Du kannst also komplett deine eigene Idee von> system_time und time() implementieren und dennoch den Rest aus der> avr-libc benutzen.>> Die time-Bibliothek ist m.E. ausreichend gut modularisiert, als dass da> aus der libc.a nur die Dinge gelinkt werden, die du nicht schon selbst> definiert hast – ganz und gar bereits ohne "weak".>> Du kannst mich natürlich gern korrigieren, falls das nicht der Fall sein> sollte. Das ist jetzt nur mein Eindruck nach dem ersten Blick auf den> Sourcecode.
Da hätte ich doch die Frage, wie sollte das aussehen. Zur Zeit habe ich
die LibC auf meinem System installiert (Gentoo). AVR-GCC nutzt die
system installierte. Natürlich kann ich die LibC projektspezifisch aus
dem SRC kompilieren. Ich würde aber gerne eine Möglichkeit haben eine
einzelne zu nutzen.
Oder wie ist das gemeint dass ich mir die Module anpassen kann?
sep schrieb:> Oder wie ist das gemeint dass ich mir die Module anpassen kann?
Dass du dir das für dich Relevante in dein Projektverzeichnis kopieren
kannst, oder die entsprechenden Funktionen gleich bei dir neu schreibst.
Dank der Modularisierung der Bibliothek werden dann die durch die
Bibliothek definierten Funktionen (und Daten) einfach nicht von dort
geladen, denn du hast sie ja schon innerhalb deines Projekts verfügbar.
Dafür braucht man gar kein "weak", das ist ganz normale
Bibliotheks-Funktionalität: der Linker zieht eine Bibliothek nur zur
Auflösung undefinierter Symbole heran, und dann auch nur modulweise –
nicht etwa die Bibliothek im Ganzen.
Jörg W. schrieb:> Dafür braucht man gar kein "weak", das ist ganz normale> Bibliotheks-Funktionalität: der Linker zieht eine Bibliothek nur zur> Auflösung undefinierter Symbole heran, und dann auch nur modulweise –> nicht etwa die Bibliothek im Ganzen.
Verdammt. Und ich dachte genau dafür gäbe es das weak... ...
Hm. Man lernt nie aus. Ich denke ich werde das morgen einmal probieren.
Danke für den Hinweis. ;)
So, hab das noch einmal probiert und das funktioniert. Danke. Ich bin
immer davon ausgegangen, das ich die Funktionen nicht "überschreiben"
kann und das dafür extra das weak da ist, Danke dafür! ^^
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