Forum: Mikrocontroller und Digitale Elektronik AVR32 EVK1100: Auf Spare SPI (SPI0) schreiben erzeugt TIMEOUT


von Holger M. (nezaya)


Lesenswert?

Hallo,

ich sitze gerade an folgedem Problem.

Ich habe ein AVR32 32UC3A0512-UES auf einem EVK1100 Board, AVR32 Studio 
2.1.1 und das zum Controller gehörende Software-Framework 1.2.2ES.

Ich möchte den Spare SPI (SPI0) Anschluss auf dem Board verwenden. Die 
initialisierung klappt auch (alle Rückgaben SPI_OK), aber sobald ich die 
Funktion spi_write aufrufe, erhalte ich als Rückgabewert 
SPI_ERROR_TIMEOUT.

An den entsprechenden Pins am Board ändert sich der Takt von 0 auf 1, 
dann tut sich nichts mehr.

Die Ansteuerung des Displays auf dem Board ebenfalls über SPI (SPI1) 
klappt gleichzeitig problemlos.

Hat jemand eine Idee woran es liegen könnte?


Zuerst lege dich die GPIO Map folgdermaßen fest:
1
//GPIO MAP for SPARE SPI
2
  static const gpio_map_t SPI0_GPIO_MAP = { { AVR32_SPI0_SCK_0_PIN,
3
  AVR32_SPI0_SCK_0_FUNCTION }, //SPI Clock
4
      { AVR32_SPI0_MISO_0_PIN, AVR32_SPI0_MISO_0_FUNCTION }, //MISO
5
      { AVR32_SPI0_MOSI_0_PIN, AVR32_SPI0_MOSI_0_FUNCTION }, //MOSI
6
      { AVR32_SPI0_NPCS_0_PIN, AVR32_SPI0_NPCS_0_FUNCTION }, //Chip Select NPCS
7
      { AVR32_SPI0_NPCS_1_PIN, AVR32_SPI0_NPCS_1_FUNCTION } //Chip Select 2
8
  };

Dann die Optionen einstellen:
1
//add the spi options driver structure for the SPARE SPI
2
  spi_options_t spi0Options = { .reg= SPARE_SPI_NPCS, .baudrate=1000000,
3
      .bits=8, .spck_delay=0, .trans_delay=0, .stay_act=1, .spi_mode=0,
4
      .fdiv=0, .modfdis=1 };

Die IO-Map zuweisen:
1
  gpio_enable_module(SPI0_GPIO_MAP, sizeof(SPI0_GPIO_MAP)
2
      / sizeof(SPI0_GPIO_MAP[0]));

Den SPI als Master initialisieren:
1
if(spi_initMaster(&AVR32_SPI0, &spi0Options)==SPI_OK)
2
...

Auswahlmodus setzen:
1
if(spi_selectionMode(&AVR32_SPI0, 0, 0, 0)==SPI_OK)
2
...

Chip Register setzen:
1
if(spi_setupChipReg(&AVR32_SPI0, &spi0Options, FOSC0)==SPI_OK)
2
...

SPI0 einschalten:
1
spi_enable(&AVR32_SPI0);

Chip auswählen:
1
spi_selectChip(&AVR32_SPI0, 0)

Schreiben:
1
if (spi_write(&AVR32_SPI0, 101)==SPI_ERROR_TIMEOUT)

Die Vergleiche in den if-Bedingungen sind jeweils wahr.

Die "selbe" Initialisierung wird parallel auch mit dem SPI für das 
Display ausgeführt. Natürlich mit angepasster IO-Map usw... Dieses 
funktioniert fehlerfrei.

Nachtrag: Das Problem das hier 
(Beitrag "AVR32 SPI Problem (gelöst)") beschrieben wird ist 
ähnlich, allerding habe ich schon die vorgeschlagene Lösung umgesetzt.

Zudem habe ich den betreffenden Code mit Main angefügt.

von Holger M. (nezaya)


Angehängte Dateien:

Lesenswert?

Da man scheinbar beim Editieren nichts mehr anhängen kann (zumindest hat 
es zweimal nicht geklappt) hier der Code aus main.

von Holger M. (nezaya)


Lesenswert?

So, ich muss das Thema noch mal hoch holen.

Da bisher niemand geantwortet hat, erweitere ich die Fragestellung.

Ich will nicht mehr wissen, wo der Fehler liegt, sondern nur ob es 
überhaupt schon mal jemand geschafft hat den SPARE SPI auf dem EVK1100 
zu nutzen.

Inzwischen habe ich nämlich mehr Hinweise darauf gefunden, dass es nicht 
geht, als das es geht.

Für eine (positive?) Antwort wäre ich dankbar.

Gruß nezaya

von Holger M. (nezaya)


Lesenswert?

Nachtrag: Der obige Code funktioniert. Falls also jemand das selbe 
Problem hat oder SPI nutzen will kann er obigen Code als Beispiel 
verwenden.

