Forum: Mikrocontroller und Digitale Elektronik Recursive Funktion führt zu Error 1089 in XC8


von BeastyK (Gast)


Lesenswert?

Moin Leute,

ich versuche mich gerade in Fraktale und der Darstellung auf einem 
ST7735 Display.
Nachdem ich das Problem mit R-G-B und B-G-R gelöst habe steh ich nun 
davor das der Compiler einfach keine Rekursion solcher Art hier mag:
1
void drawCircle_rec(int x, int y, float radius) {
2
  drawCircle(x, y, radius, WHITE);
3
  if(radius > 2) {
4
    radius *= 0.75f;
5
6
//The drawCircle() function is calling itself recursively.
7
8
    drawCircle_rec(x, y, radius);
9
  }
10
}

der Compiler meint dann ganz nett:

ST7735.h:1240: error: (1089) recursive function call to 
"_drawCircle_rec"

Der PIC ist ein PIC18F4455 und XC8.

Nehm jede Hilfe an!

Gruß dat
Beast

von Lothar (Gast)


Lesenswert?

Stackoverflow? Stack vergrößern. int x, int y als globale Variablen. 
Überlaufschutz: max. Zahl von Aufrufen.

von c-hater (Gast)


Lesenswert?

BeastyK schrieb:

> ST7735.h:1240: error: (1089) recursive function call to
> "_drawCircle_rec"

Tja, ich kenne den Compiler nicht persönlich, aber ich würde mal sagen, 
daß ihn nicht die Tatsache der Rekursion an sich stört (sowas kommt ja 
schließlich dauernd vor), sondern vielmehr die Tatsache, daß du da eine 
hübsche Endlos-Rekursion gebaut hast.

Und wenn das so offensichtlich ist, daß es sogar der Compiler merkt, 
dann mußt du einfach mal die verschissene Logik von diesen lächerlichen 
drei Zeilen Code überdenken!!!

Du willst doch nicht dümmer sein als das Programm?

von Sebastian W. (wangnick)


Lesenswert?

Compiler-option --STACK?

LG, Sebastian

von BeastyK (Gast)


Lesenswert?

c-hater schrieb:
> Tja, ich kenne den Compiler nicht persönlich, aber ich würde mal sagen,
> daß ihn nicht die Tatsache der Rekursion an sich stört (sowas kommt ja
> schließlich dauernd vor), sondern vielmehr die Tatsache, daß du da eine
> hübsche Endlos-Rekursion gebaut hast.

Wie du sehen kannst hört der rekursive Teil auf wenn der Radius < 2 
wird!

c-hater schrieb:
> Und wenn das so offensichtlich ist, daß es sogar der Compiler merkt,
> dann mußt du einfach mal die verschissene Logik von diesen lächerlichen
> drei Zeilen Code überdenken!!!

Ja, ähm, genau!

dat
Beast

von BeastyK (Gast)


Lesenswert?

Sebastian Wangnick schrieb:
> Compiler-option --STACK?

Danke Sebastian, ich werde es damit mal versuchen!

von Frank K. (fchk)


Lesenswert?

BeastyK schrieb:

> ST7735.h:1240: error: (1089) recursive function call to
> "_drawCircle_rec"
>
> Der PIC ist ein PIC18F4455 und XC8.

Falsche Architektur, sage ich mal.

Dieser PIC hat einen 31 Worte großen Hardware-Stack. Der liegt nicht 
irgendwo im Adressraum rum, sondern ist irgendwo im Prozessorkern 
verbaut. Den kannst Du weder irgendwo anders hinlegen noch vergrößern 
oder verkleinern. Kleinere PICs haben sogar nur einen 3 Worte Stack.

Ich denke, dass die Compilerentwickler deswegen Rekursionen komplett 
untersagen. Zumindest bei PIC16-Compilern ist das normal. Du musst das 
ganze also in einen iterativen Algorithmus umschreiben.
Alternativen:
- C18 Compiler verwenden; der ist ausschließlich für PIC18F gemacht und 
nicht wie der XC8 auch für PIC12/PIC16.
- einen 16- oder 32 Bit PIC verwenden. Da ist das kein Problem. Du musst 
dafür nur den XC16 bzw XC32 nachinstallieren.

fchk

von BeastyK (Gast)


