Forum: Compiler & IDEs Compilerfehler bei switch anweisung


von Robert T. (Firma: Thormann) (robertthormann)


Lesenswert?

Hallo!

ich kämpfe noch immer mit meinem "giftigen" TINY40.

Da ich in AVR Studio 5 keine globalen Variablen für den chip verwenden 
kann
und in AVR Studio 6 zwar die globalen Variablen funktionieren aber 
keinerlei ISR auf dem Chip unterstützt werden muss ich zu ungewöhnlichen 
und "unsauberen" Programmiermethoden greifen.

Mein Aktuelles Problem ist dass ich bei meiner SWITCH Anweisung den 
Fehler "R_AVR_7_PCREL against 'no swymbol'" geworfen bekomme und nicht 
weiß was ich dagegen tuen soll (habe dr. google befragt und 
herausgefunden das es ev. an einem zu ?langen? sprung im Prog. liegt) 
jedoch hilft mir, als gcc neuling, diese Information nicht weiter ;)

EV Kann mir ja jemand helfen

GLG
Robert

CODE:

 * Created: 26.06.2012 09:29:00
 *  Author: robert.thormann
 */

//----------------------------------------------------------------------
#define    F_CPU 12000   // Taktfrequenz des myAVR-Boards
#include   <avr/io.h>    // AVR Register und Konstantendefinitionen
#include   <inttypes.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdbool.h>



//----------------------------------------------------------------------


uint16_t readADC(uint8_t channel)
{
   // Funktion 1 zum Auslesen der Spannung

   uint8_t i;                   // Variablen definieren (Zählervariable 
i + Resultat)
   uint16_t result = 0;

   ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
   // wenn adps1+2 on sind und adps0 off, dann ist der Teilungsfaktor 64 
(Tabelle Datasheet)

   ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V 
verwenden, REFS1 gibt es bei Attiny13 nicht
   //externen Kondensator mit 100nF (Aufdruck 104) an AREF auf Masse

   //Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
   ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, 
d.h. Messung starten
   while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist

   // Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
   for (i=0; i<3; i++)
   {
      // Schleife, startet 3*
      ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
      while(ADCSRA & (1<<ADSC));  //Warte bis Messung vorbei

      result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> 
später alles /3
   }

   ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren

   result=result/3;    // Durchschnittswert

   return result;
}


