Forum: FPGA, VHDL & Co. Kommunikation mit NIOSII SPI


von Niko (Gast)


Lesenswert?

Hi,

ich arbeite gerade an einem Projekt für die FH und muss dabei über das 
SPI im NIOS II Prozessor die Register eines Bauteils beschreiben um die 
Funktion des Bauteils richtig testen zu können.

Das SPI soll 7 bit Reg-Addr, 1 r/w bit und 16 bit daten übertragen.

Ich bin leider was FPGAs anbelangt und NIOS recht unerfahren und da 
happerts schon an Kleinigkeiten.

Kann mir jemand bitte erklären wie man die SPI im NIOS anspricht?
z.B.: im Reg1 den Wert 1 schreiben.


Momentan versuche ich es mit einem normalen IOWR(base,Reg-Nr,data) 
-Befehl, doch beim lesen im I-Net bin ich auf eigene SPI-Aufrufe 
gestoßen, die ich nicht ganz verstehe.

Die sageh dann so aus:
1
while (!(IORD_ALTERA_AVALON_SPI_STATUS(SPI_BASE) & ALTERA_AVALON_SPI_STATUS_TRDY_MSK));
2
IOWR_ALTERA_AVALON_SPI_TXDATA(SPI_BASE, 0x0001);
dazu die meist
1
int alt_avalon_spi_command(alt_u32 base, alt_u32 slave,
2
                           alt_u32 write_length,
3
const alt_u8 * write_data,
4
                           alt_u32 read_length, alt_u8 * read_data,
5
                           alt_u32 flags);

Ich hoffe hier hat jemand mehr Erfahrung wie ich.

Gruß
Niko

von niko (Gast)


Lesenswert?

Ich versteh es immernoch nicht. Ich will 24 bit senden.
Wie sag ich der SPI das nach 24 bit schluss ist?

von Duke Scarring (Gast)


Lesenswert?

Hast Du mal ein Link zum Datenblatt des SPI-Cores?

Duke

von Niko (Gast)


Lesenswert?

Vielen Danke für die Antwort.


Hier das Datenblatt.

http://www.altera.com/literature/ug/ug_embedded_ip.pdf

Ab Seite 83 beginnt der Teil über die SPI.
Ab Seite 91 beginnt die Software.

Momentan sieht es bei mir zusammengefasst so aus:
1
#include <altera_avalon_spi_regs.h>
2
#include <altera_avalon_spi.h>
3
 
4
 
