Forum: FPGA, VHDL & Co. Konfiguriere Xilinx SPI IP als Slave


von FPGA B. (beginner_eda)


Angehängte Dateien:

Lesenswert?

Hallo,

ich probiere Xilinx IP als Salve zu konfigurieren:
https://www.xilinx.com/support/documentation/ip_documentation/axi_quad_spi/v3_2/pg153-axi-quad-spi.pdf

aber habe kein Erfolg.

Ich wolte nicht auf Flash zu schreiben sondern mit externe spi Master 
als slave zu kommunizieren.

Siehe Anhang für Blockdiagram.

wie steht auf Seite 84, habe "Enable Master Mode" unchecked und folgende 
code benutz:
1
******************************************************************************/
2
/***************************** Include Files *********************************/
3
#include "xparameters.h" /* XPAR parameters */
4
#include "xspi.h" /* SPI device driver */
5
#include "xspi_l.h"
6
/************************** Constant Definitions *****************************/
7
/*
8
* The following constants map to the XPAR parameters created in the
9
* xparameters.h file. They are defined here such that a user can easily
10
* change all the needed parameters in one place.
11
*/
12
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
13
14
15
16
/***************** Macros (Inline Functions) Definitions *********************/
17
18
/************************** Function Prototypes ******************************/
19
int SpiPolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId);
20
/************************** Variable Definitions *****************************/
21
/*
22
* The instances to support the device drivers are global such that the
23
* are initialized to zero each time the program runs.
24
*/
25
static XSpi SpiInstance; /* The instance of the SPI device */
26
/*
27
* The following variables are used to read and write to the Spi device, they
28
* are global to avoid having large buffers on the stack.
29
*/
30
u8 ReadBuffer;
31
u8 WriteBuffer;
32
33
/*****************************************************************************/
34
/**
35
*
36
* Main function to call the Spi Polled example.
37
*
38
* @param None
39
*
40
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
41
*
42
* @note None
43
*
44
******************************************************************************/
45
int main(void)
46
{
47
int Status;
48
/*
49
* Run the Spi Polled example.
50
*/
51
Status = SpiPolledExample(&SpiInstance, SPI_DEVICE_ID);
52
if (Status != XST_SUCCESS) {
53
return XST_FAILURE;
54
}
55
return XST_SUCCESS;
56
}
57
/*****************************************************************************/
58
/**
59
*
60
* This function does a minimal test on the Spi device and driver as a
61
* design example. The purpose of this function is to illustrate how to use
62
* the XSpi component using the polled mode.
63
*
64
* This function sends data and expects to receive the same data.
65
*
66
*
67
* @param SpiInstancePtr is a pointer to the instance of Spi component.
68
* @param SpiDeviceId is the Device ID of the Spi Device and is the
69
* XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
70
*
71
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
72
*
73
* @note
74
*
75
* This function contains an infinite loop such that if the Spi device is not
76
* working it may never return.
77
*
78
******************************************************************************/
79
int SpiPolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId)
80
{
81
int Status;
82
u32 Count;
83
u8 Test;
84
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
85
/*
86
* Initialize the SPI driver so that it is ready to use.
87
*/
88
ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
89
if (ConfigPtr == NULL) {
90
return XST_DEVICE_NOT_FOUND;
91
}
92
Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
93
ConfigPtr->BaseAddress);
94
if (Status != XST_SUCCESS) {
95
return XST_FAILURE;
96
}
97
/*
98
* Perform a self-test to ensure that the hardware was built correctly.
99
*/
100
Status = XSpi_SelfTest(SpiInstancePtr);
101
if (Status != XST_SUCCESS) {
102
return XST_FAILURE;
103
//xil_printf("xyz\n\r");
104
}
105
/*
106
* Run loopback test only in case of standard SPI mode.
107
*/
108
if (SpiInstancePtr->SpiMode != XSP_STANDARD_MODE) {
109
return XST_SUCCESS;
110
//xil_printf("xyz\n\r");
111
}
112
/*
113
* Set the Spi device as a slave.
114
115
  //siehe Seite 25 und 26. */
