summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Foster <nick@nerdnetworks.org>2010-08-12 10:23:33 -0700
committerNick Foster <nick@nerdnetworks.org>2010-08-12 10:23:33 -0700
commit32c40b5f5956d29e3be1fc3c94a213f8f0d68f42 (patch)
tree3e059559d9b1d80e807a114240052b2947684e87
parentdfafbd5f2dbf0758df33d10922eec3c1a37dd32b (diff)
downloaduhd-32c40b5f5956d29e3be1fc3c94a213f8f0d68f42.tar.gz
uhd-32c40b5f5956d29e3be1fc3c94a213f8f0d68f42.tar.bz2
uhd-32c40b5f5956d29e3be1fc3c94a213f8f0d68f42.zip
Working support for multiple UARTs.
Default behavior (printf, gets, etc.) routes to DEFAULT_UART, set in hal_uart.h. Use fputstr() to print to other UARTs. Bring fgets() from hal_io.c out in hal_io.h if you want to read data from other UARTs. Still blocking. No interrupt-driven stuff yet.
-rw-r--r--firmware/microblaze/lib/hal_io.c66
-rw-r--r--firmware/microblaze/lib/hal_io.h2
-rw-r--r--firmware/microblaze/lib/hal_uart.c89
-rw-r--r--firmware/microblaze/lib/hal_uart.h42
-rw-r--r--firmware/microblaze/usrp2p/memory_map.h6
5 files changed, 122 insertions, 83 deletions
diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c
index b68067308..8bb5e2af8 100644
--- a/firmware/microblaze/lib/hal_io.c
+++ b/firmware/microblaze/lib/hal_io.c
@@ -18,9 +18,9 @@
// conditionalized on HAL_IO_USES_DBOARD_PINS && HAL_IO_USES_UART
-#include "hal_io.h"
#include "memory_map.h"
#include "hal_uart.h"
+#include "hal_io.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@@ -102,7 +102,7 @@ hal_finish(void)
// %c
inline int
-fputchar(int ch)
+putchar(int ch)
{
hal_gpio_set_rx((s << 8) | W, 0xff80);
hal_gpio_set_rx(0, 0xff80);
@@ -124,16 +124,29 @@ hal_finish(void)
// %c
inline int
-fputchar(int ch)
+fputchar(hal_uart_name_t u, int ch)
+{
+ hal_uart_putc(u, ch);
+ return ch;
+}
+
+inline int
+putchar(int ch)
{
- hal_uart_putc(ch);
+ hal_uart_putc(DEFAULT_UART, ch);
return ch;
}
int
-fgetchar(void)
+fgetchar(hal_uart_name_t u)
+{
+ return hal_uart_getc(u);
+}
+
+int
+getchar(void)
{
- return hal_uart_getc();
+ return fgetchar(DEFAULT_UART);
}
#else // nop all i/o
@@ -172,34 +185,57 @@ getchar(void)
// \n
inline void
-fnewline(void)
+fnewline(hal_uart_name_t u)
{
- putchar('\n');
+ fputchar(u, '\n');
+}
+
+inline void
+newline(void)
+{
+ fnewline(DEFAULT_UART);
}
int
-fputstr(const char *s)
+fputstr(hal_uart_name_t u, const char *s)
{
while (*s)
- putchar(*s++);
+ fputchar(u, *s++);
return 0;
}
int
-fputs(const char *s)
+putstr(const char *s)
+{
+ return fputstr(DEFAULT_UART, s);
+}
+
+int
+fputs(hal_uart_name_t u, const char *s)
{
- putstr(s);
- putchar('\n');
+ fputstr(u, s);
+ fputchar(u, '\n');
return 0;
}
+int puts(const char *s)
+{
+ return fputs(DEFAULT_UART, s);
+}
+
char *
-fgets(char * const s)
+fgets(hal_uart_name_t u, char * const s)
{
char *x = s;
- while((*x=(char)hal_uart_getc()) != '\n') x++;
+ while((*x=(char)hal_uart_getc(u)) != '\n') x++;
*x = 0;
return s;
}
+char *
+gets(char * const s)
+{
+ return fgets(DEFAULT_UART, s);
+}
+
diff --git a/firmware/microblaze/lib/hal_io.h b/firmware/microblaze/lib/hal_io.h
index c67d96c62..99f8f7fc9 100644
--- a/firmware/microblaze/lib/hal_io.h
+++ b/firmware/microblaze/lib/hal_io.h
@@ -20,10 +20,12 @@
#define INCLUDED_HAL_IO_H
#include "memory_map.h"
+#include "hal_uart.h"
void hal_io_init(void);
void hal_finish();
char *gets(char * const s);
+int fputstr(hal_uart_name_t u, const char *s);
/*
* ------------------------------------------------------------------------
diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c
index 91d67b5e0..6717cd5e8 100644
--- a/firmware/microblaze/lib/hal_uart.c
+++ b/firmware/microblaze/lib/hal_uart.c
@@ -16,93 +16,88 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "memory_map.h"
#include "hal_uart.h"
#include "hal_io.h"
-#include "memory_map.h"
-
-// First pass, no interrupts
-// Replaced with divisors.py which generates best divisor
-//#define CALC_DIVISOR(rate) (WISHBONE_CLK_RATE / ((rate) * 16))
+//just to save you from going insane, note that firmware/FPGA UARTs [0-2] correspond to serial ports [1-3].
+//so in software, we refer to UART_DEBUG as UART0, but it transmits on pin TXD<1>. see the UART assignments in hal_uart.h.
#define NSPEEDS 6
#define MAX_WB_DIV 4
+//if you're going to recalculate the divisors, it's just uart_clock_rate / baud_rate.
+//uart_clock_rate is 50MHz for USRP2.
static const uint16_t
-divisor_table[MAX_WB_DIV+1][NSPEEDS] = {
- { 2, 2, 2, 2, 2, 2}, // 0: can't happen
- { 651, 326, 163, 109, 54, 27 }, // 1: 100 MHz
- { 326, 163, 81, 54, 27, 14 }, // 2: 50 MHz
- { 217, 109, 54, 36, 18, 9 }, // 3: 33.3333 MHz
- { 163, 81, 41, 27, 14, 7 }, // 4: 25 MHz
+divisor_table[NSPEEDS] = {
+ 5208, // 9600
+ 2604, // 19200
+ 1302, // 38400
+ 868, // 57600
+ 434, // 115200
+ 217 // 230400
};
-//we wrap hal_uart_putc hal_uart_putc_nowait, and hal_uart_getc to accept a UART pointer given by hal_get_uart. we modify hal_io.c to use the new versions.
+static char uart_mode[4] = {
+ [UART_DEBUG] = UART_MODE_ONLCR,
+ [UART_EXP] = UART_MODE_ONLCR,
+ [UART_GPS] = UART_MODE_ONLCR
+};
-static char uart_mode[4] = {UART_MODE_ONLCR, UART_MODE_ONLCR, UART_MODE_ONLCR, UART_MODE_ONLCR};
+static char uart_speeds[4] = {
+ [UART_DEBUG] = US_230400,
+ [UART_EXP] = US_230400,
+ [UART_GPS] = US_230400
+};
void
-hal_uart_set_mode(int uart, int mode)
+hal_uart_set_mode(hal_uart_name_t uart, int mode)
{
uart_mode[uart] = mode;
}
+void hal_uart_set_speed(hal_uart_name_t uart, hal_uart_speed_t speed)
+{
+ uart_regs[uart].clkdiv = divisor_table[speed];
+}
+
void
hal_uart_init(void)
{
- for(int i = 0; i < 4; i++) {
- hal_uart_set_mode(i, UART_MODE_ONLCR);
- u->clkdiv = 217; // 230400 bps TODO: change to reflect new quad UART
+ for(int i = 0; i < 2; i++) { //uart 3 is unused
+ hal_uart_set_mode(i, uart_mode[i]);
+ hal_uart_set_speed(i, uart_speeds[i]);
}
}
void
-hal_uart_putc(uart_regs_t *u, int ch)
+hal_uart_putc(hal_uart_name_t u, int ch)
{
- if (ch == '\n')// && (uart_mode[uart] == UART_MODE_ONLCR)) //map \n->\r\n if necessary
+ if ((ch == '\n') && (uart_mode[u] == UART_MODE_ONLCR)) //map \n->\r\n if necessary
hal_uart_putc(u, '\r');
- while (u->txlevel == 0) // wait for fifo to have space
+ while (uart_regs[u].txlevel == 0) // wait for fifo to have space
;
- u->txchar = ch;
+ uart_regs[u].txchar = ch;
}
void
-hal_uart_putc_nowait(uart_regs_t *u, int ch)
+hal_uart_putc_nowait(hal_uart_name_t u, int ch)
{
- if (ch == '\n')// && (uart_mode[uart] == UART_MODE_ONLCR)) //map \n->\r\n if necessary
+ if ((ch == '\n') && (uart_mode[u] == UART_MODE_ONLCR)) //map \n->\r\n if necessary
hal_uart_putc(u, '\r');
- if(u->txlevel) // If fifo has space
- u->txchar = ch;
+ if(uart_regs[u].txlevel) // If fifo has space
+ uart_regs[u].txchar = ch;
}
int
-hal_uart_getc(uart_regs_t *u)
+hal_uart_getc(hal_uart_name_t u)
{
- while ((u->rxlevel) == 0) // wait for data to be ready
+ while ((uart_regs[u].rxlevel) == 0) // wait for data to be ready
;
- return u->rxchar;
+ return uart_regs[u].rxchar;
}
-uart_regs_t *
-hal_get_uart(int number)
-{
- switch(number) {
- case 0:
- return uart_regs_0;
- break;
- case 1:
- return uart_regs_1;
- break;
- case 2:
- return uart_regs_2;
- break;
- case 3:
- return uart_regs_3;
- break;
- default:
- return uart_regs_0; //for safety
-}
diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h
index 218bd7cb4..81f4a6777 100644
--- a/firmware/microblaze/lib/hal_uart.h
+++ b/firmware/microblaze/lib/hal_uart.h
@@ -25,29 +25,37 @@
#define UART_MODE_RAW 0x0000 // no mapping on input or output
#define UART_MODE_ONLCR 0x0001 // map \n to \r\n on output (default)
+#define DEFAULT_UART UART_DEBUG //which UART printf, gets, etc. use
+
+typedef enum {
+ US_9600 = 0,
+ US_19200 = 1,
+ US_38400 = 2,
+ US_57600 = 3,
+ US_115200 = 4,
+ US_230400 = 5
+} hal_uart_speed_t;
+
+typedef struct {
+ hal_uart_speed_t speed;
+} hal_uart_config_t;
+
+typedef enum {
+ UART_DEBUG = 0,
+ UART_EXP = 1,
+ UART_GPS = 2
+} hal_uart_name_t;
+
/*
* \brief Set uart mode
*/
-void hal_uart_set_mode(int uart, int flags);
+void hal_uart_set_mode(hal_uart_name_t uart, int flags);
/*!
* \brief one-time call to init
*/
void hal_uart_init(void);
-typedef enum {
- US_9600,
- US_19200,
- US_38400,
- US_57600,
- US_115200,
- US_230400,
-} hal_uart_speed_t;
-
-typedef struct {
- hal_uart_speed_t speed;
-} hal_uart_config_t;
-
/*!
* \brief Set uart parameters
* Default is 115,200 bps, 8N1.
@@ -62,17 +70,17 @@ void hal_uart_get_config(hal_uart_config_t *c);
/*!
* \brief Enqueue \p ch for output over serial port
*/
-void hal_uart_putc(uart_regs_t *u, int ch);
+void hal_uart_putc(hal_uart_name_t u, int ch);
/*!
* \brief Enqueue \p ch for output over serial port, silent fail if queue is full
*/
-void hal_uart_putc_nowait(uart_regs_t *u, int ch);
+void hal_uart_putc_nowait(hal_uart_name_t u, int ch);
/*
* \brief Blocking read of next char from serial port
*/
-int hal_uart_getc(uart_regs_t *u);
+int hal_uart_getc(hal_uart_name_t u);
#endif /* INCLUDED_HAL_UART_H */
diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h
index b69cc59bd..addcf67d4 100644
--- a/firmware/microblaze/usrp2p/memory_map.h
+++ b/firmware/microblaze/usrp2p/memory_map.h
@@ -779,12 +779,10 @@ typedef struct {
volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads
volatile uint32_t txchar; // Write characters to be sent here
volatile uint32_t rxchar; // Read received characters here
+ volatile uint32_t x[3]; //padding to reach 32B
} uart_regs_t;
-#define uart_regs_0 ((uart_regs_t *) UART_BASE)
-#define uart_regs_1 ((uart_regs_t *) UART_BASE + 0x0020)
-#define uart_regs_2 ((uart_regs_t *) UART_BASE + 0x0040)
-#define uart_regs_3 ((uart_regs_t *) UART_BASE + 0x0060)
+#define uart_regs ((uart_regs_t *) UART_BASE)
///////////////////////////////////////////////////
// ATR Controller, Slave 11