Das Problem war, das ich vor dem Schreiben auf den SPI nicht wie oben 
den Chip-Select mit spi_selectChip(&AVR32_SPI0, 0) sondern versehentlich 
mit spi_selectChip(&AVR32_SPI0, 1) ausgewählt hatte. Mit 
spi_selectChip(&AVR32_SPI0, 0) funktioniert der obige Code. Mit 
spi_selectChip(&AVR32_SPI0, 1) gibt es beim Schreiben den beschriebenen 
Fehler. Damit spi_selectChip(&AVR32_SPI0, 1) funktioniert, müssten wohl 
die Einstellungen des SPI geändert werden. Fall ich dass mal angepasst 
habe poste ich es auch hier.

von Effray (Gast)


Lesenswert?

Vielen Dank, Holger. Das hat mir sehr weitergeholfen. Wirklich super, 
dieser Eintrag. So Beispielcode sollte man öfters jemand posten.
Ich habe lange nach einem Beispielcode gesucht, aber leider findet man 
ja in den meisten Threads/Foren unbrauchbare Antworten wie guck ins 
Datenblatt.

Für meinen Fall, musste ich noch kleine Änderungen vornehmen, aber im 
Wesentlichen konnte ich das übernehmen. Ich poste einmal meinen Code, 
vielleicht kann ich ja auch damit noch einem helfen:

Für den Slave ändert sich nur das Init und SelectionMode entfällt.

Siehe auch:
http://support.atmel.no/knowledgebase/avr32studiohelp/AT32UC3B_Software_Framework/COMPONENTS/MEMORY/DATA_FLASH/AT45DBX/EXAMPLE/DOC/html/a00017.html#1fc77d26387ef26a9b5020e4e04b3b2e

int main(void)
{
  unsigned short RX = 4;
  unsigned short TX = 2;


  int error_code;
  char adr[2] = {0x04,0x00};
  char line[50];
  int i;
  unsigned short data = 6;

  volatile avr32_spi_t *spi;

  // Zuerst GPIO Map festlegen:
  static const gpio_map_t SPI0_GPIO_MAP = { { AVR32_SPI0_SCK_0_0_PIN,
    AVR32_SPI0_SCK_0_0_FUNCTION }, //SPI Clock
        { AVR32_SPI0_MISO_0_0_PIN, AVR32_SPI0_MISO_0_0_FUNCTION }, 
//MISO
        { AVR32_SPI0_MOSI_0_0_PIN, AVR32_SPI0_MOSI_0_0_FUNCTION }, 
//MOSI
        { AVR32_SPI0_NPCS_0_0_PIN, AVR32_SPI0_NPCS_0_0_FUNCTION }, 
//Chip Select NPCS
        { AVR32_SPI0_NPCS_0_0_PIN, AVR32_SPI0_NPCS_0_0_FUNCTION } //Chip 
Select 2
    };


  static const gpio_map_t USART_GPIO_MAP =
  {
    {EXAMPLE_USART_RX_PIN, EXAMPLE_USART_RX_FUNCTION},
    {EXAMPLE_USART_TX_PIN, EXAMPLE_USART_TX_FUNCTION}
  };

  //static const gpio_map_t USART_SPI_GPIO_MAP =
  //{
  //  {EXAMPLE_USART_SPI_SCK_PIN,  EXAMPLE_USART_SPI_SCK_FUNCTION },
  //  {EXAMPLE_USART_SPI_MISO_PIN, EXAMPLE_USART_SPI_MISO_FUNCTION},
  //  {EXAMPLE_USART_SPI_MOSI_PIN, EXAMPLE_USART_SPI_MOSI_FUNCTION},
  //  {EXAMPLE_USART_SPI_NSS_PIN,  EXAMPLE_USART_SPI_NSS_FUNCTION }
  //};

  // USART options.
  static const usart_options_t USART_OPTIONS =
  {
    .baudrate     = 57600,
    .charlength   = 8,
    .paritytype   = USART_NO_PARITY,
    .stopbits     = USART_1_STOPBIT,
    .channelmode  = USART_NORMAL_CHMODE
  };

  // USART SPI options.
  static const usart_spi_options_t USART_SPI_OPTIONS =
  {
  .baudrate     = 60000,
    //.baudrate     = 6000000,
    .charlength   = 8,
    .spimode      = 0,
    .channelmode  = USART_NORMAL_CHMODE
  };

  static const spi_options_t spiOptions =
  {
    .reg          = SPARE_SPI_NPCS,
    //.reg          = DIP204_SPI_NPCS,
    .baudrate     = 60000,
    .bits         = 8,
    .spck_delay   = 0,
    .trans_delay  = 0,
    .stay_act     = 1,
    .spi_mode     = 0,
    .modfdis      = 1
  };

  spi_options_t spi0Options = {
      .reg= SPARE_SPI_NPCS,
      .baudrate=1000000,
      .bits=8,
      .spck_delay=0,
      .trans_delay=0,
      .stay_act=1,
      .spi_mode=0,
      .modfdis=1 };


  // Switch main clock to external oscillator 0 (crystal).
  pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

  // Assign GPIO to USART.
  gpio_enable_module(USART_GPIO_MAP, sizeof(USART_GPIO_MAP) / 
sizeof(USART_GPIO_MAP[0]));

  // Assign GPIO to SPI.
  //gpio_enable_module(USART_SPI_GPIO_MAP, sizeof(USART_SPI_GPIO_MAP) / 
sizeof(USART_SPI_GPIO_MAP[0]));

  // IO-Map zuweisen
  gpio_enable_module(SPI0_GPIO_MAP, sizeof(SPI0_GPIO_MAP) / 
sizeof(SPI0_GPIO_MAP[0]));


  // Initialize USART in RS232 mode.
  usart_init_rs232(EXAMPLE_USART, &USART_OPTIONS, FOSC0);


  // Init Master
  error_code = spi_initMaster(&AVR32_SPI0, &spi0Options);
  sprintf(line,"Init Master, Errorcode %i X\n", error_code);
  usart_write_line(EXAMPLE_USART, line);

  // Auswahlmodus
  error_code = spi_selectionMode(&AVR32_SPI0, 0, 0, 0);
  sprintf(line,"Select Mode, Errorcode %i X\n", error_code);
  usart_write_line(EXAMPLE_USART, line);

  // Chip setzen
  error_code = spi_setupChipReg(&AVR32_SPI0, &spi0Options, FOSC0);
  sprintf(line,"Chip set, Errorcode %i X\n", error_code);
  usart_write_line(EXAMPLE_USART, line);

  // SPI0 einschalten
  spi_enable(&AVR32_SPI0);

  // Chip wählen
  spi_selectChip(&AVR32_SPI0, 0);

  sprintf(line,"SPI success X\n");
  usart_write_line(EXAMPLE_USART, line);


  while (TRUE)  {

    // Schreiben
    spi_write(&AVR32_SPI0, TX);
    spi_read(&AVR32_SPI0, &RX);
    sprintf(line,"Master: Data send: %i ; Received: %i X\n",TX, RX);
    usart_write_line(EXAMPLE_USART, line);
  }


