UART





Das UART-Übertragungsverfahren sieht vor, das zunächst ein dem Ruhepegel der Leitung (in diesem Fall 1) entgegengesetztes Startbit Übertragen wird, also eine Null. Danach werden fünf bis acht Datenbits und optional ein Paritätsbit gesendet. Die Parität bezieht sich auf das Hamminggewicht der Datenbits inklusive Paritätsbit und kann dementsprechend "gerade" oder "ungerade" sein. Das Paritätsbit muss die Datenbits zu der für die Übertragung gewählten Parität ergänzen, ansonsten werden die Daten als fehlerhaft angezeigt. Am Schluss werden ein oder zwei Stoppbits übertragen, die dem Pegel des Ruhezustandes entsprechen, also logische Einsen. Bei der Übertragung wird das niederwertigste Bit zuerst gesendet. Im Ruhezustand kann eine Übertragung beliebig lange angehalten werden. Die Uart besitzt auch je einen FIFO für den Datenempfang und für das Senden. Die Größe kann getrennt in den Werten von zweier Potenzen eingestellt werden. Die maximale Größe wird durch die Ressourcen des FPGA begrenzt. Die Größe der FIFOs kann nur während der Erstellung eines Projekts im Systembilder festgelegt werden. Die Werte für die Vorteiler der einzelnen Datenraten werden dabei auch automatisch für die bei der Konfiguration anzugebende Takt Frequenz ermittelt.

Für den Bootlader und die STDIO wird die UART auf folgende Werte eingestellt:

Datenrate: (Baud) 115200 Kbit/sec
Bitanzahl: 8 Bit
Parität: keine
Stoppbits: >=1
Hardwareprotokoll (Flow Control): keins
Softwareprotokoll (Flow Control): keins

Die Daten werden damit bei 2 Stoppbits in folgender Form übertragen:


Durch das ISE bei der Übersetzung von transiver.v ermittelte Teiler
Ergebnisse einer Teilerberechnung mit Excel für die Datei transiver.v

Register

Offset Register Zugriff
0 UART_Status read
1 UART_FIFO_READ (RESET Rx Interrupt) read
2 UART_FIFO_WRITE write
3 UART_CTRL write
3 UART_Status (RESET Tx Interrupt) read
4 UART_MODEM (optional) write


Bitbelegung UART_Status

Bit Maske Hex Bedeutung
0 0x00001 rx FIFO leer
1 0x00002 rx FIFO voll
2 0x00004 tx FIFO leer
3 0x00008 tx FIFO voll
4 0x00010 tx FIFO wurde geschrieben
5 0x00020 tx Interrupt
6 0x00040 rx Paritätsfehler
7 0x00080 rx Framefehler (offene Leitung oder BREAK wird empfangen)
8 0x00100 rx Datenverlust
9 0x00200 Modemsignal dcd (wenn freigegeben)
10 0x00400 Modemsignal cts (wenn freigegeben)
11 0x00800 Modemsignal dsr (wenn freigegeben)
12 0x01000 rx_clk Schieberegister Takt Rx
13 0x02000 rx Schieberegister arbeitet nicht
14 0x04000 tx_clk Schieberegister Takt Tx (arbeitet ständig mit Datenrate!!)
15 0x08000 rst_uart (UART befindet sich noch im RESET)
16 0x10000 tx Schieberegister arbeitet nicht

Soll die Datenrate zwischen mehreren Übertragungen verändert werden, dann muss vorher der Ruhezustand der UART abgefragt werden und erst dann kann man die neue Datenrate einstellen. Der Ruhezustand ist vorhanden, wenn die UART sich nicht mehr im RESET (rst_uart = 0) befindet, der Rx Fifo leer ist und das Rx Schieberegister nicht arbeitet und auch der Tx Fifo leer ist und das Tx Schieberegister nicht arbeitet. Das Statusregister muss also mit der Maske 0x1A005 gelesen und das Ergebnis mit 0x12005 verglichen werden. Liegt genau dieser Wert vor, dann kann die neue Datenrate eingestellt werden.

Bitbelegung UART_CTRL

