Forum: FPGA, VHDL & Co. Digilent Nexys3 (Spartan6), Microblaze und die Interrupts


von Matthias W. (iwreakhavoc)


Lesenswert?

Hallo zusammen,

als Teil meiner Masterarbeit möchte ich einen diskreten Zustandsregler 
für ein inverses Pendel implementieren. Das Ganze soll jedoch nicht auf 
einem µController erfolgen, sondern auf einer FPGA-Platform auf der ich 
einen Microblaze IPCore aufsetze.

Wie aus dem Titel ersichtlich handelt es sich um ein Nexys3 Board der 
Firma Digilent, auf welchem ein Xilinx Spartan6 FPGA verbaut ist.
Ich arbeite somit mit der ISE Design Suite 14.7 mit Webpack Lizenz.

Bisher habe ich schon mehrfach erfolgreich das Microblaze MCS mit Hilfe 
des IPCoreGenerators eingebuden und auch einfache Testprogramme 
("HelloWorld" per UART) mit dem SDK erzeugt.

Leider findet man über die Programmierung des Microblaze nur sehr wenige 
Informationen. Bisher waren meine beste Informationsquelle diverse 
Problem-Threads aus dem Xilinx-Forum. Natürlich habe ich auch schon 
etliche PDFs an Dokumentation über Microblaze durchsucht, leider ohne 
großen Erfolg.

Ich habe das "HelloWorld"-Programm so modifiziert, dass immer bei einem 
Tastendruck eine UART-Ausgabe erhalte. Dies läuft im Moment jedoch nur 
über Polling. Als nächsten Schritt wollte ich mich mit Interrupts des 
Microblaze beschäftigen, jedoch komme ich hierbei kein Stück weiter.

Zwar habe ich schon verschiedene Tutorials zum Microblaze gefunden, 
allerdings wird hierbei in der Regel das EDK mit Xilinx Platform Studio 
benutzt, wofür meine Webpack-Lizenz nicht auszureichen scheint, und 
hören die Tutorials meistens nach dem Laden des "HelloWorld"-Programms 
auf.

Ich bin für jeden Tipp dankbar!

Gruß,
Matthias

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Matthias W. schrieb:
> Das Ganze soll jedoch nicht auf einem µController erfolgen, sondern auf
> einer FPGA-Platform auf der ich einen Microblaze IPCore aufsetze.
Und was (ausser dem signifikant höheren Preis) genau ist nun der 
relevante Unterschied zwischen einem fertigen Softcore-uC im FPGA und 
einem fertigen uC z.B. mit ARM Core? Richtig: eigentlich keiner.

Wenn du den Start und die Regelung direkt in VHDL machen würdest, das 
wäre was...

: Bearbeitet durch Moderator
von Matthias W. (iwreakhavoc)


Lesenswert?

Lothar M. schrieb:
> Matthias W. schrieb:
>> Das Ganze soll jedoch nicht auf einem µController erfolgen, sondern auf
>> einer FPGA-Platform auf der ich einen Microblaze IPCore aufsetze.
> Und was (ausser dem signifikant höheren Preis) genau ist nun der
> relevante Unterschied zwischen einem fertigen Softcore-uC im FPGA und
> einem fertigen uC z.B. mit ARM Core? Richtig: eigentlich keiner.
>
> Wenn du den Start und die Regelung direkt in VHDL machen würdest, das
> wäre was...

Na ja, ausgesucht habe ich mir das nur bedingt... ;-)
Es geht vorallem darum, sich in den Microblaze einzuarbeiten und die 
Information für zukünftige Projekte verfügbar zu machen. Als SoC könnte 
man das Ganze ja noch um weitere Komponenten wie z.B. eine 
Kommutierungslogik für BLDC Motoren erweiteren, die dann auch 
tatsächlich von dem Geschwindigkeitsplus des FPGA profitieren.

Im Moment wäre es mir auch lieber, die Regelung auf einem Cortex-M4 
umzusetzen. Hierfür finde ich wesentlich mehr Informationen.

Die Zustandsregelung in VHDL umzusetzen wäre tatsächlich mal eine 
Aufgabe, jedoch bezweifel ich mit meinen beschränkten Kenntnissen, dass 
das so ohne weiteres machbar ist. Ich lasse mich jedoch gerne eines 
besseren belehren :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Matthias W. schrieb:
> Es geht vorallem darum, sich in den Microblaze einzuarbeiten und die
> Information für zukünftige Projekte verfügbar zu machen.
Der scheint zwischenzeitlich tatsächlich frei verfügbar zu sein. Ob es 
allerdings ohne EDK "Spass" macht, damit zu arbeiten, sei dahingestellt.

von Matthias W. (iwreakhavoc)


Lesenswert?

Lothar M. schrieb:
> Matthias W. schrieb:
>> Es geht vorallem darum, sich in den Microblaze einzuarbeiten und die
>> Information für zukünftige Projekte verfügbar zu machen.
> Der scheint zwischenzeitlich tatsächlich frei verfügbar zu sein. Ob es
> allerdings ohne EDK "Spass" macht, damit zu arbeiten, sei dahingestellt.

Also bisher kann ich sagen, dass sich der Spaß definitiv in Grenzen 
hält.

Würde ich wenigstens einfache Beispiel-Projekte finden können, in denen 
mal ein externes Interrupt oder ein Timer verwendet wird, wäre mir ja 
schon ein ganzes Stück geholfen. Leider wirkt es so, als wäre ich der 
erste, der diesen umständlichen Weg beschreitet. :-D

von Matthias W. (iwreakhavoc)


Lesenswert?

Mittlerweile habe ich ein Beispiel gefunden, bei dem ein Timer-Interrupt 
verwendet wird. Ich habe also ein neues Projekt angelegt und den Code 
übernommen, um die Initialisierung nachvollziehen zu können. Leider 
bekomme ich jetzt beim Kompilieren des SDK-Projektes eine Fehlermeldung, 
dass ich die Größe meines BlockRAMs um knapp 3kB überschritten hätte.
Ich kann mir das eigentlich kaum vorstellen, da ich den Microblaze mit 
64kB Programmspeicher erstellt habe und das Programm wirklich kurz ist. 
Es handelt sich eigentlich um ein "HelloWorld" mit einem 
Timer-Interrupt.

Hier meine Quelle:

http://www.ibelimb.com/2014/03/30/generating-a-microblaze-soft-processor-with-ise-webpack-14-dot-7/

von Bit Wurschtler (Gast)


Lesenswert?

mikroblaze gcc-kompilerschalter -s (Optimierung auf size) aktivieren

von Mac G. (macgyver0815)


Lesenswert?

Matthias W. schrieb:
> Leider
> bekomme ich jetzt beim Kompilieren des SDK-Projektes eine Fehlermeldung,
> dass ich die Größe meines BlockRAMs um knapp 3kB überschritten hätte.
> Ich kann mir das eigentlich kaum vorstellen, da ich den Microblaze mit
> 64kB Programmspeicher erstellt habe und das Programm wirklich kurz ist.

Die BRAMs werden in kiloBIT angegeben. Nicht kiloBYTE.
FPGAs haben zwar rattenschnellen Speicher, aber i.d.R. recht wenig.

Edit:
Evtl. hab ichs auch falsch gelesen - hast Du das schon erfolgreich mit 
64KByte synthetisiert?

: Bearbeitet durch User
von Matthias W. (iwreakhavoc)


Lesenswert?

Mac G. schrieb:
> Die BRAMs werden in kiloBIT angegeben. Nicht kiloBYTE.
> FPGAs haben zwar rattenschnellen Speicher, aber i.d.R. recht wenig.
>
> Edit:
> Evtl. hab ichs auch falsch gelesen - hast Du das schon erfolgreich mit
> 64KByte synthetisiert?

Also die Synthese funktionierte bisher einwandfrei.
Ich habe mich zunächst gewundert, dass ich mittlerweile die kostenlose 
Microblaze-Variante mit 64kB erstellen kann. Bis vor kurzem war hier 
eine Grenze bei 16kB. Nach einem Update des IPCores wurde die Grenze 
aber offenbar nach oben verschoben.

von Matthias W. (iwreakhavoc)


Lesenswert?

Bit Wurschtler schrieb:
> mikroblaze gcc-kompilerschalter -s (Optimierung auf size) aktivieren

Mit Optimierung auf size sind es leider noch 2984 byte.

von Gustl B. (-gb-)


Lesenswert?

Das passt doch locker in 64kByte rein und auch in 64kBit (= 8kByte).

von Matthias W. (iwreakhavoc)


Lesenswert?

Gustl B. schrieb:
> Das passt doch locker in 64kByte rein und auch in 64kBit (= 8kByte).

Ich meinte damit 2984 byte zu groß!  (66984 byte) ;-)

von Duke Scarring (Gast)


Lesenswert?

Da läuft irgendwas beim Linken oder mit den Bibliotheken schief.
Ein UART + Hello World sollte in unter 1 kByte passen.

Du kannst ja mal mit nm nachschauen, wo die Bytes verballert werden:
1
$ zpu-elf-nm --print-size --size-sort main.elf
2
00003f37 00000001 T __malloc_lock
3
00003f38 00000001 T __malloc_unlock
4
00005bfc 00000001 D char_count
5
000074b0 00000001 B command_number
6
...