PS: Da sind sicherlich noch überflüssige Teile bei, aber ich denke 
Beispielcode ist einfach das, was weiterhilft. Viel Spaß!

von André (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Holger und Effray
Ich habe hier auch versucht über den SPI0 etwas zu senden.
Erstmal Danke, dass Ihr euch die Mühe gemacht habt Beispielcode 
hochzuladen, das ist der verständlichste den ich bisher gefunden habe.
Dennoch habe ich ein Verständnisproblem:
Holger hat geschrieben

Zuerst lege dich die GPIO Map folgendermaßen fest:

//GPIO MAP for SPARE SPI
  static const gpio_map_t SPI0_GPIO_MAP = { { AVR32_SPI0_SCK_0_PIN,
  AVR32_SPI0_SCK_0_FUNCTION }, //SPI Clock
      { AVR32_SPI0_MISO_0_PIN, AVR32_SPI0_MISO_0_FUNCTION }, //MISO
      { AVR32_SPI0_MOSI_0_PIN, AVR32_SPI0_MOSI_0_FUNCTION }, //MOSI
      { AVR32_SPI0_NPCS_0_PIN, AVR32_SPI0_NPCS_0_FUNCTION }, //Chip 
Select NPCS
      { AVR32_SPI0_NPCS_1_PIN, AVR32_SPI0_NPCS_1_FUNCTION } //Chip 
Select 2
  };

Ich habe das so übernommen, und bekomme bei allen Einträgen Fehler ( 
AVR32_SPI0_SCK_0_PIN undeclared (first use in this function) etc)
aber komme jezt einfach nicht drauf wie und wo das definiert wird.
Kann man das einfach so festlegen? ist AVR32_SPI0_SCK_0_PIN einfach eine 
Variable, die ich frei wählen kann oder sind die in einem file 
vordefiniert?
Im Beispiel dip204_example, das mitgeliefert wurde, wird das so ähnlich 
definiert und das funktioniert einwandfrei.
Ich wäre froh um jede Hilfe.
Warscheinlich fehlt etwas Grundlegendes, irgendwie die falschen files 
included oder so, mein code im Anhang.
Danke!
Gruss André

von André (Gast)


Lesenswert?

bin auf etwas interessantes gestossen: im evk1100.h werden all diese 
Connections deklariert mit AVR32_SPI0_MISO_0_0_PI etc (habe das im 
Beitrag von Effray gar nicht gesehen). wenn ich das in meinem Code 
ändere habe ich dafür "multiple definition of ''" von allen gpio und spi 
funktionen.

von André (Gast)


Lesenswert?

Hat sich erledigt, hatte irgendwie falsche oder doppelte Driver 
eingebunden. Habe noch etwas Mühe mit dem ganzen Framework und 
Strukturen.
Senden hat aber funktioniert, als nächstes ist lesen dran...

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.