Bit Bedeutung Reset
0 Rx Freigabe 0
1 Tx Freigabe 0
2 Paritätsprüfung freigeben 0
3 0=ungerade / 1=gerade Parität 0
4 0=ein / 1=zwei Stopbits 0
7 bis 5 Wort Länge 111
8 Bit = 111 (0x00E0)
7 Bit = 110 (0x00C0)
6 Bit = 101 (0x00A0)
5 Bit = 100 (0x0080)
8 nicht verwendet
12 bis 9 Datenrate 0000
115200 = 0000 (0x0000)
057600 = 0001 (0x0200)
038400 = 0010 (0x0400)
031250 = 0011 (0x0600) (MIDI Datenrate)
019200 = 0100 (0x0800)
009600 = 0101 (0x0A00)
004800 = 0110 (0x0C00)
002400 = 0111 (0x0E00)
001200 = 1000 (0x1000)
000600 = 1001 (0x1200)
000300 = 1010 (0x1400)
000150 = 1011 (0x1600)
000075 = 1100 (0x1800)
000050 = 1101 (0x1A00)
007812,5 für alle anderen Werte (Boot 68hc11)
13 Freigabe des Rx Interrupt 0
14 Freigabe des Tx Interrupt 0
15 Sende BREAK (Tx ständig low = Startbit) 0

Bitbelegung UART_MODEM

Bit Bedeutung Reset
0 Zustand DSR bzw. DTR, wenn Ausgang 0
1 Zustand RTS bwz. CTS, wenn Ausgang 0
2 Zustand DCD, wenn Ausgang 0
3 Richtung Port dcd, 1=Ausgang, 0=Eingang 0
4 Richtung Port rts, 1=Ausgang, 0=Eingang 0
5 Richtung Port dtr, 1=Ausgang, 0=Eingang 0
17-6 not used


1. #include <uart.h>

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

