Delay-Routine für STM8S

OP #5321681
Lesenswert?

Hat jemand eine funktionierende ms-Delay-Routine ohne Timer für den 
STM8S unter SDCC?

Derzeit nutze ich:
1
static inline void delay(unsigned int t)
2
{
3
    while (t--)
4
        ;
5
}
6

7
static inline void delay_us(unsigned int t)  //Ungenau
8
{
9
    delay(t*4);
10
}
11
  
12
static inline void delay_ms(unsigned int t)  //Ungenau
13
{
14
    delay_us(t*1000);
15
}

Das funktioniert, ist aber nicht zyklengenau, da ich das ungefähr diesem 
Inline-ASM-Beispiel nachempfunden ist:
https://github.com/Hoksmur/stm8_routines/blob/master/delay.h

Mir kommt es so vor, wie wenn der SDCC etwas wegoptimieren würde bzw. 
sich undefiniert verhält - teilweise Fehlermeldungen auftreten, je 
nachdem ob die Funktion "inline" ist.
#5321849
Lesenswert?

Zeitverzögerung mit busy waiting kann man machen. Aber natürlich muß man 
dann die Taktfrequenz berücksichtigen und die innere Schleife schreibt 
man besser in inline Assembler, damit es unabhängig vom Compiler wird. 
Für kurze Delays (wenige µs) sollte es dann besser ein Makro sein. Schau 
dir die delay-Funktionen aus der AVR-libc an. Die funktionieren, also 
kann das Design nicht ganz falsch sein.
OP #5321992
Lesenswert?

Volle22 schrieb:
> Axel S. schrieb:
>> Zeitverzögerung mit busy waiting kann man machen.
>
> machen aber nur Anfänger die das auch bleiben wollen.
> Es ist die schlechteste aller Möglichkeiten.

Bei einer Display-Initialisierung oder anderen "Blocking" Tasks ist das 
durchaus legitim, deswegen frage ich ja auch.    Mit nem Timer kann ich 
es auch, keine Frage ;)

Eigentlich könnte ich es auch bei der Initialisierung nutzen, denn da 
brauche ich den Timer sowieso (noch) nicht für andere Tasks.

Die Frage ist jedoch von ganz allgemeinem Interesse: Wie mache ich 
später, bei anderen Programmen kurze Delays (us-Bereich), z.b. wenn ich 
VGA/Video-Timings erzeuge?   Genau da nutzt man üblicherweise 
Busy-Waiting-Delays.

Axel S. schrieb:
> Zeitverzögerung mit busy waiting kann man machen. Aber natürlich
> muß man
> dann die Taktfrequenz berücksichtigen und die innere Schleife schreibt
> man besser in inline Assembler, damit es unabhängig vom Compiler wird.
> Für kurze Delays (wenige µs) sollte es dann besser ein Makro sein. Schau
> dir die delay-Funktionen aus der AVR-libc an. Die funktionieren, also
> kann das Design nicht ganz falsch sein.

Du meinst, die gesamte innere Schleife? Also auch mit bedingtem Sprung, 
usw..?

Das wäre eine Idee, wenn der Compiler dann von der Optimierung dieses 
Inline-ASM Teils absehen würde.   SDCC unterstützt auch eine "Peephole 
ASM" Optimierung - ob der Inline-Teil dann unangetastet bleibt, weiss 
ich nicht.   Alle bisherigen Beispiele hatten als Inline-ASM nur "NOP", 
der Rest war in C.

In ASM ist es machbar, allerdings kenne ich mich mit der 
STM8-Architektur nicht gut genug aus, ich weiss nicht, wie sich die 
Pipeline, Wait sates etc... auswirken um das zyklengenau zu bekommen. 
Einzige Alternative wäre an einem Portpin zu messen - ich würde es aber 
gerne verstehen. Beim PIC ist es einfach: 4 Quarztakte normal, 4*2 
Quarztakte bei Sprung

Im STM8 CPU Manual sieht man die Problematik:
http://www.st.com/content/ccc/resource/technical/document/programming_manual/43/24/13/9a/89/df/45/ed/CD00161709.pdf/files/CD00161709.pdf/jcr:content/translations/en.CD00161709.pdf

Die Zyklenzahl hängt ab ob aus dem Flash/RAM abgearbeitet wird, sie 
hängt von der Länge des Instruction Words ab (Prefetch-Buffer 96 Bit) 
usw...  - es ist also relativ komplex, ähnlich wie bei 16/32-Bittern.
Gast #5322015
Lesenswert?

du bekommst nie ein zuverlässiges Timing
es mag jetzt meist funktionieren ( weil du nicht siehst das es nur 99.8% 
sind)

Dann ändert jemand eine Interrupt Routine, baut irgendwo noch was ein , 
schliest den Debugger an, nimmt ein neuere Version des Prozessors, 
ändert einen Einstellung ...
schon bist du bei 95%
es fällt auf
und du suchst tagelang nach dem Problem
Gast #5322034
Lesenswert?

Also beim STM32F1xx ode F4xx zählt man mit der

  --> Data Watchpoint and Trace Unit

die Zyklen und kann damit ziemlich präzise auf die Mikrosekunden
zurückrechnen.

Ob es das beim 8-Bitter auch gibt hab ich jetzt nicht nachgeschaut.
#5322195
Lesenswert?

Volle22 schrieb:
> Axel S. schrieb:
>> Zeitverzögerung mit busy waiting kann man machen.
>
> machen aber nur Anfänger die das auch bleiben wollen.
> Es ist die schlechteste aller Möglichkeiten.

Das hängt wesentlich davon ab, wie lange man warten muß. Wenn man z.B. 
ein paar µs bei der Ansteuerung von Peripherie warten muß (z.B. einem 
HD44780 LCD) dann ist busy waiting das Mittel der Wahl.


TU S. schrieb:
>> die innere Schleife schreibt
>> man besser in inline Assembler, damit es unabhängig vom Compiler wird

> Du meinst, die gesamte innere Schleife? Also auch mit bedingtem Sprung,
> usw..?

Ja.

> Das wäre eine Idee, wenn der Compiler dann von der Optimierung dieses
> Inline-ASM Teils absehen würde.

Mir wäre nicht bekannt, daß ein C-Compiler Inline-ASM anfassen würde. 
Wäre auch verfehlt, IMHO. Im Notfall implementierst du die Funktion in 
reinem Assembler.
#5323375
Lesenswert?

TU S. schrieb:
> Das wäre eine Idee, wenn der Compiler dann von der Optimierung dieses
> Inline-ASM Teils absehen würde.   SDCC unterstützt auch eine "Peephole
> ASM" Optimierung - ob der Inline-Teil dann unangetastet bleibt, weiss
> ich nicht.   Alle bisherigen Beispiele hatten als Inline-ASM nur "NOP",
> der Rest war in C.

Inline-ASM fasst der Peephole Optimizer nur an, wenn die Option 
--peep-asm verwendet wird.

Philipp

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren