Forum: Mikrocontroller und Digitale Elektronik Scheduler für AVR


von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Guten Tag,
ich möchte euch hier ein Scheduler zeigen. Vielleicht kann das für 
jemand behilflich werden.
Grundidee stammt von einem Blogger mit Pseudonym DI HALT.
Vorteil so einer Lösung, wenn auf den ersten Blick auch etwas 
abschreckend aussieht: man kann Projekt leichter pflegen und erweitern.

Hier ist eine Probe, mit einer Platine mit AtMega128A von Olimex. 
Scheduler selbst, das sind rtos.c und rtos.h. Alles andere ist nur zum 
Verständnis, wie alles funktioniert. Tastenabfrage ist nach Herrn 
Dannegger. lcd.c und lcd.h - Grundideen aus diesem Forum, dazu noch 
Modus mit Puffer in RAM (um nicht nach jedem Zeichen 50 us nutzlos 
warten zu müssen).

Außer Init gibt es vier Funktionen:
SetTask speichert eine Aufgabe in Puffer.
SetTimerTask speichert eine Aufgabe in Timmerpuffer, für Verzögerung.
TaskManager arbeitet in der Hauptschleife ( while(1) ) und führt die 
Aufgaben aus.
TimerService wird in Timerinterrupt jede 1 ms (oder so ähnlich) 
durchgeführt: Die Programmtimer werden decrementiert und nach der Zeit 
wird die Aufgabe mit SetTask in Puffer gesetzt.
Aufgabenpuffer ist als Ring gemacht, Timerpuffer nicht als Ring.
Zusätzlich gibt es die Möglichkeit, für jede Aufgabe bis 3 Variablen zu 
speichern, die auch in Puffern bleiben. Diese Funktionalität ist zwar 
nicht zwingend notwendig und kostet RAM und Zeit, erleichtert aber das 
Programmieren.

Für eure Kritik werde ich dankbar.

Viele Grüße,
Maxim.

von Säbelzahn (Gast)


Lesenswert?

Gratulieren! Gut zusammengeklickt, die Programme und die Ideen von 
Anderen.

von Maxim B. (max182)


Lesenswert?

Säbelzahn schrieb:
> die Programme und die Ideen von
> Anderen.

Sollte ich Fahrrad selbst erfinden?
Selbst in Datenblatt stehen Programmbeispiele. Nicht benutzen?

Autoren von Ideen habe ich genannt, noch eigene Ideen dazu gebracht... 
Hoffentlich etwas brauchbares bekommen. Ich habe schon mit Scheduler 
(aber die Variante ohne Variablen) ein Ding gemacht.

Selbst J.S.Bach, mein Kollege aus Leipzig, hat die Tonleiter nicht 
selber erfunden.

: Bearbeitet durch User
von Albert (Gast)


Lesenswert?

OT: Es ist mir immernoch schleierhaft, warum man auf einem 8bit 
Prozessor einen Scheduler braucht? Kriegt man es nicht hin so ein paar 
Prozesse ohne Wartezyklen parallel laufen zu lassen?

von Maxim B. (max182)


Lesenswert?

Albert schrieb:
> warum man auf einem 8bit
> Prozessor einen Scheduler braucht?

Um schneller viele gute Dinge machen zu können. Ohne die Zeit für 
Gerippe zu verlieren.

Aber Scheduler kann genau so gut auch mit STM32 arbeiten. Das ist ja C.

: Bearbeitet durch User
von derjaeger (Gast)


Lesenswert?

>Kriegt man es nicht hin so ein paar Prozesse ohne Wartezyklen parallel laufen zu 
lassen?


Ein Scheduler ist praktisch wenn man zyklisch mehrere Aufgaben 
quasi-parallel erledigen will ... was ja der Sinn eines Controllers ist 
(zyklisch Eingaben abfragen, Daten holen/ablegen, .. )

von Maxim B. (max182)


Lesenswert?

Nicht nur einfach zyklisch. Man kann aus einer Aufgabe eine andere mit 
Verzögerung rufen und somit komplizierte Abhängigkeiten schaffen.

Hauptidee: die Zeit für delay nicht verschwenden.

Im Vergleich mit Flag-Automat ist Scheduler weniger problematisch, wenn 
eine oder andere Aufgabe zufällig mehr Zeit braucht, als zwischen 
Timer-Interrupts bleibt.

: Bearbeitet durch User
von Albert (Gast)


Lesenswert?

Maxim B. schrieb:
> Nicht nur einfach zyklisch. Man kann aus einer Aufgabe eine andere mit
> Verzögerung rufen und somit komplizierte Abhängigkeiten schaffen.

Genau das ist es - die Leute denken zu kompliziert. Dann braucht man 
auch keinen Scheduler.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

... scheduler habe ich verschiedene auf avr/pic/stm zu laufen und finde 
es auch oft sinnig, aber richtig "böse" finde ich immer noch

1. viele triviale kommentare ohne informationsgehalt, anstatt 
vielsagende bezeichner zu verwenden!

2. immer und immer wieder klammern zu setzen, auch wenn da keine sein 
müssen - ein unding!

3. die redundante programmierung, sprich copy&paste oder basteln!

eins von vielen beispielen; lcd.c function

//original
void lcd_string_P( PGM_P data ) {
    u8 tmp;

    tmp=pgm_read_byte(data);
    while( tmp != '\0' ) {
        lcd_data( tmp );
        data++;
        tmp = pgm_read_byte(data);
    }
}

//mein zweizeiler aus der pistole in 3sec
void lcd_puts_p(PGM_P sp) {
    uint8_t s;
    while (s=pgm_read_byte(sp++), s)
        lcd_data(s);
}


mt

p.s. der hier gezeigte "scheduler" verdient den namen NICHT!

von Peter D. (peda)


Lesenswert?

Albert schrieb:
> OT: Es ist mir immernoch schleierhaft, warum man auf einem 8bit
> Prozessor einen Scheduler braucht?

Seit wann ist es verboten, sich auch auf 8-Bittern die Arbeit zu 
erleichtern?

Ich benutze einen Scheduler in fast allen Projekten, sobald etwas 
verzögert ausgeführt werden muß. Das erspart einem, jedesmal extra 
Zählschleifen hinschreiben zu müssen.

Hier mal meine Version. Die Idee mit der sortierten Liste ist aber nicht 
von mir.
Beitrag "Wartezeiten effektiv (Scheduler)"

von Karl M. (Gast)


Lesenswert?

Danke Peter,

dass Du dein Projekt hier noch mal verlinks.
Ich verwende deinen Scheduler (peda) auch meinen Projekten und kann ihn 
mit der Tastenentprellung (peda) nur empfehlen.

von Maxim B. (max182)


Lesenswert?

Apollo M. schrieb:
> 2. immer und immer wieder klammern zu setzen, auch wenn da keine sein
> müssen - ein unding!

Ich bin anderer Meinung. Die Klammer kosten nichts. Aber unter 
bestimmten Umständen können sie viel Ärger sparen.

Apollo M. schrieb:
> 1. viele triviale kommentare ohne informationsgehalt, anstatt
> vielsagende bezeichner zu verwenden!

Lieber zu viel als zu wenig. Sonst vergesse ich bald selber, was und 
warum so und nicht anders. Zeitverschwendung, ohne Kommentare zu 
schreiben.

Wer aber besser ohne Kommentare lebt, der darf sie natürlich löschen.

So oder so, das Ding funktioniert. Man kann das natürlich auch besser 
machen...
1
//original
2
void lcd_string_P( PGM_P data ) {
3
    u8 tmp;
4
5
    tmp=pgm_read_byte(data);
6
    while( tmp != '\0' ) {
7
        lcd_data( tmp );
8
        data++;
9
        tmp = pgm_read_byte(data);
10
    }
11
}
12
13
//mein zweizeiler aus der pistole in 3sec
14
void lcd_puts_p(PGM_P sp) {
15
    uint8_t s;
16
    while (s=pgm_read_byte(sp++), s)
17
        lcd_data(s);
18
}
Kannst du bitte erklären, welche Vorteile deine Schreibweise hat?
Du hast ein paar Zeilen weniger. Was hast du gespart? Papier? Geld? CO2?

Apollo M. schrieb:
> 3. die redundante programmierung, sprich copy&paste oder basteln!
Für mich hat Verständlichkeit höchsten Wert. Wenn das ein paar Zeilen 
mehr bedeutet, so muß das sein.

Apollo M. schrieb:
> p.s. der hier gezeigte "scheduler" verdient den namen NICHT!
Egal wie das heißt. Hauptsache, das Ding arbeitet wie soll.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Albert schrieb:
> Genau das ist es - die Leute denken zu kompliziert. Dann braucht man
> auch keinen Scheduler.

Ja, früher habe ich das auch ohne gemacht. Für LED blinken je LED ein 
Programmtimer. Für Tastenabfrage je Taste ein Programmtimer :) Ja, so 
kann das auch funktionieren. Das Problem kommt erst wenn man nach einem 
Jahr etwas zu ändern hat.

Einmal wollte ich genau sehen, was per MIDI übertragen wird. Es kam 
immer wieder zu Verschlucken von MIDI-Code. Na ja, habe ich gedacht: AVR 
sei sicher zu langsam :)
In Wirklichkeit war Problem natürlich nicht in AVR...

: Bearbeitet durch User
von Ralph S. (jjflash)


Lesenswert?

Maxim B. schrieb:
> Kannst du bitte erklären, welche Vorteile deine Schreibweise hat?
> Du hast ein paar Zeilen weniger. Was hast du gespart? Papier? Geld? CO2?

... ich bin zwar nicht der Author des Zweizeilers, aaaaber: deine 
Version produziert zweimal Code für den Zugriff auf das Flash, der 
Zweizeiler nur einmal (der Zweizeiler gefällt mir aber dennoch nicht so 
sehr).