#ifdef __cplusplus
extern "C" {
#endif

#include <peripherals/uart.h>
#include <peripherals/uart_light.h>
#include <stdint.h>

// section kept for compatibility with older projects, may be removed in the
// future

// Status Signale
#define	RX_EMPTY	UART_RX_EMPTY   
#define	RX_FULL		UART_RX_FULL    
#define	TX_EMPTY	UART_TX_EMPTY   
#define	TX_FULL		UART_TX_FULL    
#define	TX_IRQ_PRE	UART_TX_IRQ_PRE 
#define	TX_IRQ_FLAG	UART_TX_IRQ_FLAG
#define	RX_P_ERR	UART_RX_P_ERR   
#define	RX_F_ERR	UART_RX_F_ERR   
#define	RX_D_ERR	UART_RX_D_ERR   
#define	M_DCD		UART_M_DCD      
#define	M_CTS		UART_M_CTS      
#define	M_DSR		UART_M_DSR      
#define	RX_CLK		UART_RX_CLK     
#define	RX_STOP		UART_RX_STOP    
#define	TX_CLK		UART_TX_CLK     
#define	RST_UART	UART_RST_UART	// UART noch im RESET, wenn = 1
#define	TX_STOP		UART_TX_STOP    
                                    
                                    
// Steuersignale    
#define	RX_EN		UART_RX_EN      
#define	TX_EN		UART_TX_EN      
#define	PARI_EN		UART_PARI_EN    
#define	PARI_EVEN	UART_PARI_EVEN	// 0 = ungerade / 1 = gerade
#define	TWO_STOP	UART_TWO_STOP	// 0 = ein / 1 = zwei Stopbits
                                    
#define	DATA_LEN_5	UART_DATA_LEN_5 
#define	DATA_LEN_6	UART_DATA_LEN_6 
#define	DATA_LEN_7	UART_DATA_LEN_7 
#define	DATA_LEN_8	UART_DATA_LEN_8 
                                    
#define	BPS_115200	UART_BPS_115200 
#define	BPS_57600	UART_BPS_57600  
#define	BPS_38400	UART_BPS_38400  
#define	BPS_31250	UART_BPS_31250	// MIDI Datenrate
#define	BPS_19200	UART_BPS_19200  
#define	BPS_9600	UART_BPS_9600   
#define	BPS_4800	UART_BPS_4800   
#define	BPS_2400	UART_BPS_2400   
#define	BPS_1200	UART_BPS_1200   
#define	BPS_600		UART_BPS_600    
#define	BPS_300		UART_BPS_300    
#define	BPS_150		UART_BPS_150    
#define	BPS_75		UART_BPS_75     
#define	BPS_50		UART_BPS_50     
#define	BPS_7812	UART_BPS_7812	// Boot 68hc11 mit 7812,5 Baud
                                    
#define	RX_IE		UART_RX_IE      
#define	TX_IE		UART_TX_IE      
#define	TX_BREAK	UART_TX_BREAK   

// Interruptfreigabe fuer UART light
#define	RXUL_IE		(1<<9)
#define TXUL_IE		(1<<10)

// Modem Outputs und Richtung
#define	DTR_DSR		UART_DTR_DSR
#define	RTS_CTS		UART_RTS_CTS
#define	DCD		UART_DCD    
#define	DCD_OUT		UART_DCD_OUT
#define	RTS_OUT		UART_RTS_OUT
#define	DTR_OUT		UART_DTR_OUT

typedef uart_regs_t uart_t;

void uart_write (uart_t *uart, const uint18_t value);
unsigned char uart_read (uart_t *uart);
int uart_read_nb (uart_t *uart, unsigned char *value);
void __attribute__((error("stdio_uart_open is no longer supported. Declare a global variable
	 FILE * stdout = &UART_*_FILE instead"))) stdio_uart_open2(uart_t *uart);

// end compatibility section

void uart_wait_idle(uart_regs_t *uart);
void uart_send(uart_regs_t *uart, const unsigned char value);
unsigned char uart_receive(uart_regs_t *uart);
int uart_receive_nb (uart_regs_t *uart, unsigned char *value);

#define declare_UART_FILE(uart) { \
	.base_addr = (void*) uart, \
	.send_byte = (fun_stdio_send_byte) uart_send, \
	.receive_byte = (fun_stdio_receive_byte) uart_receive, \
	.receive_byte_nb = (fun_stdio_receive_byte_nb) uart_receive_nb \
}

void __attribute__((error("stdio_uart_open is no longer supported. Declare a global variable
	 FILE * stdout = &UART_*_FILE instead"))) stdio_uart_open(uart_regs_t *uart);

#ifdef __cplusplus
}
#endif

#endif /*UART_H_*/

2. #include <peripherals/uart.h>

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

#ifdef __cplusplus
extern "C" {
#endif

#include 

// Status Signale
#define UART_RX_EMPTY    (1<<0)
#define UART_RX_FULL     (1<<1)
#define UART_TX_EMPTY    (1<<2)
#define UART_TX_FULL     (1<<3)
#define UART_TX_IRQ_PRE  (1<<4)
#define UART_TX_IRQ_FLAG (1<<5)
#define UART_RX_P_ERR    (1<<6)
#define UART_RX_F_ERR    (1<<7)
#define UART_RX_D_ERR    (1<<8)
#define UART_M_DCD       (1<<9)
#define UART_M_CTS       (1<<10)
#define UART_M_DSR       (1<<11)
#define UART_RX_CLK      (1<<12)
#define UART_RX_STOP     (1<<13)
#define UART_TX_CLK      (1<<14)
#define UART_RST_UART    (1<<15)     // UART noch im RESET, wenn = 1
#define UART_TX_STOP     (1<<16)


// Steuersignale
#define UART_RX_EN       (1<<0)
#define UART_TX_EN       (1<<1)
#define UART_PARI_EN     (1<<2)
#define UART_PARI_EVEN   (1<<3)      // 0 = ungerade / 1 = gerade
#define UART_TWO_STOP    (1<<4)      // 0 = ein / 1 = zwei Stopbits

#define UART_DATA_LEN_5  (4<<5)      // 0x00080
#define UART_DATA_LEN_6  (5<<5)      // 0x000A0
#define UART_DATA_LEN_7  (6<<5)      // 0x000C0
#define UART_DATA_LEN_8  (7<<5)      // 0x000E0

#define UART_BPS_115200  (0<<9)      // 0x00000
#define UART_BPS_57600   (1<<9)      // 0x00200
#define UART_BPS_38400   (2<<9)      // 0x00400
#define UART_BPS_31250   (3<<9)      // 0x00600 MIDI Datenrate
#define UART_BPS_19200   (4<<9)      // 0x00800
#define UART_BPS_9600    (5<<9)      // 0x00A00
#define UART_BPS_4800    (6<<9)      // 0x00C00
#define UART_BPS_2400    (7<<9)      // 0x00E00
#define UART_BPS_1200    (8<<9)      // 0x01000
#define UART_BPS_600     (9<<9)      // 0x01200
#define UART_BPS_300     (10<<9)     // 0x01400
#define UART_BPS_150     (11<<9)     // 0x01600
#define UART_BPS_75      (12<<9)     // 0x01800
#define UART_BPS_50      (13<<9)     // 0x01A00
#define UART_BPS_7812    (14<<9)     // 0x01C00 Boot 68hc11 mit 7812,5 Baud

#define UART_RX_IE       (1<<13)
#define UART_TX_IE       (1<<14)
#define UART_TX_BREAK    (1<<15)

// Modem Outputs und Richtung (optional)
#define UART_DTR_DSR     (1<<0)
#define UART_RTS_CTS     (1<<1)
#define UART_DCD         (1<<2)
#define UART_DCD_OUT     (1<<3)
#define UART_RTS_OUT     (1<<4)
#define UART_DTR_OUT     (1<<5)

// Rueckgabewerte fuer non blocking read
#define UART_OK          0
#define UART_NO_DATA     1

typedef struct {
    volatile uint18_t   status;     // read
    volatile uint18_t   rx_data;    // read (Reset Rx Interrupt)
    volatile uint18_t   tx_data;    // write
    volatile uint18_t   ctrl_stat;  // write (or read = status & Reset Tx Interrupt)
    volatile uint18_t   modem;      // write (optional)
} uart_regs_t;

#ifdef __cplusplus
}
#endif

#endif

2. #include <peripherals/uart_ligth.h>

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

#ifdef __cplusplus
extern "C" {
#endif

#include 

// Status Signale
#define UART_LIGHT_RX_EMPTY     (1<<0)
#define UART_LIGHT_RX_FULL      (1<<1)
#define UART_LIGHT_TX_EMPTY     (1<<2)
#define UART_LIGHT_TX_FULL      (1<<3)
#define UART_LIGHT_TX_IRQ_PRE   (1<<4)
#define	UART_LIGHT_TX_IRQ_FLAG	(1<<5)

// Interruptfreigabe fuer UART light
#define UART_LIGHT_RXIE         (1<<9)
#define UART_LIGHT_TXIE         (1<<10)


typedef struct {
    volatile uint18_t   status;		// read/write = Reset Tx Interrupt
    volatile uint18_t   rx_data;	// read = Reset Rx Interrupt
    volatile uint18_t   tx_data;	// write
} uart_light_regs_t;

void uart_light_send (uart_light_regs_t *uart, unsigned char value);
unsigned char uart_light_receive (uart_light_regs_t *uart);
int uart_light_receive_nb (uart_light_regs_t *uart, unsigned char *value);

#define declare_UART_LIGHT_FILE(uart) { \
	.base_addr = (void*) uart, \
	.send_byte = (fun_stdio_send_byte) uart_light_send, \
	.receive_byte = (fun_stdio_receive_byte) uart_light_receive, \
	.receive_byte_nb = (fun_stdio_receive_byte_nb) uart_light_receive_nb \
}

void __attribute__((error("stdio_uart_light_open is no longer supported. Declare a global variable
	 FILE * stdout = &UART_LIGHT_*_FILE instead"))) stdio_uart_light_open(uart_light_regs_t * uart);

#ifdef __cplusplus
}
#endif

#endif /*UART_LIGHT_H_*/


Wird im Programm #include <uart.h> verwendet, dann können die oben stehenden Funktionen genutzt werden.

1. uart_wait_idle(&UART_0);
Die Funktion wartet auf den Ruhezustand von Rx, Tx und RESET der UART_0. Es werden die Bits 0,2,13,15 und 16 vom UART_Status überwacht. Die Funktion sollte vor der Initialisierung der UART gerufen werden, damit vorher alle Datentransfer Operationen mit der alten Einstellung beendet werden können. Diese Funktion darf nicht mit einer UART_light aufgerufen werden!

2. uart_send(&UART_0, 'A');
Die Funktion sendet das Zeichen 'A' an die UART_0. Wurde stdio auf die UART_0 gesetzt, dann verwendet putchar(zeichen) diese Funktion.

3. zeichen = uart_receive(&UART_0);
Die Funktion wartet auf ein Zeichen von UART_0. Wurde stdio auf die UART_0 gesetzt, dann verwendet zeichen = getchar() diese Funktion.

4. status = uart_receive_nb(&UART_0, &zeichen);
Die Funktion wartet nicht auf ein Zeichen. War ein Zeichen vorhanden, dann ist der Status 0 und das Zeichen wird auf die Variable zeichen geschrieben. Wurde stdio auf die UART_0 gesetzt, dann verwendet status = getchar_nb(&zeichen) diese Funktion.

stdio festlegen
#ifndef	SB_UART_LIGHT_0_INTERRUPT_SUPPORTED
FILE * stdout	= &UART_0_FILE;
FILE * stdin	= &UART_0_FILE;
#else
FILE * stdout	= &UART_LIGHT_0_FILE;
FILE * stdin	= &UART_LIGHT_0_FILE;
#endif

Testprogramme für die Interruptarbeit mit UART 2


Programm für die 2. UART als C-Quelle uart2.c , als Übersetzungsliste uart2.lst und im bin-Format spartanmc.bit und spartanmc.msk können hier geladen werden.
Programmieren mit iMpact wenn nur Jumper M1 geschlossen ist.
Die Konfiguration für den Spartan 3E Starter Kit auf der das Programm lauffähig ist kann mit der folgenden Konfigurationsdatei für jConfig erstellt werden.

Offene Fragen

  • zur Zeit keine

WEB-Seiten mit Informationen zur Funktion der UART

http://www.sprut.de/electronic/interfaces/rs232/rs232.htm(external link)
http://de.wikipedia.org/wiki/RS232(external link)
http://www.lammertbies.nl/comm/cable/de_RS-232.html#pins(external link)


SpartanMC