SPI

SPI Master

Funktion

Das SPI-Master-Modul bietet die Möglichkeit, mit bis zu 15 Slave-Einheiten zu kommunizieren. Die Parameter CPOL und CPHA können frei programmiert werden und es kann aus dem Takt am Eingang clk_spi per Vorteiler der Sendetakt eingestellt werden. Ist das SPI Enable-Bit gesetzt, wird durch das Schreiben des Senderegisters der Übertragungsvorgang ausgelöst. Nach dem Beenden der Übertragung kann das Modul ein Interruptsignal auslösen. Das Signal wird zurückgesetzt durch einen Zugriff auf eines der Datenregister. Das Bit Transmit-Empty im Statusregister wird auf 1 gesetzt, wenn das Datenwort im Senderegister gesendet wurde und wird zurückgesetzt durch einen Schreibzugriff auf das Senderegister. Wenn kein neues Wort in das Senderegister geschrieben wird, wartet das Modul auf Daten.

Register

OffsetRegisterFunktionZugriff
0SPI_CTRLSteuerregisterread/write
1SPI_DATOSendedatenread/write
2SPI_DATIempfangene Datenread
3SPI_STATStatusregisterread

Das Steuerregister SPI_CTRL enthält alle zur Steuerung der Funktionen des SPI Masters nötigen Bits. Bei einem Reset werden alle Bits mit Null initialisiert bis auf den Vorteiler und die Bitanzahl. Der Vorteiler wird auf den Maximalwert 2⁷ gesetzt und die Bitanzahl auf 8. Auf das Register kann lesend und schreibend zugegriffen werden.
Das Datenregister SPI_DATO enthält die Sendedaten. Bei einem Reset werden alle Bits mit Null initialisiert. Auf das Register kann lesend und schreibend zugegriffen werden.
Das Datenregister SPI_DATI enthält die empfangenen Daten. Bei einem Reset werden alle Bits mit Null initialisiert. Auf das Register kann nur lesend zugegriffen werden.
Das Statusregister enthält alle Bereitschafts- und Besetzt-Signale. Auf das Register kann nur lesend zugegriffen werden.

SPI_CTRLMaske HexFunktionReset
Bit 0: 0x00001 SPI enable: 0 = disable, 1 = enable0
Bit 1: 0x00002 Int enable: 0 = disable, 1 = enable0
Bit 2: 0x00004 cpol: cpol stellt den Idle-Pegel des Taktsignals ein0
Bit 3: 0x00008 cpha: 0 = Flanke von activ zu idle, 1 = Flanke von idle zu activ0
Bit 4 bis 7: 0x00010 - 0x000F0 Slave Adresse: 1 bis 15 ; 0 = deselect all Slaves 0
Bit 8 bis 12: Bit Anzahl 01000
0x0010000001: 1 Bit
0x0020000010: 2 Bit
0x0030000011: 3 Bit
0x0040000100: 4 Bit
0x0050000101: 5 Bit
0x0060000110: 6 Bit
0x0070000111: 7 Bit
0x0080001000: 8 Bit
0x0090001001: 9 Bit
0x00A0001010: 10 Bit
0x00B0001011: 11 Bit
0x00C0001100: 12 Bit
0x00D0001101: 13 Bit
0x00E0001110: 14 Bit
0x00F0001111: 15 Bit
0x0100010000: 16 Bit
0x0110010001: 17 Bit
0x0120010010: 18 Bit
Bit 13 bis 15: Vorteiler: 111
0x00000000: 2⁰
0x02000001: 2¹
0x04000010: 2²
0x06000011: 2³
0x08000100: 2⁴
0x0A000101: 2⁵
0x0C000110: 2⁶
0x0E000111: 2⁷
Bit 16clk_mode0=Normal 1=sclk immer aktiv (ltc1407)0