"Deine" Schleife wäre besser in einer do .. while Schleife aufgehoben 
(um eben nur einmal Code für Flashzugriff zu generieren...

von Maxim B. (max182)


Lesenswert?

Ralph S. schrieb:
> deine
> Version produziert zweimal Code für den Zugriff auf das Flash, der
> Zweizeiler nur einmal (der Zweizeiler gefällt mir aber dennoch nicht so
> sehr).

Du wirst sicher lachen:
ich habe jetzt ausprobiert, das Programm mit meiner Variante 2 bytes 
kleiner, als von Apollo M ...

Compiler optimiert alles, man sollte oft einfach ausprobieren... Also, 
meine Variante ist ein bißchen kürzer, aber das ist eigentlich egal.

Übrigens, Gerechtigkeit halber: die Variante ist nicht meine. Ich habe 
nach diesem Muster auch ähnliche Funktion für Arbeit über Puffer 
gemacht.

Interessant ist Listing zu sehen:
erste ist "meine".
1
 2f2:  cf 93         push  r28
2
 2f4:  df 93         push  r29
3
 2f6:  ec 01         movw  r28, r24
4
 2f8:  fe 01         movw  r30, r28
5
 2fa:  84 91         lpm  r24, Z
6
 2fc:  88 23         and  r24, r24
7
 2fe:  21 f0         breq  .+8 
8
 300:  0e 94 ea 00   call  0x1d4
9
 304:  21 96         adiw  r28, 0x01
10
 306:  f8 cf         rjmp  .-16 
11
 308:  df 91         pop  r29
12
 30a:  cf 91         pop  r28
13
 30c:  08 95         ret
14
15
16
 2f2:  cf 93         push  r28
17
 2f4:  df 93         push  r29
18
 2f6:  fc 01         movw  r30, r24
19
 2f8:  84 91         lpm  r24, Z
20
 2fa:  ef 01         movw  r28, r30
21
 2fc:  21 96         adiw  r28, 0x01
22
 2fe:  88 23         and  r24, r24
23
 300:  21 f0         breq  .+8
24
 302:  0e 94 ea 00   call  0x1d4
25
 306:  fe 01         movw  r30, r28
26
 308:  f7 cf         rjmp  .-18
27
 30a:  df 91         pop  r29
28
 30c:  cf 91         pop  r28
29
 30e:  08 95         ret

So oder so, es kommt nur einmal lpm. Compiler optimiert alles gut.

: Bearbeitet durch User
von Mr_Sven (Gast)


Lesenswert?

Spätestens seit dem SSL Bug sollte jeder wissen, dass man in 
Programmiersprachen wie C niemals auf Klammern verzichten sollte.

Eben mal lcd_data durch ein kompliziertes Macro ersetzt und schon ist 
alles kaputt.

Gruß Sven

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

... programmieren hat auch was mit ästhetik zu tun, der hier gezeigte 
code ist typisch für halbwissende, wenn ihr solchen code irgendwo zeigt 
könnt ihr gleich wieder nach hause gehen!

UND einzeilige if/else anweisungen immer schön brav zu klammern ist 
klippschule und verbessert wohl kaum die lesebarkeit, aber pumpt das 
listing auf!

// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( u8 data ) {
  lcd_dataline_null();
  if (data & 0x10) LCD_PORT_DB4 |= (1<<LCD_DB4);
  if (data & 0x20) LCD_PORT_DB5 |= (1<<LCD_DB5);
  if (data & 0x40) LCD_PORT_DB6 |= (1<<LCD_DB6);
  if (data & 0x80) LCD_PORT_DB7 |= (1<<LCD_DB7);
  lcd_enable_puls();
}

// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( u8 data ) {
  lcd_dataline_null();
  if (data & 0x10){
    LCD_PORT_DB4 |= (1<<LCD_DB4);
  }
  if (data & 0x20){
    LCD_PORT_DB5 |= (1<<LCD_DB5);
  }
  if (data & 0x40){
    LCD_PORT_DB6 |= (1<<LCD_DB6);
  }
  if (data & 0x80){
    LCD_PORT_DB7 |= (1<<LCD_DB7);
  }
  lcd_enable_puls();
}

genauso wenig wie kommentare dieser art ... außer man "spricht" die 
sprache garnicht

wdt_reset(); // Watchdog auf Null

UND auch mal coding styles lesen, damit mal kappiert wird wo/wo nicht 
leerzeichen hingehören

wenn schon dann eher so das ganze ...

void lcd_string_P(PGM_P data) {
    u8 tmp = pgm_read_byte(data);
    while (tmp != 0) {
        lcd_data(tmp);
        tmp = pgm_read_byte(++data);
    }
}

UND auch mal über konsistenz im coding nachdenken - der code ist VOLL 
von inkonsistenz
z.b. die function vor lcd_string_P() incrementiert den data pointer ganz 
normal im parameter feld, also hatte dort der to noch keine 
"leseschwäche wie behauptet" aber
'\0' anstatt 0 ist immer dumm

void lcd_string( u8 *data ) {
    while( *data != '\0' )
        lcd_data( *data++ );
}

Maxim B. schrieb:
> ich habe jetzt ausprobiert, das Programm mit meiner Variante 2 bytes
> kleiner, als von Apollo M ...

kann ich nicht bestätigen, sondern umgekehrt!

mit gcc v8.2 und -Os

//mein zweizeiler aus der pistole in 3sec
void lcd_puts_p(PGM_P sp) {
  uint8_t s;
  while (s=pgm_read_byte(sp++), s)
  96:  fc 01         movw  r30, r24
  98:  24 91         lpm  r18, Z
  9a:  01 96         adiw  r24, 0x01  ; 1
  9c:  21 11         cpse  r18, r1
  9e:  fb cf         rjmp  .-10       ; 0x96 <lcd_puts_p>
  lcd_data(s);
}
  a0:  08 95         ret


