Forum: Mikrocontroller und Digitale Elektronik AT91SAM7A3 - Problem mit der SPI Initialisierung


von Karl Z. (griffin27)


Lesenswert?

Meine GNU Toolchain:
Eclipse, YAGARTO, openOCD, Parport (Wiggler), AT91SAM7A3-EK

Ich habe mit dem Board nun schon einiges zum laufen gebracht, jedoch 
will die SPI Verbindung einfach nicht.
1
//------------------------------------------------------------------------------
2
/// Configure SPI0 to comunicate with the external 16 bit ADC (ADS8344E)
3
//------------------------------------------------------------------------------
4
static void ConfigureSPI0()
5
{
6
  unsigned int status;
7
8
  // disable SPI
9
  AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIDIS;
10
  // enable SPI Clock
11
  AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, AT91C_ID_SPI0);
12
  // Configure PIO controllers to periph mode
13
  AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, // PIO controller base address
14
    ((unsigned int) AT91C_PA16_SPI0_MOSI) |
15
    ((unsigned int) AT91C_PA11_SPI0_NPCS0) |
16
    ((unsigned int) AT91C_PA15_SPI0_MISO) |
17
    ((unsigned int) AT91C_PA17_SPI0_SPCK), // Peripheral A
18
    0); // Peripheral B
19
  // enable and software reset SPI
20
  AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIEN | AT91C_SPI_SWRST;
21
  AT91C_BASE_SPI0->SPI_MR =
22
    1<<0 | // master mode enable
23
    0<<1 | // peripheral select (0=fixed peripheral)
24
    0<<2 | // peripheral chip select decode (0=direct connection)
25
    1<<4 | // mode fault detection disable
26
    0<<7 | // local loop back enable
27
    0xE<<16 | // peripheral chip select [0:3]; (see page 247 in the prelimainary)
28
          // for NPCS0 use 1110_b = 0xE
29
    0<<24; // delay between chip selects (default minimum 6 MCK cycles)
30
  //AT91C_BASE_SPI0->SPI_CSR[0]= // SPI chip select register 0
31
  AT91C_BASE_SPI0->SPI_CSR[0] =
32
    0<<0 | //clock polarity (
33
    1<<1 | // clock phase
34
    // start clk with low level and sample data on falling edge
35
    1<<3 | // chip select remains active after transfer
36
    (8-8)<<4 | // bits per transfer (8...16); value = num_bits-8
37
    20<<8 | // SPCK bautdrate divider. BR=MCK/value = 2.4MHz
38
    0<<16 | // delay before SPCK (default 1/2 SPCK cycle)
39
    0<<24; // delay between consecutive transfers
40
  //SPI_Enable(AT91C_BASE_SPI0);
41
  status=0;
42
  while((status & (AT91C_SPI_SPIENS)) == 0)
43
  {
44
    AT91C_BASE_SPI0->SPI_CR = (unsigned int) AT91C_SPI_SPIEN; // SPI enable
45
    status = AT91C_BASE_SPI0->SPI_SR;
46
  }
47
}

in der letzten while Schleife bleibt das Programm hängen.
Normalerweise würde man hier keine while-Schleife machen, aber um den 
Fehler zu endecken, habe ich das so gelöst.
Im Statusregister sollte das SPIENS bit gesetzt sein, nachdem man SPI0 
eingeschaltet hat...

Kann mir da bitte jemand weiter helfen?
Das Status Register liefert immer 0!!

Ein änliches Problem hatte ich einmal bei dem MCI (multimedia card 
interface, das nur der SAM7A3 hat). Dazumals programmierte ich auf 
CrossWorks, und ich hab das Problem bis heute nicht gelöst.

lg, Karl

von Karl Z. (griffin27)


Lesenswert?

Mache ich so viel falsch, dass jedem die Worte fehlen, oder hat wirklich 
niemand eine Idee dazu?

von Karl Z. (griffin27)


Lesenswert?

Ich habe nun den Fehler mit systematischer Suche durch auslesen aller 
relevanten Register gefunden.
Die Funktion
1
  AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, AT91C_ID_SPI0);
benötigt nicht die ID selbst, sondern einen 32-bit Wert, in dem das 
entsprechende Bit gesetzt ist. Richtigerweise also:
1
  AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1<<AT91C_ID_SPI0);

Ich glaube, dieser Fehler war mir eine große Lehre.
Wenn man also den Clock einer Peripherieeinheit nicht einschaltet, tut 
das Statusregister garnix. Es liefert immer 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.