116
    XSpi_SetControlReg(&Spi, 0x02);
117
118
/*
119
* Start the SPI driver so that the device is enabled.
120
*/
121
XSpi_Start(SpiInstancePtr);
122
/*
123
* Disable Global interrupt to use polled mode operation
124
*/
125
XSpi_IntrGlobalDisable(SpiInstancePtr);
126
/*
127
128
129
/*
130
* Receive the data. only one byte to receive
131
*/
132
XSpi_Transfer(SpiInstancePtr, ReadBuffer, ReadBuffer, 1);
133
XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, 1);


Bei mir ist auch nicht Klar wann benutz man
XSpi_Transfer(&Spi, ReadBuffer, ReadBuffer, 1);
XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, 1);
und wann
XSpi_ReadReg(BaseAddress, RegOffset)
XSpi_WriteReg(BaseAddress, RegOffset, RegisterValue)
zu lesen und schreiben und was ist unterschied?

P.S. Sorry für meinen Grammatikfehler.

: Bearbeitet durch User
von Klakx (Gast)


Lesenswert?

FPGA B. schrieb im Beitrag #4797271:
> Ich wolte nicht auf Flash zu schreiben sondern mit externe spi Master
> als slave zu kommunizieren.

Du willst also Slave sein? Dein Beispiel behandelt aber die Rolle als 
Master.

FPGA B. schrieb im Beitrag #4797271:
> Bei mir ist auch nicht Klar wann benutz man
> XSpi_Transfer(&Spi, ReadBuffer, ReadBuffer, 1);
> XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, 1);
> und wann
> XSpi_ReadReg(BaseAddress, RegOffset)
> XSpi_WriteReg(BaseAddress, RegOffset, RegisterValue)
> zu lesen und schreiben und was ist unterschied?

Ganz einfach mit Read/WriteReg ließt/schreibst du an einer bestimmten 
Adresse einen Wert bestimmter Datenbreite.

Bei den Transfer-Kommandos geht es um mehrere Lese/Schreibbefehle, die 
von/zu einem Speicherpuffer gesendet werden. Xilinx ist nicht knausrig 
mit der Doku, ließ doch einfach mal was an der Funktion steht.

von FPGA B. (beginner_eda)


Lesenswert?

Klakx schrieb:
> FPGA B. schrieb im Beitrag #4797271:
> Du willst also Slave sein? Dein Beispiel behandelt aber die Rolle als
> Master.
>
Danke für deine Antwort.
Ich vermute diese Zeile in oben code macht es Slave:

* Set the Spi device as a slave.

  //siehe Seite 25 und 26. */
    XSpi_SetControlReg(&Spi, 0x02);

und habe auch "Enable Master Mode" unchecked (Seite 84).

Was noch bracht man für die Rolle als Slave zu einstellen?

von Klakx (Gast)


Lesenswert?

schau dir doch mal das xspi_slave_polled_example.c an. Das gibt es 
zumindest bei SDK 2016.2.

Prinzipiell brauchst du ein Loop (polled) oder einen Interrupt-Handler, 
der deine SPI-Kommandos entgegennimmt und ggf. Daten zurückgibt. Das 
läuft wahrscheinlich hier u.a. ab:
1
/*
2
 * Initialize the write buffer with pattern to write, initialize the
3
 * read buffer to zero so that it can be verified after the read.
4
 */
5
Test = 0xF0;
6
for (Count = 0; Count < BUFFER_SIZE; Count++) {
7
WriteBuffer[Count] = (u8)(Count + Test);
8
ReadBuffer[Count] = 0;
9
}
10
11
/*
12
 * Prepare the data buffers for transmission and to send/receive data
13
 * when the SPI device is selected by a master.
14
 */
15
XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);

Hier im Codestück siehst du, dass man seine eigenen Speicher WriteBuffer 
und ReadBuffer vorbereitet und dann an den SPI-Controller verlinkt.

Dieser kann die dann "aussaugen" :)

von FPGA B. (beginner_eda)


Lesenswert?