//original
void lcd_string_P( PGM_P data ) {
  uint8_t tmp=pgm_read_byte(data);
  while (tmp != 0) {
    lcd_data( tmp );
    tmp = pgm_read_byte(++data);
  96:  fc 01         movw  r30, r24
  98:  24 91         lpm  r18, Z
  while (tmp != 0) {
  9a:  21 11         cpse  r18, r1
  9c:  01 c0         rjmp  .+2        ; 0xa0 <lcd_string_P+0xa>
  }
}
  9e:  08 95         ret
    tmp = pgm_read_byte(++data);
  a0:  01 96         adiw  r24, 0x01  ; 1
  a2:  f9 cf         rjmp  .-14       ; 0x96 <lcd_string_P>



mt

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

... meine buchempfehlung für jene die c-programmierung wirklich mal 
lernen wollen und "hart" genug sind, weil starker tabak wenn man dann 
schrittweise kapiert, dass man eigentlich gar keine ahnung von der 
sprache hatte!

Schellong, Moderne C-Programmierung

dann lernt ihr z.b. auch was ko-logik in c-programmierug bedeutet und 
was man damit alles machen kann ...


liegt auch als pdf im web rum!


mt

: Bearbeitet durch User
von Marc (Gast)


Lesenswert?

Apollo M. (Firma: @home) (majortom)
>... programmieren hat auch was mit ästhetik zu tun, der hier gezeigte
>code ist typisch für halbwissende, wenn ihr solchen code irgendwo zeigt
>könnt ihr gleich wieder nach hause gehen!

Wenn Du jetzt noch lernst, beim posten die Code-Tags zu setzen, damit 
das "Syntax-Highlighting" funktioniert, dann wird auch Dein Code noch 
schöner.

Die Form von Code hat immer was mit dem eigenen Stil zu tun und ich habe 
noch keinen Code gesehen, an dem ich nichts kritisieren könnte.

von Peter D. (peda)


Lesenswert?

Apollo M. schrieb:
> ... programmieren hat auch was mit ästhetik zu tun, der hier gezeigte
> code ist typisch für halbwissende, wenn ihr solchen code irgendwo zeigt
> könnt ihr gleich wieder nach hause gehen!

Ich glaube nicht, daß dieses Forum nur für Profis gedacht ist, daher muß 
man nicht gleich alle Leute anpissen, die hier was veröffentlichen.
Man kann Tipps geben, dann aber bitte in freundlichem Ton.

von Cyblord -. (cyblord)


Lesenswert?

Maxim B. schrieb:
>> 1. viele triviale kommentare ohne informationsgehalt, anstatt
>> vielsagende bezeichner zu verwenden!
>
> Lieber zu viel als zu wenig. Sonst vergesse ich bald selber, was und
> warum so und nicht anders. Zeitverschwendung, ohne Kommentare zu
> schreiben.


“Every time you write a comment, you should grimace and feel the failure 
of your ability of expression.”
―  Robert C. Martin,  The Robert C. Martin Clean Code Collection 
(Collection)

von Marc (Gast)


Lesenswert?

>“Every time you write a comment, you should grimace and feel the failure
>of your ability of expression.”
>―  Robert C. Martin,  The Robert C. Martin Clean Code Collection
>(Collection)

Dem stimme ich zu hundert Prozent zu: Code muss so geschrieben sein, 
dass Kommentare überflüssig sind.
Das Problem: Code und Kommentare laufen mit der Zeit immer auseinander.

Also: Kommentare weg, Code verbessern !

von Cyblord -. (cyblord)


Lesenswert?

Marc schrieb:

> Das Problem: Code und Kommentare laufen mit der Zeit immer auseinander.

Genau. Natürlich hat Uncle Bob auch dazu was schlaues gesagt:

“Redundant comments are just places to collect lies and misinformation.”

von Maxim B. (max182)


Lesenswert?

Peter D. schrieb:
> Ich glaube nicht, daß dieses Forum nur für Profis gedacht ist, daher muß
> man nicht gleich alle Leute anpissen, die hier was veröffentlichen.

Danke!
Ich bin natürlich kein Profi, ich verdiene mein Gehalt anders.

Was aber meine Kommentare angeht: einmal früher habe ich bemerkt, daß 
ich kaum noch verstehe, was ich vor einem Jahr geschrieben habe. Seit 
dem schreibe ich möglichst viele Kommentare. Wenn einem oder anderem 
Profi das nicht gefällt... Na, man kann nicht für allen gut sein, 
leider... :)

Kommentare schreibe ich FÜR MICH.

Übrigens, wie ich am Anfang schon geschrieben habe: es geht hier um 
rtos.h und rtos.c. Alles andere ist nur als Zugabe zu betrachten, die 
alles etwas verständlicher macht.
Stattdessen wird hier aus irgendwelchem Grund nur über meine Variante 
von lcd.h - lcd.c diskutiert (die übrigens nach Anregung von Ihnen, Herr 
Dannegger, gemacht wurde. Danke noch mal für Tipps!).
lcd.h - lcd.c funktioniert genau wie ich möchte. Ich habe dort seit 
langer Zeit fast nichts geändert. Ich mache nur Anpassungen bei Pin-Def, 
je nach der Platte. Einziges, was mir im Moment noch als fehlerhaft 
erscheint: in Puffer-Mode möchte ich gerne auch blinkende Zeichen 
ermöglichen. Darüber muß ich noch überlegen. Auch bessere Zusammenspiel 
mit rtos wäre gut.

Hier gab es noch von Apollo M. ein Tipp, ein Buch zu lesen: "Schellong, 
Moderne C-Programmierung". Leider muß ich sagen, daß dieses Buch, wie 
auch viele anderen, gleiche Nachteil hat: zu oberflächlich. Viele Fragen 
und Momente sind entweder nicht ausreichend erklärt oder gar nicht 
erwähnt. Deshalb bin ich eigentlich hier in Forum (und nicht nur hier).

