Forum: Mikrocontroller und Digitale Elektronik Delay bei ATtiny4


von Tim H. (hotty) Benutzerseite


Lesenswert?

Hallo,

ich spiele gerade mit dem ATtiny4 etwas rum... es soll eignetlich nur 
ein einfaches Blinklicht mit 2 LEDs werden.
Zum Test habe ich also mal ein Programm geschrieben, was PORTB an und 
aus machen soll:
1
#include <avr/io.h>
2
3
#define F_CPU 1000000UL
4
#include <util/delay.h>
5
6
7
8
int main(void)
9
{
10
  DDRB = 0xFF;
11
    PORTB = 0x00;
12
  
13
    while(1)
14
    {
15
    PORTB = 0x00;
16
    _delay_ms(500);
17
    PORTB = 0xFF;
18
    _delay_ms(500);
19
    }
20
}
das funktioniert soweit auch ganz gut. Nur komisch finde ich es wenn ich 
das Delay auf z.b. 100ms setzen möchte. Dann sagt mir der Compiler:

 error: unable to generate reloads for:
 internal compiler error: in find_reloads, at reload.c:3821

Wenn ich bei 100ms F_CPU auf 8000000 setze läuft das Projekt wieder ohne 
Fehler durch.
Ich kann mir jetzt irgendwie nur vorstellen, dass die delay Bibilotheken 
noch nicht für die neuen Tinys angepasst wurden (obwohl die neuste 
AVRStudio-Version nutze)
Hatte einer von euch schonmal so ein Problem? Wahrscheinlich übersehe 
ich gerade einfach nur eine Kleinigkeit.

Danke schon mal für eure Antworten !

Gruß

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Tim H. schrieb:

>  error: unable to generate reloads for:
>  internal compiler error: in find_reloads, at reload.c:3821

Atmel hat den avr-gcc aufgebohrt um die tinys zu unterstützen und dabei 
alle Register aus des Registerklasse "w" verboten.

An anderer Stelle — nämlich den delay-builtins — fordern sie aber, daß 
das Loop-Register die Constraint "w" haben muss.

Du sieht gerade den Effekt davon.

Ergo:

- Die Inline-Assebler-Version aus der avr-libc verwenden.
  Da gibt's irgendwo ein Makro das erkennt ob built-ins da sind oder
  nicht.

- Die Zeiten so stückeln, daß der Fehler nicht mehr auftritt.

von Tim H. (hotty) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Ergo:
>
> - Die Inline-Assebler-Version aus der avr-libc verwenden.
>   Da gibt's irgendwo ein Makro das erkennt ob built-ins da sind oder
>   nicht.
>
> - Die Zeiten so stückeln, daß der Fehler nicht mehr auftritt.

Danke erstmal!

Kannst du mir da ein Beispeil geben? Ich komme mit Assembler nicht so 
wirklich klar :)

von User (Gast)


Lesenswert?

bei einem Micro mit 512 Byte Flash nimmt man auch keinen C Compiler

von Ingo (Gast)


Lesenswert?

Warum nicht? Wenn man Assembler nicht kann, Atmel es nun möglich macht, 
sehe ich keine Gründe die dagegen sprechen. Es sei denn das Prjekt 
scheitert weil der Code zu groß ist, dass muss man aber vorher 
abschätzen. So pauschal kann man das nicht sagen.


Ingo

von (prx) A. K. (prx)


Lesenswert?

Ich frag mich eher andersrum: Warum sollte jemand, der nicht zigtausende 
davon verbaut, so ein Ding einsetzen?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

@Tim: Schau einfach mal in die delay.h rein, da gibt's ein Makro daß
du setzen musst.

von Tim H. (hotty) Benutzerseite


Lesenswert?

Also die Flash größe reicht mir... Das Programm oben braucht 92 Byte 
Flash. Und ja ich habe vor davon um die 1000 Stück zu verbauen.