Hallo,
Master/Slave kommuniziert(Write/Read) mit 2 byte Datei. SPI Master läuft 
in CPOL=1 und CPH=1 mode.
http://www.totalphase.com/support/articles/200349236-SPI-Background

habe while loop benutzt zu lesen und schreiben(0xF012) .
while(1)
{
  XSpi_Transfer(SpiInstancePtr, 0xF012, ReadBuffer1, 2);
  xil_printf("0x%x \r\n", ReadBuffer1);
}

aber in output kommt nur "Entering the S" und geht nicht weiter.

Hier ist die modifizierte code:
1
/* $Id: xspi_slave_polled_example.c,v 1.1.2.1 2011/08/09 06:59:27 svemula Exp $ */
2
3
******************************************************************************/
4
/*****************************************************************************/
5
/**
6
* @file xspi_slave_polled_example.c
7
*
8
* This file contains a design example using the Spi driver (XSpi) and the SPI
9
* device as a Slave, in polled mode.
10
*
11
* This example fills the Spi Tx buffer with the number of data bytes it expects
12
* to receive from the master and then Spi device waits for an external master to
13
* initiate the transfer. When the master initiates the transfer, the Spi device
14
* receives data from the master and simultaneously sends the data in Tx buffer
15
* to the master. Once the transfer is complete, this example prints the data
16
* received from the master. The number of bytes to be received by the Spi slave
17
* is defined by the constant BUFFER_SIZE in this file.
18
*
19
* The external SPI devices that are present on the Xilinx boards don't support
20
* the Master functionality. This example has been tested with an off board
21
* external SPI Master device and the Xilinx SPI device configured as a Slave.
22
* This example has been tested for byte-wide SPI transfers.
23
*
24
* @note
25
*
26
* This example assumes that there is a STDIO device in the system.
27
*
28
*<pre>
29
* MODIFICATION HISTORY:
30
*
31
* Ver   Who  Date     Changes
32
* ----- ---- -------- ---------------------------------------------------------
33
* 1.00a psk  09/05/08 First Release
34
* 3.00a ktn  10/28/09 Converted all register accesses to 32 bit access.
35
*          Updated to use the HAL APIs/macros. Replaced call to
36
*          XSpi_Initialize API with XSpi_LookupConfig and
37
*          XSpi_CfgInitialize.
38
*
39
*</pre>
40
******************************************************************************/
41
42
/***************************** Include Files *********************************/
43
44
#include "xparameters.h"  /* XPAR parameters */
45
#include "xspi.h"    /* SPI device driver */
46
#include "stdio.h"
47
48
/************************** Constant Definitions *****************************/
49
50
/*
51
 * The following constants map to the XPAR parameters created in the
52
 * xparameters.h file. They are defined here such that a user can easily
53
 * change all the needed parameters in one place.
54
 */
55
#define SPI_DEVICE_ID    XPAR_SPI_0_DEVICE_ID
56
57
/*
58
 * This is the size of the buffer to be transmitted/received in this example.
59
 */
60
#define BUFFER_SIZE    16
61
62
/**************************** Type Definitions *******************************/
63
64
65
/***************** Macros (Inline Functions) Definitions *********************/
66
67
68
/************************** Function Prototypes ******************************/
69
70
static int SpiSlavePolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId);
71
72
/************************** Variable Definitions *****************************/
73
74
/*
75
 * The instances to support the device drivers are global such that they are
76
 * initialized to zero each time the program runs. They could be local but
77
 * should at least be static so that they are zeroed.
78
 */
79
static XSpi SpiInstance;   /* The instance of the SPI device */
80
81
/*
82
 * The following variables are used to read from the  Spi device, these are
83
 * global to avoid having large buffers on the stack.
84
 */
85
u8 ReadBuffer[BUFFER_SIZE];
86
u8 WriteBuffer[BUFFER_SIZE];
87
u16 ReadBuffer1;
88
89
/*
90
 * The following variable allows a test value to be added to the values that
91
 * are sent in reflection to the Master transmission such that unique values can
92
 * be generated to guarantee the transfer from Slave to Master is successful.
93
 */