Viele Grüße!

: Bearbeitet durch User
von Cyblord -. (cyblord)


Lesenswert?

Maxim B. schrieb:
> Was aber meine Kommentare angeht: einmal früher habe ich bemerkt, daß
> ich kaum noch verstehe, was ich vor einem Jahr geschrieben habe. Seit
> dem schreibe ich möglichst viele Kommentare. Wenn einem oder anderem
> Profi das nicht gefällt... Na, man kann nicht für allen gut sein,
> leider... :)

Nun du könntest aber Vorschläge trotzdem annehmen.
Und der Vorschlag ist klar: Schreibe besseren Code.

von Maxim B. (max182)


Lesenswert?

Apollo M. schrieb:
> //original
> void lcd_string_P( PGM_P data ) {
>   uint8_t tmp=pgm_read_byte(data);
>   while (tmp != 0) {
>     lcd_data( tmp );
>     tmp = pgm_read_byte(++data);
>   96:  fc 01         movw  r30, r24
>   98:  24 91         lpm  r18, Z
>   while (tmp != 0) {
>   9a:  21 11         cpse  r18, r1
>   9c:  01 c0         rjmp  .+2        ; 0xa0 <lcd_string_P+0xa>
>   }
> }
>   9e:  08 95         ret
>     tmp = pgm_read_byte(++data);
>   a0:  01 96         adiw  r24, 0x01  ; 1
>   a2:  f9 cf         rjmp  .-14       ; 0x96 <lcd_string_P>

Lieber Herr Apollo M.,
das ist nicht mein Code! Mein ist etwas anders:
1
 tmp = pgm_read_byte(++data);
 gibt es in meinem Code nicht!

So kleine Unterschiede machen schon große Unterschiede bei Optimieren 
von Compiler. Deshalb passen Sie bitte auf, was Sie schreiben!

: Bearbeitet durch User
von Säbelzahn (Gast)


Lesenswert?

Karl M. schrieb:

> Danke Peter,
>
> dass Du dein Projekt hier noch mal verlinks.
> Ich verwende deinen Scheduler (peda) auch meinen Projekten und kann ihn
> mit der Tastenentprellung (peda) nur empfehlen.

Hast Du keine Angst, dass Du auf deinen Schleimspur ausrutschst?

von Maxim B. (max182)


Lesenswert?

Cyblord -. schrieb:
> Und der Vorschlag ist klar: Schreibe besseren Code.

Sage ich etwas dagegen?

Aber in der Funktion, über die Herr Apollo M. schrieb, scheint meine 
Variante eher besser zu sein, als seine.

Außerdem hat er mich nicht überzeugt, wie er schrieb, man brauche wenige 
Klammern. Ich habe in der Literatur genau Gegenteil gelesen: man mache 
lieber zu viel Klammern als zu wenig. Und auch in der Literatur gibt es 
Erklärungen, warum.

von Dr. Sommer (Gast)


Lesenswert?

Apollo M. schrieb:
> dann lernt ihr z.b. auch was ko-logik in c-programmierug bedeutet und
> was man damit alles machen kann ...

Das gleiche, was alle anderen unter Short-Circuit-Evaluation verstehen 
und was viele andere Sprachen auch können? Wieder was gelernt!

von jemand (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Apollo M. schrieb:
>> dann lernt ihr z.b. auch was ko-logik in c-programmierug bedeutet und
>> was man damit alles machen kann ...
>
> Das gleiche, was alle anderen unter Short-Circuit-Evaluation verstehen
> und was viele andere Sprachen auch können? Wieder was gelernt!

Der Herr Apollo M. ist das Programmiereräquivalent der üblichen und 
verhassten Rechtschreibfanatiker.

Es mag ja stimmen, dass man Code besser schreiben kann (speziell C ist 
da ja sehr "variabel") Aber hier kam nur Herumgemäkle an Kleinigkeiten, 
und nichts substantielles.

Leute wie dieser "Apollo M." machen dieses Forum so unangenehm...

von Karl K. (karl2go)


Lesenswert?

Apollo M. schrieb:
> // Sendet eine 4-bit Ausgabeoperation an das LCD
> static void lcd_out( u8 data ) {
>   lcd_dataline_null();
>   if (data & 0x10) LCD_PORT_DB4 |= (1<<LCD_DB4);
>   if (data & 0x20) LCD_PORT_DB5 |= (1<<LCD_DB5);
>   if (data & 0x40) LCD_PORT_DB6 |= (1<<LCD_DB6);
>   if (data & 0x80) LCD_PORT_DB7 |= (1<<LCD_DB7);
>   lcd_enable_puls();
> }

Was bitte ist das denn? Wer kommt hier auf die Idee jedes Bit einzeln zu 
setzen?
1
LCD_PORT &= 0x0F;  // Pins low
2
LCD_PORT |= data & 0xF0;  //high Nibble setzen

von Falk B. (falk)


Lesenswert?

Karl K. schrieb:

> Was bitte ist das denn? Wer kommt hier auf die Idee jedes Bit einzeln zu
> setzen?

Wahrscheinlich der Gleiche, der die Zuordung der Bits zu den Portbits 
maximal variabel halten wollte. Wo liegt das Problem? Die 3us 
CPU-Laufzeit?

> LCD_PORT &= 0x0F;  // Pins low
> LCD_PORT |= data & 0xF0;  //high Nibble setzen

Nö, das geht nur bei eingeschränker Zuordung der Bits am Port.

von Peter D. (peda)


Lesenswert?

Marc schrieb:
> Dem stimme ich zu hundert Prozent zu: Code muss so geschrieben sein,
> dass Kommentare überflüssig sind.

Es ist immer leichter, Dogmen aufzustellen, als sie auch einzuhalten. 
Wenn es so leicht wäre, gäbe es die Kommentarfunktion ja nicht.
Ich schreibe lieber mal einen Kommentar, als 80 Zeichen lange Funktions- 
und Variablennamen.
Die Vergabe von beschreibenden Namen ist ein wirklich schweres Thema. 
Ich möchte nicht deutlich länger an der Namensvergabe grübeln, als an 
dem eigentlichen Code.

Marc schrieb:
> Das Problem: Code und Kommentare laufen mit der Zeit immer auseinander.

Aber auch Namen können veralten, wenn man eine Funktion verändert, z.B. 
wenn ich eine Funktion universeller mache oder etwas daraus in eine 
Unterfunktion auslagere.
Was ich extrem unleserlich finde, ist CamelCase. Ich benutze immer den 
Unterstrich als Trenner in einem Namen.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Falk B. schrieb:
> Wahrscheinlich der Gleiche, der die Zuordung der Bits zu den Portbits
> maximal variabel halten wollte.

Genau deshalb.

Zuerst machte ich mit Def. drei Varianten: alles auf einem Port, Data 
auf einem und E und RS auf einem anderen Port, und völlig frei. Aber am 
Ende habe ich nur die freie Variante gelassen. Zeitunterschiede gegen 
anderen Varianten sind unbedeutend. Aber die Platte kann viel bequemer 
gemacht werden. Alles, was nicht für andere Funktionen gebraucht wird, 
kann für LCD benutzt werden.

von Maxim B. (max182)


Lesenswert?

Ich versuche mich in Namen nach meinen Regeln zu halten: falls ich das 
nicht vergesse, mache ich immer Prefix mit Filename und Unterstrich. 
Z.B. void indikator_schreib_ind_puff(u8 a,u8 b,u8 c,u8 d) befindet sich 
in indikator.c.
Es sei denn, ich benutze Bibliothek von anderen.

von Karl K. (karl2go)


Lesenswert?

Falk B. schrieb:
> Die 3us
> CPU-Laufzeit?

Ist zehnmal so lang wie das nötige Write Enable von 300ns.

von Maxim B. (max182)


Lesenswert?

Karl K. schrieb:
> Ist zehnmal so lang wie das nötige Write Enable von 300ns.

Das ist sehr wichtig, wenn zu berücksichtigen, daß E etwa 500 ns braucht 
und zwischen Befehlen ca. 40-50 us zu warten ist :)

Ich habe übrigens gekuckt: lcd_out( data ); zusammen mit 
lcd_enable_puls(); 500 ns braucht ca. 3,3 us (mit F_CPU = 16 MHz).

: Bearbeitet durch User
von Karl K. (karl2go)


Lesenswert?

Maxim B. schrieb:
> Das ist sehr wichtig, wenn zu berücksichtigen, daß E etwa 500 ns braucht
> und zwischen Befehlen ca. 40-50 us zu warten ist :)

Wenn man linear programmiert freilich nicht. Wenn man einen 
Displaybuffer verwendet und der µC zwischendrin was anderes machen kann, 
braucht es Zehnmal so lange.

Das ist so typisch Arduino-Programming: starte die Messung - delay(1000) 
- lese den Messwert. Und dann rumheulen: Mein µC ist zu langsam, ich 
brauch einen schnelleren µC.

von Marc (Gast)


Lesenswert?

>Was ich extrem unleserlich finde, ist CamelCase. Ich benutze immer den
>Unterstrich als Trenner in einem Namen.

Das fand ich am Anfang auch, aber ich habe eine Zeitlang Java gemacht 
und dort ist es Standard. Deshalb habe ich mich auf die Konvention 
"CamelCase" auch für C geeinigt.
Mit der Zeit gewöhnt man sich dran. oderEtwaNicht ? ;-)

von Maxim B. (max182)


Lesenswert?

Karl K. schrieb:
> Wenn man einen
> Displaybuffer verwendet und der µC zwischendrin was anderes machen kann,
> braucht es Zehnmal so lange.

Stimmt schon.
Aber da ich PCB selber mache, ist für mich die Möglichkeit, PINs frei 
bestimmen zu dürfen, am wichtigsten.

Übrigens, die Ausgabe kann man sehr leicht ändern, wenn man will. Statt
1
 
2
static void lcd_out( u8 data ) {
3
  lcd_dataline_null(); 
4
  if (data & 0x10){
5
    LCD_PORT_DB4 |= (1<<LCD_DB4);
6
  }
7
  if (data & 0x20){
8
    LCD_PORT_DB5 |= (1<<LCD_DB5);
9
  }
10
  if (data & 0x40){
11
    LCD_PORT_DB6 |= (1<<LCD_DB6);
12
  }
13
  if (data & 0x80){
14
    LCD_PORT_DB7 |= (1<<LCD_DB7); 
15
  }
16
  lcd_enable_puls();
17
}

kommt
1
 
