UART
Die aktuellen Versionen aller Verilog Dateien finden Sie im SubVersion hier
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 <periperals/uart.h>
... wird immer automatisch vom SpartanMC System geladen. Der Include muss nicht in der C-Quelle erfolgen.#ifndef __UART_H #define __UART_H #include <stdint.h> // 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 #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) // Rückgabewerte für 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; #endif
2. #include <uart.h>
... muss in der C-Quelle geladen werden, wenn man die Funktionen verwenden will.#ifndef UART_H_ #define UART_H_ 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); 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); void stdio_uart_open(uart_regs_t *uart); void stdio_uart_light_open(uart_light_regs_t *uart); #endif
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.
5. stdio_uart_open(UART_0);
Die UART_0 wird als stdio Gerät festgelegt. Die Funktion kann auch zur Laufzeit die stdio Funktionen auf eine andere UART umgeleiten.
Die Funktionen für die UART_light werden nur benötigt, wenn es einmal Unterschiede beim Polling von UART und UART_light geben sollte.
Testprogramme für die Interruptarbeit mit UART 2
Programm für die 2. UART als C-Quelle uart2.c



Konfiguration im binären Format für den Spartan 3E Starter Kit auf der das Programm lauffähig ist.
Die Konfiguration hat 3 Speicherblöcke und kann hier aus der TAR.GZ-Datei
- Konfigurationsdatei für jConfig
- Mit jConfig daraus erstellte module_test1_step_foerderband.v, module_subsystem_0.v, hardware.h und peripherals.h Datei
- Die verwendete Firmware mit StartUP Loader für 9 Speicherblöcke übersetzt als Quelle wd_rot_ta2_lcd.c, als Übersetzungsliste wd_rot_ta2_lcd.lst und im MEM-Format spartanmc_0.sph können hier geladen werden.
- SPARTANMC.BIT Datei für das 3e Board und SPARTANMC.MSK Datei für Verify im iMpact (nur Jumper M1 geschlossen).
- M25P16.MCS Datei und M25P16.CFI Datei für den SPI-PROM des 3e Board (nur Jumper M0 offen).
- xcf04s.MCS Datei und xcf04s.CFI Datei für den Platform Flash-PROM des 3e Board (alle Jumper M0, M1 und M2 geschlossen). Diese 6 Dateien in ein Verzeichnis speichern und von dort mit dem iMpact in einen der PROMs oder die FPGA speichern.
Offene Fragen
- zur Zeit keine
WEB-Seiten mit Informationen zur Funktion der UART
http://www.sprut.de/electronic/interfaces/rs232/rs232.htm
http://de.wikipedia.org/wiki/RS232

http://www.lammertbies.nl/comm/cable/de_RS-232.html#pins