Lesenswert?

So, hab mal geschaut und die Compiler Option von 
--stack=compiled:auto:auto:auto

Vielleicht hilft das weiter, der XC8 Compiler Guide ist ja ellenlang 
...puhh

Greets
Beast

von BeastyK (Gast)


Lesenswert?

Frank K. schrieb:
> - C18 Compiler verwenden; der ist ausschließlich für PIC18F gemacht und
> nicht wie der XC8 auch für PIC12/PIC16

Ja, sowas in der Art hab ich bei meiner Suche auch schon gelesen, im 
Microchip Forum stand dazu etwas...och menno!

Danke Frank

von Nil (nilsnilss)


Lesenswert?

Wenn ich mich nicht komplett irre, dann hast du da echt eine 
Endlos-Rekursion gebaut: das erste was du in deiner Funktion machst ist 
die Funktion aufrufen. Zur If-Abfrage kommst du nie. In jeder 
aufgerufenen Funktion wird wieder die Funktion aufgerufen. Die Abfrage 
muss vor dem Rekursionsaufruf erfolgen, dann klappt das auch (wenn dann 
der Stack reicht).

von BeastyK (Gast)


Lesenswert?

Nils Friess schrieb:
> Wenn ich mich nicht komplett irre, dann hast du da echt eine
> Endlos-Rekursion gebaut

Doch, du irrst, das eine ist drawCircle_rec und das andere nur 
drawCircle!

Der neue Umgang mit dem Stack unter XC8 scheint mir die Probs zu machen, 
werd wohl auf C18 umsteigen.

MfG
Beast

der nu inne Heia steigt

von Nil (nilsnilss)


Lesenswert?

Sorry - mein Fehler.

Schande über mich...

von BeastyK (Gast)


Lesenswert?

Ach watt,
wahrscheinlich ist c hater auch darüber gestolpert...

gutes Nächtle
Beast

von Eric B. (beric)


Lesenswert?

BeastyK schrieb:

>
1
> void drawCircle_rec(int x, int y, float radius) {
2
>   drawCircle(x, y, radius, WHITE);
3
>   if(radius > 2) {
4
>     radius *= 0.75f;
5
> 
6
> //The drawCircle() function is calling itself recursively.
7
> 
8
>     drawCircle_rec(x, y, radius);
9
>   }
10
> }
11
>

Das ist ein klassischer Fall der Endrekursion, der sich wirklich extrem 
leicht in einer normalen Schleife ohne Rekursion umwandeln lässt. Wie 
das geht überlasse ich dir.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

BeastyK schrieb:
> void drawCircle_rec(int x, int y, float radius) {
>   drawCircle(x, y, radius, WHITE);

Namen, die zu Großteil identisch sind, sollte man vermeiden. Wie man gut 
sieht, verwirrt das schnell.
Besser wäre
1
void drawDisk_rec()

Um rekursive Funktionen überhaupt verwenden zu können, muß die 
Architektur einen echten Stack (Push/Pop) haben und der Compiler muß das 
auch unterstützen.

Und z.B. beim 8051 muß man dem Compiler extra sagen, daß eine Funktion 
reentrant ist, da damit der Overhead drastisch ansteigt. Er muß dann 
alle Variablen auf den Stack legen und kann kein Overlay benutzen.

Manchmal erkennt sogar der Compiler, daß eine Rekursion Unsinn ist und 
optimiert selber den Code zu einer Schleife um.

von BeastyK (Gast)


Lesenswert?

Moin und danke an Eric und Peter für die Hinweise!
1
void drawdisk_rec(int x, int y, float radius) {
2
     while(radius !< 2) {
3
           drawCircle(x, y, radius, WHITE);
4
           radius *= 0.75f;
5
           }
6
}

Ok, läßt sich unverfänglicher und ohne Rekursion und 
Stackschwierigkeiten schreiben...müßte so in der Art stimmen..

Gruß
Beast

von Falk B. (falk)


Lesenswert?

@ BeastyK (Gast)

Den Operator !< gibt es nicht. Eher so.

1
void drawdisk_rec(int x, int y, float radius) {
2
    while(radius > 2) {
3
        drawCircle(x, y, radius, WHITE);
4
        radius *= 0.75f;
5
    }
6
}

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.