2
static void lcd_out( u8 data ) {
3
  LCD_PORT &= 0x0f;
4
  LCD_PORT |= (data & 0xf0);
5
  lcd_enable_puls();
6
}
 .
Statt 50 Cycle wird 28. Statt 3,125 us wird 1,75 us. Hilft das viel?

von Ich (Gast)


Lesenswert?

Peter D. schrieb:
> Es ist immer leichter, Dogmen aufzustellen, als sie auch einzuhalten.

Dogma:

Schreibe, in den Kommentaren warum du etwas so tust.
Nicht, was du tust, denn das steht schon im Code.

von Maxim B. (max182)


Lesenswert?

Karl K. schrieb:
> Wenn man einen
> Displaybuffer verwendet und der µC zwischendrin was anderes machen kann,
> braucht es Zehnmal so lange.

Wenn das irgendwie nicht bemerkt wurde:
LCD-Puffer wird nur jede 1 ms bedient. Auch für 4x20 LCD bedeutet das 
nur 84 ms, das ist für Auge kaum zu merken.

Die Auslastung für LCD wird:
so wie das steht: 7/1000=0,7% (nur während Kopierens, danach nicht 
mehr).
Alles auf einem Port: 3,5/1000=0,35%.
Ist das wirklich so kritisch?

: Bearbeitet durch User
von Apollo M. (Firma: @home) (majortom)


Lesenswert?

... so da habe ich ja den finger richtig in die wunden gelegt, aber wir 
können alle zufrieden sein, da an den comments offensichtlich wird, dass 
hier einige noch mitdenken.

der hier gezeigte code ob mit sinnige oder unsinnige comennts wird jede 
wette, keiner von uns nach kurzer zeit noch verstehen und darum gings 
mir!

dieser code hier hat leider nur unqualität, lese doch mal bitte jemand 
rtos.c/rtos.h und erkläre mir was das rtos.x hier zum scheduler macht 
und wo es klemmt und z.b. welchen sinn die parameter "// die Aufgaben 
bekommen je 3 Parameter: u16,s16,u8" haben, scheduler principle? round 
robin, preemptive ...? nichts davon offenbart dieser code müllberg!

ich erkenne noch nicht einmal elementare queue functions - liegt aber 
bestimmt an meiner sonnenbrille?!

bevor man irgend eine aufgabe dieser art angeht sollte mann/frau erstmal 
grundsätzliche dinge darüber lesen und ein grundsätzliches verständnis 
erlangen, und bitte auch die richtigen begrifflichkeiten verwenden.

hier http://www.cocoos.net/intro.html da könnt ihr euch mal die finger 
ablecken, an dem beispiel wie ein sehender das macht. aber vorsicht, 
dass ist richtig viel arbeit, und studiert doch mal den code dazu, dann 
lernt ihr auch was dazu - ich habe das bereits hinter mir!

dick unterstrichen, eine der schwierigsten aufgaben, ist die 
namensgebung von functions, variabeln ... ob mit suffix/prefix, 
unterschrich, camel style, gross/klein, ... um eine logische strukture 
des systems gut lesbar abzubilden.

diese aufgabe hat der to weder erkannt noch ansatzweise hinbekommen.

wenn wir hier nicht unter beobachtung wären, dann würde ich euch mal ein 
paar gute pdf bookz zu embedded rtos hochladen, aber auch die muss man 
selber lesen. ... und leider, die werden ja gleich wieder hier gelöscht!

einfach nur zum abtörnen ... was soll das, äh?

//rtos.c
/********************************************************/
/***  Fuer Ringpuffer TaskQueue *************************/
/********************************************************/

static u8 task_count = 0;
static u8 task_schwanz = 0;
static u8 task_kopf = 0;

static void task_count_inc(u8 *count, u8 max_wert){
  (*count)++;
  if(*count >= max_wert){
      *count = 0;
    }
}



mt

von Säbelzahm (Gast)


Lesenswert?

Apollo M. schrieb:


Wichtige Regeln - erst lesen, dann posten!

    Groß- und Kleinschreibung verwenden


Kannst Du das nicht oder bist Du überfordert?

von jemand (Gast)


Lesenswert?

Apollo M. schrieb:
> dieser code hier hat leider nur unqualität

Apollo M. schrieb:
> nichts davon offenbart dieser code müllberg!

Apollo M. schrieb:
> diese aufgabe hat der to weder erkannt noch ansatzweise hinbekommen.

Apollo M. schrieb:
> bevor man irgend eine aufgabe dieser art angeht sollte mann/frau erstmal
> grundsätzliche dinge darüber lesen und ein grundsätzliches verständnis
> erlangen, und bitte auch die richtigen begrifflichkeiten verwenden.

Apollo M. schrieb:
> einfach nur zum abtörnen ... was soll das, äh?

Kann bitte die Moderation hier eingreifen?
Ich denke, an dem gesamten Beitrag ist nichts konstruktives, dafür aber 
vieles, was zumindest an Beleidigungen grenzt. Mich stört es, und mich 
interessiert die ursprüngliche Diskussion zumindest als Mitleser.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Säbelzahm schrieb:
> Wichtige Regeln - erst lesen, dann posten!
>
>     Groß- und Kleinschreibung verwenden

... ich bin nicht regelgläubig, das ist eher was für katholiken, andere 
leichtgläubige, arduino jünger oder was für das breite mittelmass das 
sich hier tummelt!

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