Duke

von Matthias W. (iwreakhavoc)


Lesenswert?

Duke Scarring schrieb:
> Da läuft irgendwas beim Linken oder mit den Bibliotheken schief.
> Ein UART + Hello World sollte in unter 1 kByte passen.
>
> Du kannst ja mal mit nm nachschauen, wo die Bytes verballert werden:
>
1
> $ zpu-elf-nm --print-size --size-sort main.elf
2
> 00003f37 00000001 T __malloc_lock
3
> 00003f38 00000001 T __malloc_unlock
4
> 00005bfc 00000001 D char_count
5
> 000074b0 00000001 B command_number
6
> ...
7
>
>
> Duke

Ok, ich glaube an dieser Stelle werden meine Kompetenzen 
überschritten... :-D
Soll heißen, ich habe keine Ahnung wie ich das bewerkstellige.

von Matthias W. (iwreakhavoc)


Lesenswert?

Hm, auf Grund deines Hinweises bezüglich des Linkers, habe ich mir 
gerade mal genauer das Linker Script angeschaut. Irgendwie sieht das 
alles recht komisch aus. (Available Memory Regions: 
ilmb_cntlr_dlmb_cntlr Base Adress: 0x00000050 Size: 0x00001FB0)

Wenn ich mir mit Hilfe des Xilinx Tools "Generate a linker script" ein 
neues erzeugen möchte, ist beim Hardware Memory Map auch nur die Rede 
von 8 kB Speicher?!

von Matthias W. (iwreakhavoc)


Lesenswert?

Wie es aussieht, habe ich beim Erstellen des Hardware Projects im SDK 
das falsche BMM-File ausgewählt.
Ich kann mittlerweile die besagten Code kompilieren und ausführen. Auch 
externe Interrupts habe ich mit Hilfe eines Buttons triggern können.

Jetzt versuche ich derzeit zwei externe Interrupts über zwei 
verschiedene Buttons zu triggern.
Leider scheitere ich hierbei.

Ich initialisiere beide Buttons über XIOModule, da ich dies in der 
xiomodule.h gelesen habe.
Nach dem Aufruf von XIOModule_Intialize, _Start, _Connect und _Enable 
für beide XIOModule funktioniert jedoch immer nur eins.
Offenbar überschreibe ich den anderen immer wieder.

von Matthias W. (iwreakhavoc)


Lesenswert?

Offenbar funktioniert es so nicht. Vermutlich verstehe ich die Funktion 
des XIOModules nicht. In der xiomodule.h habe ich gelesen, dass ich für 
jedes IO-Device eine XIOModule-Variable anlegen muss. Leider scheine ich 
die Initialisierung meines ersten Interrupts durch das zweite zu 
überschreiben.
Leider ist mir nicht ganz klar wieso...
Hier mein Code:
1
#include <stdio.h>
2
#include <xparameters.h>
3
#include <xiomodule.h>
4
#include "init.h"
5
6
7
void btnrISR(void);
8
void btnlISR(void);
9
10
char btnrFlg=0,btnlFlg=0;
11
XIOModule btnr,btnl;
12
13
int main()
14
{
15
    init();
16
17
    microblaze_register_handler(XIOModule_DeviceInterruptHandler,XPAR_IOMODULE_0_DEVICE_ID);
18
19
    XIOModule_Initialize(&btnr,XPAR_IOMODULE_0_DEVICE_ID);
20
    XIOModule_Start(&btnr);
21
    XIOModule_Connect(&btnr,XIN_IOMODULE_GPI_1_INTERRUPT_INTR,btnrISR,NULL);
22
    XIOModule_Enable(&btnr,XIN_IOMODULE_GPI_1_INTERRUPT_INTR);
23
24
    XIOModule_Initialize(&btnl,XPAR_IOMODULE_0_DEVICE_ID);
25
    XIOModule_Start(&btnl);
26
    XIOModule_Connect(&btnl,XIN_IOMODULE_GPI_1_INTERRUPT_INTR,btnlISR,NULL);
27
    XIOModule_Enable(&btnl,XIN_IOMODULE_GPI_1_INTERRUPT_INTR);
28
29
    microblaze_enable_interrupts();
30
31
    xil_printf("start\n\r");
32
33
    while(1){
34
      if(btnrFlg==1){
35
        btnrFlg=0;
36
        xil_printf("Button Right\n\r");
37
      }
38
      if(btnlFlg==1){
39
        btnlFlg=0;
40
          xil_printf("Button Left\n\r");
41
    }
42
    }
43
44
    return 0;
45
}
46
47
void btnrISR(void){
48
  btnrFlg=1;
49
}
50
void btnlISR(void){
51
  btnlFlg=1;
52
}

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.