SPI_STATMaske HexFunktion
Bit 0: 0x00001 transmit empty: 1 = Sendedatenpuffer leer
Bit 1: 0x00002 Interrupt Flag
Bit 2: 0x00004 Ist 1 wenn noch SPI_SS Signale eingeschaltet sind. Die SPI_SS Signale werden erst zurückgesetzt, wenn der letzte Datentransfer beendet ist.
Bit 3: 0x00008 Ist 0 wenn die SPI_SS Signale nicht aktuell sind und wird wieder 1 wenn die letzte Slave Adresse eingestellt ist.

Die Frequenz des SCLK Signals kann aus der Frequenz des Eingangssignals clk_spi und dem Wert des Vorteilers berechnet Werden.

SCLK = CLK_SPI / (4 * Vorteiler) = 50 MHz / (4 * 2⁰) = 12,50000000 MHz
SCLK = CLK_SPI / (4 * Vorteiler) = 50 MHz / (4 * 2²) = 3,12500000 MHz
SCLK = CLK_SPI / (4 * Vorteiler) = 50 MHz / (4 * 2⁷) = 0,09765625 MHz

Konfiguration und Instanziierung

Da bei einem System Takt größer gleich 60 MHz mit dem maximalen SPI-Vorteiler von 4*(2⁷) keine Frequenz kleiner gleich 100 kHz eingestellt werden können, hat der Master einen extra Eingang clk_spi für einen Takt aus dem das Signal SCLK gebildet wird. An diesem Eingang kann der Ausgang eines TIMER-Moduls oder USERCLK-Moduls angeschlossen werden. Damit sind dann auch Frequenzen kleiner 100 kHz einstellbar. Die Interruptleitung des Moduls muss an den gewünschten Eingang des Interruptkontrollers angeschlossen werden, die Output-Pins für MOSI, Slave-Select und SCLK an den Ausgang des Top Level Moduls sowie der Pin für MISO an den Eingang. Die Ports des Top Level Moduls müssen dann noch den Pins des FPGA im jConfig zugeordnet werden.

Beispielprogramme zur Arbeit mit SPI Slave Modulen:

Lesen des ID, schreiben mit *.mcs Datei und ... vom EEPROM m25p32 in C auf dem ml507 Board:
In diesem Beispiel wird der SpartanMC SPI-Master mit 25 MHz SPI-SCLK betrieben. Meim Senden von *.mcs Dateien muss im Minicom das Tool zum senden im ASCII Format auf einen Verzögerung von 2 ms am Zeilenende und 0 ms pro Zeichen eingestellt werden. Bei der alten Einstellung mit 2 ms am Zeilenende und 1 ms pro Zeichen dauert die Übertragung etwa 3 Stunden. Mit 0 ms pro Zeichen sind es nur etwa 15 Minuten.
Beschreibung zum m25p32 m25p32.pdf
C-Quelle des Test main.c
C-Quelle des Include m25p32.c
H-Quelle des Include m25p32.h
Assemblerliste des Test main.lst
Protokoll zum Test m25p32_prot.txt
Protokoll zum Test prot_m25p32_ml507.txt
BIT Datei für das ml507 Board mit dem Programm spartanmc.bit
MSK Datei für das ml507 Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_sample.jc3
Bildschirmfoto 01 vom Minicom beim Vergleich mit Fehler
Bildschirmfoto 02 vom Minicom beim Vergleich mit Fehler
Bildschirmfoto 03 vom Minicom beim Vergleich mit Fehler und Anzeige des betroffenen Speicher
Bildschirmfoto 04 vom Minicom am Ende eines Programmierzyklus mit einer *.mcs Datei.
Bildschirmfoto 05 vom Minicom am Ende eines Programmierzyklus mit einer *.mcs Datei mit dem Fehlerstatus.
Bildschirmfoto 06 vom Minicom am Ende eines Vergleichs mit einer *.mcs Datei, die vorher programmiert wurde.
Bildschirmfoto 07 vom Minicom am Ende eines Vergleichs und Start der Anzeige aller belegten Seiten.
Bildschirmfoto 08 vom Minicom Ende der Anzeige aller belegten Seiten.