jemand schrieb:
> Ich denke, an dem gesamten Beitrag ist nichts konstruktives, dafür aber
> vieles, was zumindest an Beleidigungen grenzt.

du wohnst auf eine ponnyhof, richtig? bist wahrscheinlich blind und 
beschwerst dich gerne regelmäßig über zuviel/zuwenig sonnenschein?!

wenn ein blinder einen blinden hilft, dann fallen beide in die grube!
das wäre dann wohl für kleingeister immer eine beleidigung, habe ich das 
richtig verstanden?


mt

von Maxim B. (max182)


Lesenswert?

Apollo M. schrieb:

> wenn ein blinder einen blinden hilft, dann fallen beide in die grube!
> das wäre dann wohl für kleingeister immer eine beleidigung, habe ich das
> richtig verstanden?

Ja, so ist das.
Dein Wunsch, auf Klammer zu verzichten, macht Verdacht nahe, du bist ja 
auch kein Profi, wie?

von Dr. Sommer (Gast)


Lesenswert?

Apollo M. schrieb:
> hier http://www.cocoos.net/intro.html da könnt ihr euch mal die finger
> ablecken, an dem beispiel wie ein sehender das macht.

Nunja... Da scheint jemand den Präprozessor sehr zu lieben. Kennt aber 
nichtmal den do-while-"Trick":
1
#define os_assert( test )   if ( !(test) ) {\
2
                                os_on_assert(__LINE__);\
3
                            }

Explizites Padding? Ernsthaft?
1
typedef struct {
2
    uint8_t signal;
3
    uint8_t reserved;   /* Alignment byte */
4
    uint8_t pad0;
5
    uint8_t pad1;
6
    uint16_t delay;     /* Delay of posting in ticks */
7
    uint16_t reload;    /* Reload value for periodic messages */
8
} Msg_t;

Überall nur uint8_t, uint16_t ... verwendet, keine sprechenden Aliase 
wie pid_t oder time_t ... Jetzt irgendwie nicht so der Wahnsinn.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

Dr. Sommer schrieb:
> Überall nur uint8_t, uint16_t ... verwendet, keine sprechenden Aliase
> wie pid_t oder time_t ... Jetzt irgendwie nicht so der Wahnsinn.

da bin ich bei dir!
@pid_t oder time_t, chibios kommt dir da mehr entgegen und läuft auch 
auf avr und small 328p

Dr. Sommer schrieb:
> Nunja... Da scheint jemand den Präprozessor sehr zu lieben. Kennt aber
> nichtmal den do-while-"Trick":

der präprozessor ist ein wesentlicher teil der sprachdefinition von c, 
die meisten rtos setzen entsprechende macros daher massiv ein, weil so 
recht flexible das rtos configuriert werden kann.z.b. werden dann gerne 
verschiedene dispatcher, dynamische/statische timer handler, ... zur 
auswahl gestellt.

code macros in header files, ob mit oder ohne do{...}while(0) kapselung 
sind standard in der landschaft, macros haben vor- und nachteile, ich 
selber benutze sie häufig, anfänger sind regelmäßig darüber befremdet 
...

ich habe hier einige rtos quellen rumliegen und jede hat irgendwas 
besonderes gemacht, z.b. rtos für pic12/16 ist was anderes als für 
pic18/24/32 oder arm/avr. ich kenne auch ein rtos wo jede task als 
eigene isr läuft einschliesslich dem dispatcher - interessanter ansatz, 
wenn kein richtiger sw stack existiert, wie bei pic16.


mt

von Dr. Sommer (Gast)


Lesenswert?

Apollo M. schrieb:
> der präprozessor ist ein wesentlicher teil der sprachdefinition von c,

Ja leider. Den sollte man so sparsam wie möglich einsetzen, und so viel 
wie möglich mit (Inline-) Funktionen machen. In C++ geht das noch 
deutlich besser. In beispielhaft gutem Code sollten jedenfalls nicht 
wesentlich mehr Makros als die Include-Guards auftauchen...

von Budget (Gast)


Lesenswert?

Maxim B. schrieb:
> Säbelzahn schrieb:
> die Programme und die Ideen von
> Anderen.
>
> Sollte ich Fahrrad selbst erfinden?
> Selbst in Datenblatt stehen Programmbeispiele. Nicht benutzen?
>
> Autoren von Ideen habe ich genannt, noch eigene Ideen dazu gebracht...
> Hoffentlich etwas brauchbares bekommen. Ich habe schon mit Scheduler
> (aber die Variante ohne Variablen) ein Ding gemacht.
>
> Selbst J.S.Bach, mein Kollege aus Leipzig, hat die Tonleiter nicht
> selber erfunden.

Nicht gut deutsch dies Depp.

von Säbelzahn (Gast)


Lesenswert?

@Sommer & Apollo

Habt es ihr schon gemerkt, dass ihr beiden euch über die Programmierung 
eines Schedulers so unterhaltet, wie zwei Jungfrauen über Gruppensex?

Weder ihr noch die wissen wovon sie reden.

von Dr. Sommer (Gast)


Lesenswert?

Säbelzahn schrieb:
> Weder ihr noch die wissen wovon sie reden.

Dafür kenn ich mich mit Gruppensex aus ¯\_(ツ)_/¯

von Karl K. (karl2go)


Lesenswert?

Dr. Sommer schrieb:
> In C++ geht das noch
> deutlich besser.

Da isser wieder!

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
Noch kein Account? Hier anmelden.