int main(void)                  // Hauptprogramm, startet bei Power ON 
und Reset
{
 uint16_t i=0;
 uint16_t j=0;
 uint16_t ii=0;
 uint16_t jj=0;
 uint16_t delay1 = 0;
 uint16_t delay2 = 0;
 typedef enum {warten, runtime, abbruch} state_t;

 volatile state_t state1 = 0;
 volatile state_t state2 = 0;

 PORTA |= (1<<PA6);          //Taster LED EIN
 PORTA |= (1<<PA7);          //Taster LED EIN

   DDRA=0b11111000;
   DDRB=0b00000000;
   DDRC &= ~ ((1<<PC0) | (1<<PC1) | (1<<PC2));
   PORTA &= ~(1<<PA4);          //1 aus
   while (1)
   {

//-------------------------------ADC 
Bedienen----------------------------------------------------------


    uint16_t result1 = readADC(0); // ruft die ADC Funktion auf an Pin0 
=ADC0
    uint16_t result2 = readADC(1); // ruft die ADC Funktion auf an Pin0 
=ADC1

    delay1 = result1 * 30;      // adc ergebnis = 0-1023 und dieses mit 
30 multiplizieren damit ein einstellbereich bis ca 32000 rauskommt
    delay2 = result2 * 30;



//------------------------------STATEMASCHINE für 1. 
Taster------------------------------------------


switch (state1){


case warten:              //auf Tastendruck warten

  PORTA &= ~(1<<PA4);          //1 aus
  PORTA |= (1<<PA6);          //Taster LED EIN

  if (!(PINB & (1<<PINB0)))      //wenn tastendruck erfolgt nach runtime 
springen


    {
    state1 = runtime;
    }
break;

case runtime:              // State in dem Rel 1 und zähler läuft
  i++;                // Zähler hochzählen
  PORTA |= (1<<PA4);          //1 ein
  PORTA &= ~(1<<PA6);          // Taster LED AUS


  if (!(PINB & (1<<PINB0)))      //bei erneutem TAstendruck in state 
abbruch hüpfen


    {
    state1 = abbruch;
    }


  if(ii > delay1)            //wenn MAximalzeit erreich ist nach warten 
hüpfen
    {
    i=0;
    ii=0;
    state1 = warten;
    }
break;


case abbruch:              //abbruch durch tasterdruck
  i++;

  if(ii > 50)              //kurzes delay gegen prellen
    {
    i=0;
    ii=0;
    state1 = warten;
    }


break;

}


//------------------------------STATEMASCHINE für 2. 
Taster------------------------------------------

switch (state2){


case warten:              //auf Tastendruck warten

  PORTA &= ~(1<<PA3);          //1 aus
  PORTA |= (1<<PA7);          //Taster LED EIN

  if (!(PINB & (1<<PINB1)))      //wenn tastendruck erfolgt nach runtime 
springen


    {
    state2 = runtime;
    }
break;

case runtime:              // State in dem Rel 1 und zähler läuft
  j++;                // Zähler hochzählen
  PORTA |= (1<<PA3);          //1 ein
  PORTA &= ~(1<<PA7);          // Taster LED AUS


  if (!(PINB & (1<<PINB1)))      //bei erneutem TAstendruck in state 
abbruch hüpfen


    {
    state2 = abbruch;
    }


  if(ii > delay2)            //wenn MAximalzeit erreich ist nach warten 
hüpfen
    {
    j=0;
    jj=0;
    state2 = warten;
    }
break;


case abbruch:              //abbruch durch tasterdruck
  j++;

  if(jj > 50)              //kurzes delay gegen prellen
    {
    j=0;
    jj=0;
    state2 = warten;
    }


break;

}

    // Zähler verlangsamen

    if (i > 3)
    {
      ii++;
      i = 0;
    }

    if (j > 3)
    {
      jj++;
      j = 0;
    }
  }
}

von Karl H. (kbuchegg)


Lesenswert?

Robert Thormann schrieb:
> Hallo!
>
> ich kämpfe noch immer mit meinem "giftigen" TINY40.
>
> Da ich in AVR Studio 5 keine globalen Variablen für den chip verwenden
> kann
> und in AVR Studio 6 zwar die globalen Variablen funktionieren aber
> keinerlei ISR auf dem Chip unterstützt werden muss ich zu ungewöhnlichen
> und "unsauberen" Programmiermethoden greifen.

Der Tiny ist doch einer der Brain Dead Tinys. Oder irre ich mich?
Irgendwo hab ich einen Compiler-Patch dafür gesehen, der das Problem 
wieder gradebügelt. (Google ist dein Freund)


Abgesehen davon. Wenn es noch keinen vernünftigen C-Compiler dafür gibt, 
würde ich den µC wechseln (wenn ich das Programm nicht in Assembler 
schreiben kann oder will). Das wär für mich ein absolutes KO-Kriterium, 
einen µC NICHT zu benutzen.

> Mein Aktuelles Problem ist dass ich bei meiner SWITCH Anweisung den
> Fehler "R_AVR_7_PCREL against 'no swymbol'" geworfen bekomme und nicht
> weiß was ich dagegen tuen soll (habe dr. google befragt und
> herausgefunden das es ev. an einem zu ?langen? sprung im Prog. liegt)
> jedoch hilft mir, als gcc neuling, diese Information nicht weiter ;)

Das wird immer so weiter gehen. Du wirst von einem Problem zum nächsten 
wanken und im Endeffekt mehr Zeit damit vertun, diese 'Probleme' zu 
umgehen, als das du produktiv arbeiten kannst.

von Robert T. (Firma: Thormann) (robertthormann)


Lesenswert?