Und: meint ihr soein Makro?
1
/** \ingroup util_delay_basic
2
3
    Delay loop using a 16-bit counter \c __count, so up to 65536
4
    iterations are possible.  (The value 65536 would have to be
5
    passed as 0.)  The loop executes four CPU cycles per iteration,
6
    not including the overhead the compiler requires to setup the
7
    counter register pair.
8
9
    Thus, at a CPU speed of 1 MHz, delays of up to about 262.1
10
    milliseconds can be achieved.
11
 */
12
void
13
_delay_loop_2(uint16_t __count)
14
{
15
  __asm__ volatile (
16
    "1: sbiw %0,1" "\n\t"
17
    "brne 1b"
18
    : "=w" (__count)
19
    : "0" (__count)
20
  );
21
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Tim H. schrieb:

> Und: meint ihr soein Makro?

Prinzipiell: Ja

Konkret: Nein

Denn es verwendet Constraint "w", die Atmel aus Bequemlickkeit aus dem 
Compiler gekickt hat, und zudem SBIW, den es auf tiny nicht hat.

Also "=w" durch "=d" ersetzen und SBIW durch das längere, aber 
gleich-schnelle SUBI+SBCI.

von Tim H. (hotty) Benutzerseite


Lesenswert?

Hallo,

danke für die Antwort.
jetzt bekomme ich diese Fehlermeldung:
Error: illegal opcode sbiw for mcu attiny4
in der Schleife:
1
void _delay_loop_2(uint16_t __count)
2
{
3
  __asm__ volatile (
4
    "1: sbiw %0,1" "\n\t"
5
    "brne 1b"
6
    : "=d" (__count)
7
    : "0" (__count)
8
  );
9
}
Ich denke ich muss diese Zeile anpassen: "1: sbiw %0,1" "\n\t" aber wie?

Gruß

von (prx) A. K. (prx)


Lesenswert?

Einfach mal lesen was Johann geschrieben hat.

von Ingo (Gast)


Lesenswert?

Der Befehl SBIW gibt's nicht, wie Johan angemerkt hat, du jedoch nicht 
beachtest...

von Tim H. (hotty) Benutzerseite


Lesenswert?

ja das weiß ich nur aus dem einen muss ich ja 2 Befehle machen ... nur 
wie?

von Max (Gast)


Lesenswert?


von Tim H. (hotty) Benutzerseite


Lesenswert?

hmm gibt es keine Möglichkeit die delay.h einfach anzupassen?

von Eumel (Gast)


Lesenswert?

Schreib dir doch ne eigene Delay Routine....ist jetzt nicht so 
schwierig.

von Cyblord -. (cyblord)


Lesenswert?


von Tim H. (hotty) Benutzerseite


Lesenswert?

Hallo,

danke für eure Hilfe schonmal. Ich hab jetzt diese Schleife geschrieben:
1
void delay(uint8_t ms){
2
  uint16_t cnt = 17355;
3
4
  while(cnt != 0){  
5
    cnt--;
6
  }
7
}
Die Schleife läuft genau 1s wenn ich den Code nicht optimiere. Aber 
dadurch braucht PORTB=0x00; auch mehrere Befehle. Wenn ich wieder die 
Optimierung einstelle, dann wird meine Schleife einfach wegoptimiert...

von alarm (Gast)


Lesenswert?

Tim H. schrieb:
> Wenn ich wieder die
> Optimierung einstelle, dann wird meine Schleife einfach wegoptimiert...
Dann pack ein volatile asm("nop") rein.

von Tim H. (hotty) Benutzerseite


Lesenswert?

Danke!
Funktioniert super :)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Lass doch den MURKS mir C-Warteschleifen!

Korrigiere stattdessen den Header!
1
void _delay_loop_2 (uint16_t __count)
2
{
3
  __asm__ volatile (
4
    "1: subi %A0,1" "\n\t"
5
    "sbci %B0,0"    "\n\t"
6
    "brne 1b"
7
    : "=d" (__count)
8
    : "0" (__count)
9
  );
10
}

Wie's aussieht, hat Atmel nichtmal ein built-in Makro eingebaut, mit dem 
man diese brainf**ck Architektur abfragen kann...

http://distribute.atmel.no/tools/opensource/avr-gcc/gcc-4.5.1/32-gcc-4.5.1-avrtiny10.patch

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.