94
int Test;
95
96
/*****************************************************************************/
97
/**
98
*
99
* Main function to call the Spi Slave example in polled mode.
100
*
101
* @param  None
102
*
103
* @return  XST_SUCCESS if successful, otherwise XST_FAILURE.
104
*
105
* @note    None
106
*
107
******************************************************************************/
108
int main(void)
109
{
110
  int Status;
111
112
  /*
113
   * Run the Spi Slave polled example.
114
   */
115
116
  Status = SpiSlavePolledExample(&SpiInstance, SPI_DEVICE_ID);
117
  if (Status != XST_SUCCESS) {
118
    return XST_FAILURE;
119
120
121
  }
122
  return XST_SUCCESS;
123
}
124
125
/*****************************************************************************/
126
/**
127
*
128
* This function does a minimal test on the Spi device and driver as a design
129
* example. The purpose of this function is to illustrate the device slave
130
* functionality in polled mode. This function receives data from a master and
131
* prints the received data.
132
*
133
* @param  SpiInstancePtr is a pointer to the instance of Spi component.
134
*
135
* @param  SpiDeviceId is the Device ID of the Spi Device and is the
136
*    XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
137
*
138
* @return  XST_SUCCESS if successful, otherwise XST_FAILURE.
139
*
140
* @note    This function contains an infinite loop such that if the Spi
141
*    device doesn't receive any data, it may never return.
142
*
143
******************************************************************************/
144
int SpiSlavePolledExample(XSpi *SpiInstancePtr, u16 SpiDeviceId)
145
{
146
  XSpi_Config *ConfigPtr;
147
  int Status;
148
  u32 Count;
149
150
  xil_printf("\r\nEntering the Spi Slave Polled Example.\r\n");
151
  xil_printf("Waiting for data from SPI master\r\n");
152
153
  /*
154
   * Initialize the SPI driver so that it's ready to use, specify the
155
   * device ID that is generated in xparameters.h.
156
   */
157
  ConfigPtr = XSpi_LookupConfig(SpiDeviceId);
158
  if (ConfigPtr == NULL) {
159
    return XST_FAILURE;
160
  }
161
  Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
162
        ConfigPtr->BaseAddress);
163
  if (Status != XST_SUCCESS) {
164
    return XST_FAILURE;
165
  }
166
167
168
169
170
  /*
171
   * The SPI device is a slave by default and the clock phase and polarity
172
   * have to be set according to its master. In this example, CPOL is set
173
   * to active low and CPHA is set to 1.
174
   */
175
  Status = XSpi_SetOptions(SpiInstancePtr, XSP_CLK_PHASE_1_OPTION |
176
         XSP_CLK_ACTIVE_LOW_OPTION);
177
  if (Status != XST_SUCCESS) {
178
    return XST_FAILURE;
179
  }
180
181
  /*
182
   * Start the SPI driver so that the device is enabled.
183
   */
184
  XSpi_Start(SpiInstancePtr);
185
186
  /*
187
   * Disable Global interrupt to use polled mode operation.
188
   */
189
  XSpi_IntrGlobalDisable(SpiInstancePtr);
190
191
192
  /*
193
   * Prepare the data buffers for transmission and to send/receive data
194
   * when the SPI device is selected by a master.
195
   */
196
while(1)
197
{
198
  XSpi_Transfer(SpiInstancePtr, 0xF012, ReadBuffer1, 2);
199
  xil_printf("0x%x \r\n", ReadBuffer1);
200
}
201
202
203
204
  return XST_SUCCESS;
205
}

Habe etwas falsch gemacht?

: Bearbeitet durch User
von Klakx (Gast)


Lesenswert?

FPGA B. schrieb im Beitrag #4797930:
> XSpi_Transfer(SpiInstancePtr, 0xF012, ReadBuffer1, 2);

Ist das wirklich richtig? Ich glaube dort sollte ein Pointer zu einem 
Speicher stehen. Also eher WriteBuffer.

und WriteBuffer sollte dann davor mit WriteBuffer[0]=0x12 und 
WriteBuffer[1]=0xF0 initialisiert werden. Es sei denn du willst wirklich 
von Adresse 0xF012 die Daten nehmen.