Einstellen von 4 Spannungen am DAC ltc2624 in C auf dem 3e Starter Kit Board:
Beschreibung zum ltc2624 ltc2624.pdf
C-Quelle des Test spi_ltc2624.c
Assemblerliste des Test spi_ltc2624.lst
Protokoll zum Test spi_ltc2624.txt
VSIM Bitverlauf der Datenübertragung VSIM1.png
VSIM mit der Periodendauer des SCK VSIM2.png
BIT Datei für das 3estk Board mit dem Programm spartanmc.bit
MSK Datei für das 3estk Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_m_ltc2624.jc3

Funktionstest für den SpartanMC SPI-Slave in C auf dem 3e Starter Kit Board:
Beschreibung zum SpartanMC SPI spi.pdf
C-Quelle des Test spi_slave.c
Assemblerliste des Test spi_slave.lst
Protokoll zum Test prot_all_tests_1041khz.pdf
Protokoll zum Test prot_all_tests_3125khz.txt
BIT Datei für das 3estk Board mit dem Programm spartanmc.bit
MSK Datei für das 3estk Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_ms.jc3

Funktionstest für den SpartanMC SPI-Slave in C auf dem sp601 Board:
Beschreibung zum SpartanMC SPI spi.pdf
C-Quelle des Test spi_slave.c
Assemblerliste des Test main.lst
Protokoll zum Test prot_all_tests_1667khz.pdf
Protokoll zum Test prot_spi_1666_6667mhz.txt
Protokoll zum Test prot_spi_5000mhz.txt
Protokoll zum Test prot_spi_5250mhz.txt (Bei der Synthese wurde ein Timing Error angezeigt!)
BIT Datei für das 3estk Board mit dem Programm spartanmc.bit
MSK Datei für das 3estk Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig spi_master_slave.jc3

Funktionstest für das Display OLED25664 in C auf dem SP601 Board:
Beschreibung zum SpartanMC SPI spi.pdf
Beschreibung zum Display NHD-3.12-25664UMB3.pdf
Beschreibung zum Display Kontroller SSD1322.pdf
C-Quelle des Test main.c
C-Include oled_25664.c
H-Include oled_25664.h
H-Include ascii57.h
C-Include spi_local.c
H-Include spi_local.h
Foto vom Test IMG_1242.JPG
Foto vom Test IMG_1241.JPG
BIT Datei für das SP601 Board mit dem Programm spartanmc.bit
MSK Datei für das SP601 Board mit dem Programm spartanmc.msk
SpartanMC Konfigurationsdatei für jConfig sp601_spi_oled25664.jc3

C-Quellen der SPI-Include Funktionen:

Programm Beschreibung
* spi_readwrite.c - spi_master_readwrite - Senden von Daten an den Slave und warten bis der Master wieder bereit ist und dann die Rx Daten zurückgeben
spi_slave_readwrite    - Senden von Daten an den Master und warten bis der Slave wieder bereit ist und dann die Rx Daten zurückgeben
* spi_write.c - spi_master_write - warten bis der Master wieder bereit ist und dann Daten senden
spi_slave_write    - warten bis dammy Byte empfangen wurde, Byte senden und warten bis der Slave wieder bereit ist
* spi_read.c - spi_master_read - dummy Byte 0x55 senden und warten bis der Master wieder bereit ist und dann Daten lesen
spi_slave_read    - warten bis ein Byte empfangen wurde und dann empfangenes Byte zur Kontrolle zurueck senden
* spi_enable.c - spi_master_enable - SpartanMC SPI-Master-Device einschalten
spi_slave_enable    - SpartanMC SPI-Slave-Device einschalten
* spi_disable.c - spi_master_disable - SpartanMC SPI-Master-Device ausschalten
spi_slave_disable    - SpartanMC SPI-Slave-Device ausschalten
* spi_enable_irq.c - spi_master_enable_irq - Interrupt eines SpartanMC Master SPI-Device freigeben
spi_slave_enable_irq    - Interrupt eines SpartanMC Slave SPI-Device freigeben
* spi_disable_irq.c - spi_master_disable_irq - Interrupt eines SpartanMC Master SPI-Device sperren
spi_slave_disable_irq    - Interrupt eines SpartanMC Slave SPI-Device sperren
* spi_set_cpol.c - spi_master_set_cpol - Polarität des SPI Takt vom Master setzen (0 = Ruhezustand des Takt / 1 = Ruhezustand des Takt)
spi_slave_set_cpol    - Polarität des SPI Takt vom Slave setzen (0 = Ruhezustand des Takt / 1 = Ruhezustand des Takt)
* spi_set_cpah.c - spi_master_set_cpah - Phasenlage des SPI Takt vom Master setzen (0 = Datenübernahme mit der 1. Flanke / 1 = Datenübernahme mit der 2. Flanke)
spi_slave_set_cpah    - Phasenlage des SPI Takt vom Slave setzen (0 = Datenübernahme mit der 1. Flanke / 1 = Datenübernahme mit der 2. Flanke)
* spi_set_bitcnt.c - spi_master_set_bitcnt - Anzahl der Bits des Datenworts vom Master einstellen (1 bis 18). Rückgabe -1, wenn < 1 oder > 18.
spi_slave_set_bitcnt    - Anzahl der Bits des Datenworts vom Slave einstellen (1 bis 18). Rückgabe -1, wenn < 1 oder > 18.
* spi_master_set_div.c - Vorteiler für den SPI Takt setzen (20 bis 27)
* spi_master_activate.c - Aktivieren eines Slave und warten bis das SS-Signal eingeschaltet ist (es können nacheinander mehrere Slave aktiviert werden). Es wird eine 0 zurückgegeben, wenn die Funktion erfolgreich war. Ist der Master nicht freigegeben, oder die Nummer des Slave ist kleiner 1 oder größer 15 wird eine 1 zurückgegeben
* spi_master_deactivate.c - alle Slave Module deaktivieren und warten bis die SS-Signale ausgeschaltet sind.


1. #include <spi.h>

... muss in der C-Quelle geladen werden, wenn man die Funktionen verwenden will.
#ifndef __SPI_H
#define __SPI_H

#ifdef __cplusplus
extern "C" {
#endif

#include <peripherals/spi_master.h>
#include <peripherals/spi_slave.h>
#include <bitmagic.h>

//master only functions
int  spi_master_activate(spi_master_regs_t *spi,unsigned int device);		// return = 1 if spi not enable or device<1 or device>15
void spi_master_deactivate(spi_master_regs_t *spi);
void spi_master_set_div(spi_master_regs_t *spi, unsigned int div);

//master duplicate functions
unsigned int spi_master_readwrite(spi_master_regs_t *spi, unsigned int data);
unsigned int spi_master_read(spi_master_regs_t *spi);
void spi_master_write(spi_master_regs_t *spi, unsigned int data);
void spi_master_enable(spi_master_regs_t *spi);     
void spi_master_disable(spi_master_regs_t *spi);     
void spi_master_enable_irq(spi_master_regs_t *spi);     
void spi_master_disable_irq(spi_master_regs_t *spi);     
void spi_master_set_cpol(spi_master_regs_t *spi, unsigned int cpol);     
void spi_master_set_cpah(spi_master_regs_t *spi, unsigned int cpah);     
int  spi_master_set_bitcnt(spi_master_regs_t *spi, unsigned int bitcnt);	// return = bitcnt or -1 if error (bitcnt > 18 or bitcnt < 1)

//slave duplicate functions
unsigned int spi_slave_readwrite(spi_slave_regs_t *spi, unsigned int data);
unsigned int spi_slave_read(spi_slave_regs_t *spi);
void spi_slave_write(spi_slave_regs_t *spi, unsigned int data);
void spi_slave_enable(spi_slave_regs_t *spi);     
void spi_slave_disable(spi_slave_regs_t *spi);     
void spi_slave_enable_irq(spi_slave_regs_t *spi);     
void spi_slave_disable_irq(spi_slave_regs_t *spi);     
void spi_slave_set_cpol(spi_slave_regs_t *spi, unsigned int cpol);     
void spi_slave_set_cpah(spi_slave_regs_t *spi, unsigned int cpah);     
int  spi_slave_set_bitcnt(spi_slave_regs_t *spi, unsigned int bitcnt);		// return = bitcnt or -1 if error (bitcnt > 18 or bitcnt < 1)

#ifdef __cplusplus
}
#endif