5
main{
6
int test;
7
 
8
while (!(IORD_ALTERA_AVALON_SPI_STATUS(SPI_BASE) & ALTERA_AVALON_SPI_STATUS_TRDY_MSK));
9
 
10
IOWR_ALTERA_AVALON_SPI_TXDATA(SPI_BASE, 0xFFFF);
11
 
12
while (!(IORD_ALTERA_AVALON_SPI_STATUS(SPI_BASE) & ALTERA_AVALON_SPI_STATUS_TRDY_MSK));
13
 
14
test=IORD_ALTERA_AVALON_SPI_RXDATA(SPI_BASE);

Ich sollte eigentlich FFFF am Register auslesen können... oder?
Momentan ergibt das auslesen nur "0".
Muss ich noch andere Sachen beachten ausser die hier genannten?




Gruß
Niko

von Harald F. (hfl)


Lesenswert?

Moin Niko!

Eine Frage: Wieso nudelst Du auf der Hardware herum? Du hast doch die 
Seite 91 im Manual gefunden. Dort steht die Funktion 
alt_avalon_spi_command die für dich die ganze Bitpopelei übernimmt. Nimm 
doch diese Funktion und gut ?!?

Grüße,
Harald

von Niko (Gast)


Lesenswert?

Genao daran scheitert es wie gesagt :D
Wie verwendet man die?

Ich hab gerade seit gestern einen Hänger im Verständniss des commands
1
unsigned char wdata[3];
2
wdata[0]=0x00;       // Addr. 0 & w
3
wdata[0]=0x02;       // MSB
4
wdata[0]=0x03;       // LSB
5
6
int alt_avalon_spi_command(meine_base, 0,3,wdata,0, rdata,0);

Sollte das meine Register beschreiben ?

von Niko (Gast)


Lesenswert?

Ich bekomme beim lesen immer eine 0.
Auch mit dem command.
Das schreiben auf das Register tut nicht.... :(

von Duke Scarring (Gast)


Lesenswert?

@Harald:

Im Datenblatt steht:
1
alt_avalon_spi_command()
2
...
3
Description: ... It supports only SPI masters with
4
data width less than or equal to 8 bits.
Passt also nicht für 24 Bit :-/


@Niko:
1.
Hast Du schon mal nach alt_avalon_spi_command gegoogelt?

2.
> Ich bekomme beim lesen immer eine 0.
> Das schreiben auf das Register tut nicht.... :(
Wie stellst Du das fest? Auf der Hardware oder im Simulator?

3.
Im Datenblatt sind auf Seite 89 ein paar Timingdiagramme. Hast Du das 
richtige Timing eingestellt? Wie sieht den die Instanziierung Deines 
Cores aus? Stimmt die base-address?

Duke

von Niko (Gast)


Lesenswert?

Hallo Duke, hallo Harald,

danke schonmal für eure Antworten.
Messungen mit dem Oszi haben ergeben, dass die SPI 16 Bit pro zyklus 
schreibt. Am Programm lag es wohl doch nicht. (Habs ausgemessen die 
schreibbefehle würden für 8 Bit passen).

Jetzt ist die Frage wo kann ich einstellen das die SPI nur 8 Bit senden 
(fals das möglich ist) und dann stellt sich natürlich die Frage ob
3x8 bit wirklich 24 bit ergeben.

Zur Erklärung:

ich habe mir eine Funktion erstellt die genau das gleiche wie commands 
macht..

write (Reg-adress);
write (MSB);
write(LSB);       // das ist jetzt nur veranschaulicht


Zwischen den einzelnen schreib befehlen habe ich eine totzeit.
liegt wohl teilweise auch am buffer befehl:

while (!(read(TRDY_MSK)); // warte auf ready

doch ich bezweifle das es ohne diesen befehl viel besser wird.

Am Baustein das ich mit der SPI konfigurieren will benötige ich laut 
Datenblatt 24 aufeinanderfolgene Takte.
Ich habe dann zwar 24 sclk Takte, doch die sind jeweils in 8er Blöcke 
unterteilt. Ob es wirklich nichts ausmacht wenn zwischen den sclk's so 
ein abstand ist wird sich zeigen ...
(hoffentlich kann es der Baustein... )

von Harald F. (hfl)


Lesenswert?

----(snip)----
unsigned char wdata[3];
wdata[0]=0x00;       // Addr. 0 & w
wdata[0]=0x02;       // MSB
wdata[0]=0x03;       // LSB

int alt_avalon_spi_command(meine_base, 0,3,wdata,0, rdata,0);

Sollte das meine Register beschreiben ?
----(snap)----

Ja. Das und nix anderes. Wobei Du sicher auch ein array für die 
Emfpangsdaten definiert hast, in dem Fall unsigned char rdata[3]. Und 
meine_base hat hoffentlich den richtigen Wert. Dann solltest Du bei dem 
Funktionsaufruf oben 48 Takte bekommen, 3*8 für wdata und 3*8 für rdata.

von Duke Scarring (Gast)


Lesenswert?

Niko schrieb:
> Ich habe dann zwar 24 sclk Takte, doch die sind jeweils in 8er Blöcke
> unterteilt. Ob es wirklich nichts ausmacht wenn zwischen den sclk's so
> ein abstand ist wird sich zeigen ...
> (hoffentlich kann es der Baustein... )

Das sollte kein Problem sein. Zur Absicherung hilft ein Blick ins 
Datenblatt.

Duke

von Niko (Gast)


Lesenswert?

Gut damit wäre das Problemm gelöst und ich verstehe mittlerweile viel 
mehr vom SPI-Core.
(auch wenn es eigentlich nicht meine Baustelle war :D, doch als Student 
lernt man ja nie umsonst :D)

Vielen Dank Duke, vielen Dank Harald.

von Rumpelstielzchen (Gast)


Lesenswert?

Hallo!

Wie hast du das Problem mit der Totzeit gelöst? Ich versuche auch 
mittels alt_avalon_spi_command auf die Register des Flashs zuzugreifen. 
Aber bei mir landet er immer in der Endlosschleife, weil die Readys 
nicht kommen.

Beim Systemstart wird das Flash durch 
ALTERA_AVALON_EPCS_FLASH_CONTROLLER_INIT gestartet, wo u.a. auch 
alt_avalon_spi_command aufgerufen wird und auch erfolgreich aus der 
Schleife zurückkehrt.

Hat jemand ne Idee?

Das ist der alt_avalon_spi_command Aufruf, der im Init klappt, aber wenn 
ich ihn manuell ausführe, hängen bleibt:
1
const alt_u8 rd_id_cmd[] = {epcs_rdid};
2
  alt_u8 id[3];
3
4
  alt_avalon_spi_command(
5
    base,
6
    0,
7
    sizeof(rd_id_cmd) / sizeof(*rd_id_cmd),
8
    rd_id_cmd,
9
    3,
10
    id,
11
    0
12
  );
13
14
  return (alt_u32) ((id[0] << 16) | (id[1] << 8) | id[2]);


An dieser Stelle bleibt er hängen:
1
/* Wait until the interface has finished transmitting */
2
  do
3
  {
4
    status = IORD_ALTERA_AVALON_SPI_STATUS(base);
5
  }
6
  while ((status & ALTERA_AVALON_SPI_STATUS_TMT_MSK) == 0);

von Rumpelstielzchen (Gast)


Lesenswert?

Korrektur: In dieser Schleife bleibt er hängen.
1
do
2
    {
3
      status = IORD_ALTERA_AVALON_SPI_STATUS(base);
4
    }
5
    while (((status & ALTERA_AVALON_SPI_STATUS_TRDY_MSK) == 0 || credits == 0) &&
6
            (status & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) == 0);

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.