FPGA B. schrieb im Beitrag #4797930:
> aber in output kommt nur "Entering the S" und geht nicht weiter.

Es sollte hoffentlich auch "Waiting for data from SPI master\r\n" 
kommen.

FPGA B. schrieb im Beitrag #4797930:
> Habe etwas falsch gemacht?

Fang an zu Debuggen. Einen Tipp habe ich ja schon gegeben. Das 
einfachste ist jetzt mal zu schauen wie weit dein Programm kommt. Z.b. 
Erreichst du überhaupt die while(1) Schleife? Davor sind viele 
Prüfabfragen..sind diese erfolgreich?

von FPGA B. (beginner_eda)


Lesenswert?

Klakx schrieb:
> FPGA B. schrieb im Beitrag #4797930:
>> XSpi_Transfer(SpiInstancePtr, 0xF012, ReadBuffer1, 2);
>
> Ist das wirklich richtig? Ich glaube dort sollte ein Pointer zu einem
> Speicher stehen. Also eher WriteBuffer.
>
> und WriteBuffer sollte dann davor mit WriteBuffer[0]=0x12 und
> WriteBuffer[1]=0xF0 initialisiert werden. Es sei denn du willst wirklich
> von Adresse 0xF012 die Daten nehmen.

Meinst du so was:

#define BUFFER_SIZE    2
u8 ReadBuffer[BUFFER_SIZE];
u8 WriteBuffer[BUFFER_SIZE];
u8 *readptr:
u8 *writeptr;
readprt=&ReadBuffer;
writeptr=&WriteBuffer;
for (Count = 0; Count < BUFFER_SIZE; Count++) {
    WriteBuffer[Count] = (u8)(Count);
    ReadBuffer[Count] = 0;
  }

  /*
   * Prepare the data buffers for transmission and to send/receive data
   * when the SPI device is selected by a master.
   */
  XSpi_Transfer(SpiInstancePtr, writeptr, readptr, BUFFER_SIZE);

  /*
   * Print all the data received from the master so that it can be
   * compared with the data sent by the master.
   */
  xil_printf("\r\nReceived data is:\r\n");
  for (Count = 0; Count < BUFFER_SIZE; Count++) {
    xil_printf("0x%x \r\n", ReadBuffer[Count]);
  }

aber es gibt auch gar nicht.

>
> FPGA B. schrieb im Beitrag #4797930:
>> aber in output kommt nur "Entering the S" und geht nicht weiter.
>
> Es sollte hoffentlich auch "Waiting for data from SPI master\r\n"
> kommen.
Nie, nur "Entering the S" zeigt im console when ich Original slave code 
nehme.
>
> FPGA B. schrieb im Beitrag #4797930:
>> Habe etwas falsch gemacht?
>
> Fang an zu Debuggen. Einen Tipp habe ich ja schon gegeben. Das
> einfachste ist jetzt mal zu schauen wie weit dein Programm kommt. Z.b.
> Erreichst du überhaupt die while(1) Schleife? Davor sind viele
> Prüfabfragen..sind diese erfolgreich?
habe bis zum
XSpi_Transfer(SpiInstancePtr, writeptr, readptr, BUFFER_SIZE);
mit xil_printf("test")  function in verkehrt situation wie
 if (Status == XST_SUCCESS) {xil_printf("test")} für  if (Status != 
XST_SUCCESS)
getested und kommt print in console d.h. bis while(1) Schleife geht 
schon.

: Bearbeitet durch User
von Klakx (Gast)


Lesenswert?

Pointerzuweisung beachten.
korrigiert:
1
u8 ReadBuffer[BUFFER_SIZE];
2
u8 WriteBuffer[BUFFER_SIZE];
3
u8 *readptr:
4
u8 *writeptr;
5
readprt=ReadBuffer;
6
writeptr=WriteBuffer;

Das ist aber wahrscheinlich nicht die letzte Baustelle. Kommt überhaupt 
ein Signal vom Master?

Wenn ich ganz ratlos mit einem Interface wäre, dann würde ich das ggf. 
auch in Vivado noch simulieren.

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.