Ich würde ja liebend gernen den chip wechseln, jedoch ist dei HW 
entwicklung der SW entwicklung um einige wochen vorraus und der chip ist 
schon verbaut. Wenn ich jetzt den chip wechsle wirft das alles um wochen 
zurück :(

... und ja es ise in Brain Dead Tiny,.. und NEIN ich hab ihn mir nicht 
ausgesucht gg

LG Robert

von Karl H. (kbuchegg)


Lesenswert?

Robert Thormann schrieb:
> Ich würde ja liebend gernen den chip wechseln, jedoch ist dei HW
> entwicklung der SW entwicklung um einige wochen vorraus und der chip ist
> schon verbaut. Wenn ich jetzt den chip wechsle wirft das alles um wochen
> zurück :(

So wie ich das sehe, wirft dich dieses Compilerproblem (das ja 
eigentlich ein Atmel Problem ist, wenn die absichtlich ihren 
µC-Befehlssatz inkompatibel umabauen) aber auch um Wochen zurück.

Und ein Compiler, dem man nicht vertrauen kann, ist so ziemlich das 
schlimmste überhaupt. Du weißt nie in der SW-Entwicklung, woran du bist.

Ich würde wirklich mal die Jungs von der HW fragen, was das bedeuten 
würde den Tiny mit einem möglichst kompatiblem Exemplar zu ersetzen. 
Erklär ihnen, dass dir sonst nicht viel anderes übrig bleibt, als dein 
Programm in Assembler zu schreiben, wenns etwas Brauchbares sein soll. 
Und ob ihnen bewusst ist, dass du das eigentlich nach Möglichkeit 
vermeiden möchtest, weil es neue Einarbeitungszeit, neue Fehler und 
längere Entwicklunsgszeit bedeutet.

Und ohne dir zu nahe treten zu wollen: Wenn ich mir dein Programm so 
ansehe, dann ist Assembler ganz sicher etwas, was deine Kollegen von der 
HW Fraktion ganz sicher nicht haben wollen. Was soll es denn überhaupt 
werden?


>
> ... und ja es ise in Brain Dead Tiny,.. und NEIN ich hab ihn mir nicht
> ausgesucht *gg*

Trotzdem gilt immer noch
Beitrag "Re: ISR Problem mit AVR Studio6"

von Robert Thormann (Gast)


Lesenswert?

Gibt es einen pinkompartiblen typus den man verwenden könnte?
lg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Robert Thormann schrieb:
> ich kämpfe noch immer mit meinem "giftigen" TINY40.

Wende dich doch an den Atmel-Support.  Die haben den Compiler
verbrochen, dann sollen sie das bitteschön auch supporten und
nicht wir.

Vermutlich bleibt dir aber nicht viel anderes übrig als das Ding
in Assembler zu programmieren oder einen schweineteuren IAR zu
kaufen oder zu hoffen, dass du das ganze Projekt mit einer zeitlich
limitierten Demoversion des IAR gebacken bekommst.

Nein, einen pinkompatiblen anderen AVR gibt's nicht.  ATtiny461 und
ATtiny4313 sind zwar auch 20pinnig, aber haben eine andere Belegung.

von Peter D. (peda)


Lesenswert?

Wie ich das sehe, kämpfst Du an 2 Fronten:
1. Du willst einen halb kastrierten ATtiny verwenden.
2. Du willst keine bewährte Entprellung verwenden, sondern mehr schlecht 
als recht, was mit Delay zusammen schustern.

Da sehe ich ehrlich keine Chance, daß es was wird.



Robert Thormann schrieb:
> #define    F_CPU 12000   // Taktfrequenz des myAVR-Boards

Wo kommen die 12kHz denn her?


Peter

von Peter D. (peda)


Lesenswert?

Es ist natürlich von Atmel eine Dummheit, grundlos gravierende 
Änderungen am Core vorzunehmen.
Und es ist eine Gemeinheit, die ATtiny/halbe mit den standard ATtiny auf 
eine Seite zu stellen und damit einen Neueinsteiger in die Irre zu 
führen, sie wären kompatibel.

Ich setze diese vergurkten Neuschöpfungen (ATtiny/halbe, Xmega ohne CAN) 
jedenfalls nicht ein.

Schreib dochmal an den Atmel-Support, ob die Dir helfen können.


Peter

von Marwin (Gast)


Lesenswert?

Wo ist denn eigentlich genau das Problem? Wenn sich das auf den switch 
beschraenkt, nun, der ist ja leicht zu ersetzen...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:

> Es ist natürlich von Atmel eine Dummheit, grundlos gravierende
> Änderungen am Core vorzunehmen.

Würd ich so nich sagen...

Was auf jeden Fall eine Dummheit ist, ist eine Toolchain zu verteilen, 
von der offenbar noch nie Code auf der Zielhardware lief.

Den Opcode für LDS/STS zu ändern ist kein Problem, sofern die Tools das 
richtig assemblieren. Der ANwender bekommt davon überhapt nix mit -- es 
sei denn, er programmiert in Assembler und rechnet Sprung-Offsets von 
Hand aus.

Marwin schrieb:
> Wo ist denn eigentlich genau das Problem? Wenn sich das auf den switch
> beschraenkt, nun, der ist ja leicht zu ersetzen...

Das ist nicht der Punkt. Wenn Spung-Offsets falsch sind -- was hier 
offenbar der Fall ist -- hilft es nix, das switch zu ersetzen. 
Vielleicht in dem Moment, aber bei kleinen Codeänderungen/erweiterungen 
kommt der Fehler dann an anderer Stelle wieder zurück.

Was genau das Problem ist sollte im Assembler-Dump oder Disassembly des 
Objects sichtbar sein: Es ist eine BRBS oder BRBC Instruktion mit einem 
Offset (in Words), der nicht in 7 Bits signed, d.h. in [-64,63) 
hineinpasst.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Es ist natürlich von Atmel eine Dummheit, grundlos gravierende
> Änderungen am Core vorzunehmen.

Dein "grundlos" kannst du sicher begründen, ja?

Hast du dir denn schon mal überlegt, wie wenig Platz für den Die
wirklich in einem SOT-23-Gehäuse ist?  Warum man den Mini-Core
dann auch wieder in größeren Gehäusen als ATtiny20 und ATtiny40
ausliefert, musst du wohl die Marketingleute fragen.  Vermutlich,
weil man auf diese weise trotzdem noch superbillige Controller
bauen kann, die vielen Leuten genügen.  Guck' dir die Digikey-Preise
an, ein ATtiny40 kostet die Hälfte eines ATtiny4313, und wenn man
den featuremäßig eher vergleichbaren ATtiny461 nimmt, sogar nur 40 %
davon.

Ob man die neuen nun "Tiny" nennen sollte, naja, den Namen hatte man
wohl früher schon etwas zu voreilig vergeben ...

Johann L. schrieb:
> Was auf jeden Fall eine Dummheit ist, ist eine Toolchain zu verteilen,
> von der offenbar noch nie Code auf der Zielhardware lief.

Ich würde nicht sagen, dass davon gar nichts gelaufen ist, aber viel
mehr als das obligatorische "Blinkenlight" scheint es in der Tat nicht
gewesen zu sein.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch schrieb:
> Guck' dir die Digikey-Preise
> an, ein ATtiny40 kostet die Hälfte eines ATtiny4313, und wenn man
> den featuremäßig eher vergleichbaren ATtiny461 nimmt, sogar nur 40 %
> davon.

Der Preis ist kein Maßstab.
Bei der Einführung der Xmega haben sie die auch zu Dumpingpreisen 
abgegeben und dafür die Preise der Standard-AVRs verdreifacht. Davor war 
z.B. der ATmega8 schon unter 1€ zu haben.

Daß die Halbierung der Register eine merkbare Kosteneinsparung bewirkt, 
kann ich mir nicht so richtig vorstellen.

Und die geänderten Befehle dürften garnichts einsparen.
Ob nun mit LPM oder LD der Flash gelesen wird, die Transistoren dafür 
müssen ja trotzdem vorhanden sein.


Peter

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.