#endif

2. #include <periperals/spi_master.h>

... wird immer automatisch vom SpartanMC System geladen. Der Include muss nicht in der C-Quelle erfolgen.
#ifndef __SPI_MASTER_H
#define __SPI_MASTER_H

#ifdef __cplusplus
extern "C" {
#endif

#include <peripherals/spi_common.h>

// CONTROL
#define SPI_MASTER_CTRL_EN          SPI_CTRL_EN
#define SPI_MASTER_CTRL_INT_EN      SPI_CTRL_INT_EN
#define SPI_MASTER_CTRL_CPOL        SPI_CTRL_CPOL
#define SPI_MASTER_CTRL_CPHA        SPI_CTRL_CPHA
#define SPI_MASTER_CTRL_SLAVE       0x000F0  // 00 0000 0000 1111 0000
#define SPI_MASTER_CTRL_BITCNT      SPI_CTRL_BITCNT
#define SPI_MASTER_CTRL_DIV         0x0E000  // 00 1110 0000 0000 0000
#define SPI_MASTER_CTRL_CLK_MOD     0x10000  // 01 0000 0000 0000 0000

//STATUS COMPATIBILITY SECTION FOR OLD PROJECTS
#define SPI_MASTER_STAT_TRANS_EMPTY SPI_STAT_TRANS_EMPTY
#define SPI_MASTER_STAT_INT         SPI_STAT_INT
#define SPI_MASTER_STAT_SS_ON       SPI_STAT_SS_ON
#define SPI_MASTER_STAT_SS_SET      SPI_STAT_SS_SET

typedef struct {
   	spi_t spi;
} spi_master_regs_t;

#ifdef __cplusplus
}
#endif

#endif

2. #include <periperals/spi_common.h>

... wird immer automatisch vom SpartanMC System geladen. Der Include muss nicht in der C-Quelle erfolgen.
#ifndef __SPI_COMMON_H
#define __SPI_COMMON_H

#ifdef __cplusplus
extern "C" {
#endif

// CONTROL
#define SPI_CTRL_EN          0x00001  // 00 0000 0000 0000 0001
#define SPI_CTRL_INT_EN      0x00002  // 00 0000 0000 0000 0010
#define SPI_CTRL_CPOL        0x00004  // 00 0000 0000 0000 0100
#define SPI_CTRL_CPHA        0x00008  // 00 0000 0000 0000 1000
#define SPI_CTRL_BITCNT      0x01F00  // 00 0001 1111 0000 0000

//STATUS
#define SPI_STAT_TRANS_EMPTY 0x00001  // 00 0000 0000 0000 0001
#define SPI_STAT_INT         0x00002  // 00 0000 0000 0000 0010
#define SPI_STAT_SS_ON       0x00004  // 01 0000 0000 0000 0100
#define SPI_STAT_SS_SET      0x00008  // 10 0000 0000 0000 1000

typedef volatile struct {
    volatile unsigned int spi_control;
    volatile unsigned int spi_data_out;
    volatile unsigned int spi_data_in;
    volatile unsigned int spi_status;
} spi_t;

#ifdef __cplusplus
}
#endif

#endif



SpartanMC