aboutsummaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rwxr-xr-x[-rw-r--r--]firmware/fx3/b200/b200_gpifconfig.h46
-rw-r--r--firmware/fx3/b200/b200_main.c974
-rw-r--r--firmware/fx3/b200/b200_main.h2
-rw-r--r--firmware/fx3/b200/b200_usb_descriptors.c100
-rw-r--r--firmware/octoclock/CMakeLists.txt2
-rw-r--r--firmware/octoclock/bootloader/CMakeLists.txt2
-rw-r--r--firmware/octoclock/bootloader/main.c141
-rw-r--r--firmware/octoclock/include/clkdist.h4
-rw-r--r--firmware/octoclock/include/debug.h4
-rw-r--r--firmware/octoclock/include/gpsdo.h2
-rw-r--r--firmware/octoclock/include/net/enc28j60.h539
-rw-r--r--firmware/octoclock/include/net/enc28j60conf.h49
-rw-r--r--firmware/octoclock/include/net/eth_mac_addr.h5
-rw-r--r--firmware/octoclock/include/network.h12
-rw-r--r--firmware/octoclock/include/octoclock.h27
-rw-r--r--firmware/octoclock/include/state.h23
-rw-r--r--firmware/octoclock/include/usart.h4
-rw-r--r--firmware/octoclock/lib/clkdist.c14
-rw-r--r--firmware/octoclock/lib/enc28j60.c488
-rw-r--r--firmware/octoclock/lib/init.c6
-rw-r--r--firmware/octoclock/lib/network.c40
-rw-r--r--firmware/octoclock/lib/state.c102
-rw-r--r--firmware/octoclock/lib/udp_handlers.c37
-rw-r--r--firmware/octoclock/lib/usart.c8
-rw-r--r--firmware/octoclock/octoclock_r4/CMakeLists.txt2
-rw-r--r--firmware/octoclock/octoclock_r4/octoclock_r4_main.c152
-rw-r--r--firmware/usrp3/CMakeLists.txt14
-rw-r--r--firmware/usrp3/include/ethernet.h5
-rw-r--r--firmware/usrp3/include/trace.h82
-rw-r--r--firmware/usrp3/lib/ethernet.c403
-rw-r--r--firmware/usrp3/lib/u3_net_stack.c26
-rw-r--r--firmware/usrp3/x300/x300_defs.h1
-rw-r--r--firmware/usrp3/x300/x300_init.c41
-rw-r--r--firmware/usrp3/x300/x300_main.c10
34 files changed, 1882 insertions, 1485 deletions
diff --git a/firmware/fx3/b200/b200_gpifconfig.h b/firmware/fx3/b200/b200_gpifconfig.h
index 58836fac8..a6a24e0c5 100644..100755
--- a/firmware/fx3/b200/b200_gpifconfig.h
+++ b/firmware/fx3/b200/b200_gpifconfig.h
@@ -1,10 +1,6 @@
-//
-// Copyright 2013-2014 Ettus Research LLC
-//
-
/*
- * Project Name: b200_v2.cyfx
- * Time : 01/17/2013 12:50:08
+ * Project Name: ssf2-edit.cyfx
+ * Time : 11/17/2014 13:01:01
* Device Type: FX3
* Project Type: GPIF2
*
@@ -13,7 +9,7 @@
*
* This is a generated file and should not be modified
* This file need to be included only once in the firmware
- * This file is generated by Gpif2 designer tool version - 1.0.715.0
+ * This file is generated by Gpif2 designer tool version - 1.0.837.1
*
*/
@@ -25,7 +21,7 @@
/* Summary
Number of states in the state machine
*/
-#define CY_NUMBER_OF_STATES 6
+#define CY_NUMBER_OF_STATES 7
/* Summary
Mapping of user defined state names to state indices
@@ -36,12 +32,13 @@
#define WRITE 3
#define SHORT_PKT 4
#define ZLP 5
+#define DSS_STATE 6
/* Summary
Initial value of early outputs from the state machine.
*/
-#define ALPHA_RESET 0x8
+#define ALPHA_RESET 0xC
/* Summary
@@ -58,26 +55,27 @@ uint16_t CyFxGpifTransition[] = {
waveform table.
*/
CyU3PGpifWaveData CyFxGpifWavedata[] = {
- {{0x1E086001,0x000100C4,0x80000000},{0x00000000,0x00000000,0x00000000}},
- {{0x4E080302,0x00000200,0x80000000},{0x00000000,0x00000000,0x00000000}},
- {{0x1E086001,0x000100C4,0x80000000},{0x4E040704,0x20000200,0xC0100000}},
+ {{0x1E086001,0x000302C4,0x80000000},{0x00000000,0x00000000,0x00000000}},
+ {{0x4E080302,0x00000300,0x80000000},{0x1E086006,0x000302C4,0x80000000}},
+ {{0x1E086001,0x000302C4,0x80000000},{0x4E040704,0x20000300,0xC0100000}},
+ {{0x4E080302,0x00000300,0x80000000},{0x1E086001,0x000302C4,0x80000000}},
{{0x00000000,0x00000000,0x00000000},{0x00000000,0x00000000,0x00000000}},
- {{0x00000000,0x00000000,0x00000000},{0x3E738705,0x00000200,0xC0100000}},
- {{0x00000000,0x00000000,0x00000000},{0x5E002703,0x2001020C,0x80000000}},
- {{0x00000000,0x00000000,0x00000000},{0x4E040704,0x20000200,0xC0100000}}
+ {{0x00000000,0x00000000,0x00000000},{0x3E738705,0x00000300,0xC0100000}},
+ {{0x00000000,0x00000000,0x00000000},{0x5E002703,0x2003030C,0x80000000}},
+ {{0x00000000,0x00000000,0x00000000},{0x4E040704,0x20000300,0xC0100000}}
};
/* Summary
Table that maps state indices to the descriptor table indices.
*/
uint8_t CyFxGpifWavedataPosition[] = {
- 0,1,0,2,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
- 0,4,0,2,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
- 0,5,0,2,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
- 0,6,0,2,0,0
+ 0,1,0,2,0,0,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 0,5,0,2,0,0,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 0,6,0,2,0,0,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 0,7,0,2,0,0,7
};
/* Summary
@@ -154,12 +152,12 @@ uint32_t CyFxGpifRegValue[] = {
0x00000000, /* CY_U3P_PIB_GPIF_LAMBDA_STAT */
0x00000000, /* CY_U3P_PIB_GPIF_ALPHA_STAT */
0x00000000, /* CY_U3P_PIB_GPIF_BETA_STAT */
- 0x00080000, /* CY_U3P_PIB_GPIF_WAVEFORM_CTRL_STAT */
+ 0x000C0000, /* CY_U3P_PIB_GPIF_WAVEFORM_CTRL_STAT */
0x00000000, /* CY_U3P_PIB_GPIF_WAVEFORM_SWITCH */
0x00000000, /* CY_U3P_PIB_GPIF_WAVEFORM_SWITCH_TIMEOUT */
0x00000000, /* CY_U3P_PIB_GPIF_CRC_CONFIG */
0x00000000, /* CY_U3P_PIB_GPIF_CRC_DATA */
- 0xFFFFFFF1 /* CY_U3P_PIB_GPIF_BETA_DEASSERT */
+ 0xFFFFFFC1 /* CY_U3P_PIB_GPIF_BETA_DEASSERT */
};
/* Summary
diff --git a/firmware/fx3/b200/b200_main.c b/firmware/fx3/b200/b200_main.c
index cb0172af3..e552d3177 100644
--- a/firmware/fx3/b200/b200_main.c
+++ b/firmware/fx3/b200/b200_main.c
@@ -1,5 +1,5 @@
//
-// Copyright 2013-2014 Ettus Research LLC
+// Copyright 2013-2015 Ettus Research LLC
//
/* This file defines the application that runs on the Cypress FX3 device, and
@@ -34,18 +34,19 @@
* Indented features must have the parent feature enabled as well.
*/
-//#define HAS_HEAP // This requires memory to be set aside for the heap (e.g. required for printing floating-point numbers). You can apply the accompanying patch ('fx3_mem_map.patch') to fx3.ld & cyfxtx.c to create one.
-//#define ENABLE_MSG // This will cause the compiled code to exceed the default text memory area (SYS_MEM). You can apply the accompanying patch ('fx3_mem_map.patch') to fx3.ld & cyfxtx.c to resize the memory map so it will fit.
-//#define ENABLE_MANUAL_DMA_XFER
-//#define ENABLE_MANUAL_DMA_XFER_FROM_HOST
-//#define ENABLE_MANUAL_DMA_XFER_TO_HOST
+#define HAS_HEAP // This requires memory to be set aside for the heap (e.g. required for printing floating-point numbers). You can apply the accompanying patch ('fx3_mem_map.patch') to fx3.ld & cyfxtx.c to create one.
+#define ENABLE_MSG // This will cause the compiled code to exceed the default text memory area (SYS_MEM). You can apply the accompanying patch ('fx3_mem_map.patch') to fx3.ld & cyfxtx.c to resize the memory map so it will fit.
+#define ENABLE_MANUAL_DMA_XFER // Allows us to set it from the host (using the side channel util), doesn't auto-enable it
+//#define ENABLE_P2U_SUSP_EOP
+#define ENABLE_MANUAL_DMA_XFER_FROM_HOST
+#define ENABLE_MANUAL_DMA_XFER_TO_HOST
//#define ENABLE_DMA_BUFFER_PACKET_DEBUG
-//#define ENABLE_FPGA_SB // Be careful: this will add an ever-so-slight delay to some operations (e.g. AD3961 tune)
+#define ENABLE_FPGA_SB // Be careful: this will add an ever-so-slight delay to some operations (e.g. AD3961 tune)
#define ENABLE_RE_ENUM_THREAD
#define ENABLE_USB_EVENT_LOGGING
//#define PREVENT_LOW_POWER_MODE
-//#define ENABLE_INIT_B_WORKAROUND // This should only be enabled if you have a board where the FPGA INIT_B line is broken, but the FPGA is known to work
-//#define ENABLE_DONE_WORKAROUND // This should only be enabled if you have a board where the FPGA DONE line is broken, but the FPGA is known to work
+/*#define ENABLE_INIT_B_WORKAROUND // This should only be enabled if you have a board where the FPGA INIT_B line is broken, but the FPGA is known to work*/
+/*#define ENABLE_DONE_WORKAROUND // This should only be enabled if you have a board where the FPGA DONE line is broken, but the FPGA is known to work*/
#define WATCHDOG_TIMEOUT 1500
#define CHECK_POWER_STATE_SLEEP_TIME 500 // Should be less than WATCHDOG_TIMEOUT
@@ -178,7 +179,7 @@ static uint8_t g_usb_event_log_contiguous_buf[USB_EVENT_LOG_SIZE];
#ifdef ENABLE_FPGA_SB
static CyBool_t g_fpga_sb_enabled = CyFalse;
-static uint16_t g_fpga_sb_uart_div = 434*2;
+//static uint16_t g_fpga_sb_uart_div = 434*2;
static uint16_t g_fpga_sb_last_usb_event_log_index = 0;
static CyU3PThread thread_fpga_sb_poll;
static CyU3PMutex g_suart_lock;
@@ -215,7 +216,8 @@ enum ConfigFlags {
CF_DMA_BUFFER_SIZE = 1 << 5,
CF_DMA_BUFFER_COUNT = 1 << 6,
CF_MANUAL_DMA = 1 << 7,
-
+ CF_SB_BAUD_DIV = 1 << 8,
+
CF_RE_ENUM = 1 << 31
};
@@ -236,7 +238,17 @@ typedef struct ConfigMod {
CONFIG config;
} CONFIG_MOD, *PCONFIG_MOD;
-static CONFIG g_config;
+static CONFIG g_config = {
+ 65, // tx_swing
+ 0x11, // tx_deemphasis
+ 0, // disable_usb2
+ 1, // enable_as_superspeed
+ CY_U3P_DS_THREE_QUARTER_STRENGTH, // pport_drive_strength
+ 64512, // dma_buffer_size 2**16-1, then aligned to next page boundary
+ 1, // dma_buffer_count
+ 0, // manual_dma
+ 434*2 // sb_baud_div
+};
static CONFIG_MOD g_config_mod;
#define REG_LNK_PHY_ERROR_STATUS 0xE0033044
@@ -251,7 +263,7 @@ enum PhyErrors {
PHYERR_PHY_ERROR_EB_UND_EV = 1 << 2,
PHYERR_PHY_ERROR_EB_OVR_EV = 1 << 1,
PHYERR_PHY_ERROR_DECODE_EV = 1 << 0,
-
+
PHYERR_MAX = PHYERR_PHY_LOCK_EV,
PHYERR_MASK = (PHYERR_MAX << 1) - 1
};
@@ -259,7 +271,7 @@ enum PhyErrors {
typedef struct USBErrorCounters {
int phy_error_count;
int link_error_count;
-
+
int PHY_LOCK_EV;
int TRAINING_ERROR_EV;
int RX_ERROR_CRC32_EV;
@@ -281,35 +293,45 @@ typedef struct DMACounters {
int ERROR;
int PROD_SUSP;
int CONS_SUSP;
-
+
int BUFFER_MARKER;
int BUFFER_EOP;
int BUFFER_ERROR;
int BUFFER_OCCUPIED;
-
+
int last_count;
int last_size;
-
+
int last_sid;
int bad_sid_count;
} DMA_COUNTERS, *PDMA_COUNTERS;
+typedef struct PIBCounters
+{
+ int socket_inactive; // CYU3P_PIB_ERR_THR1_SCK_INACTIVE
+} PIB_COUNTERS, *PPIB_COUNTERS;
+
typedef struct Counters {
int magic;
-
+
DMA_COUNTERS dma_to_host;
DMA_COUNTERS dma_from_host;
-
+
int log_overrun_count;
-
+
int usb_error_update_count;
- USB_ERROR_COUNTERS usb_error_counters;
-
+ USB_ERROR_COUNTERS usb_error_counters;
+
int usb_ep_underrun_count;
-
+
int heap_size;
-
+
int resume_count;
+
+ int state_transition_count;
+ int invalid_gpif_state;
+
+ PIB_COUNTERS pib_counters[4];
} COUNTERS, *PCOUNTERS;
volatile static COUNTERS g_counters;
@@ -333,7 +355,7 @@ caddr_t _sbrk(int incr)
extern char __heap_end;
char *prev_heap_end;
- if (heap_end == 0)
+ if (heap_end == 0)
{
heap_end = (char *)&__heap_start;
}
@@ -366,15 +388,15 @@ void msg(const char* str, ...) {
va_list args;
static char buf[LOG_BUFFER_SIZE];
int idx = 0;
-
+
msg_CHECK_USE_LOCK
LOCK(g_log_lock);
-
+
++log_count;
log_count %= 10000;
va_start(args, str);
-
+
if (1) { // FIXME: Optional
uint32_t time_now = CyU3PGetTime();
idx += sprintf(buf, "%08X %04i ", (uint)time_now, log_count);
@@ -382,19 +404,19 @@ void msg(const char* str, ...) {
else
idx += sprintf(buf, "%04i ", log_count);
idx += vsnprintf(buf + idx, LOG_BUFFER_SIZE - idx, str, args);
-
+
va_end(args);
-
+
if ((LOG_BUFFER_SIZE - log_buffer_len) < (idx + 1 + 1)) {
msg_CHECK_USE_LOCK
LOCK(g_counters_lock);
++g_counters.log_overrun_count;
msg_CHECK_USE_LOCK
UNLOCK(g_counters_lock);
-
+
goto msg_exit;
}
-
+
// Circular buffer if we need it later, but currently won't wrap due to above condition
memcpy(log_buffer + log_buffer_len, buf, min(idx + 1, LOG_BUFFER_SIZE - log_buffer_len));
if ((idx + 1) > (LOG_BUFFER_SIZE - log_buffer_len))
@@ -404,7 +426,7 @@ void msg(const char* str, ...) {
}
else
log_buffer[log_buffer_len + idx + 1] = '\0';
-
+
log_buffer_len += (idx + 1);
msg_exit:
msg_CHECK_USE_LOCK
@@ -437,42 +459,42 @@ void msg_nl(const char* str, ...)
*/
void log_reset(void) {
//LOCK(g_log_lock);
-
+
log_buffer_idx = 0;
- log_buffer_len = 0;
+ log_buffer_len = 0;
log_buffer[0] = '\0';
-
+
//UNLOCK(g_log_lock);
}
void counters_auto_reset(void) {
//LOCK(g_counters_lock);
-
- g_counters.log_overrun_count = 0;
-
+
+ g_counters.log_overrun_count = 0;
+
//UNLOCK(g_counters_lock);
}
void counters_dma_reset(void) {
LOCK(g_counters_lock);
-
+
LOCK(g_counters_dma_to_host_lock);
memset((void*)&g_counters.dma_to_host, 0x00, sizeof(DMA_COUNTERS));
UNLOCK(g_counters_dma_to_host_lock);
-
+
LOCK(g_counters_dma_from_host_lock);
memset((void*)&g_counters.dma_from_host, 0x00, sizeof(DMA_COUNTERS));
UNLOCK(g_counters_dma_from_host_lock);
-
+
UNLOCK(g_counters_lock);
}
void counters_reset_usb_errors(void) {
LOCK(g_counters_lock);
-
+
g_counters.usb_error_update_count = 0;
memset((void*)&g_counters.usb_error_counters, 0x00, sizeof(g_counters.usb_error_counters));
-
+
UNLOCK(g_counters_lock);
}
@@ -485,10 +507,10 @@ void dma_callback (
int from_host)
{
CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
-
+
PDMA_COUNTERS cnt = (PDMA_COUNTERS)(from_host ? &g_counters.dma_from_host : &g_counters.dma_to_host);
CyU3PMutex* lock = (from_host ? &g_counters_dma_from_host_lock : &g_counters_dma_to_host_lock);
-
+
uint16_t buffer_status = (input->buffer_p.status & CY_U3P_DMA_BUFFER_STATUS_MASK);
if (buffer_status & CY_U3P_DMA_BUFFER_MARKER)
{
@@ -513,49 +535,51 @@ void dma_callback (
LOCKP(lock);
int prod_cnt = cnt->PROD_EVENT++;
UNLOCKP(lock);
-
- if (cnt->last_count != input->buffer_p.count)
- msg("[DMA %05d] buffer.count (%d) != last_count (%d)", prod_cnt, input->buffer_p.count, cnt->last_count);
+
+ //if (cnt->last_count != input->buffer_p.count)
+ // msg("[DMA%d %05d] buffer.count (%05d) != last_count (%05d)", from_host, prod_cnt, input->buffer_p.count, cnt->last_count);
cnt->last_count = input->buffer_p.count;
-
+
if (cnt->last_size != input->buffer_p.size)
- msg("[DMA %05d] buffer.size (%d) != last_size (%d)", prod_cnt, input->buffer_p.size, cnt->last_size);
+ msg("[DMA%d %05d] buffer.size (%05d) != last_size (%05d)", from_host, prod_cnt, input->buffer_p.size, cnt->last_size);
cnt->last_size = input->buffer_p.size;
-
+
uint32_t* p32 = input->buffer_p.buffer;
uint32_t sid = p32[1];
cnt->last_sid = (int)sid;
- if ((sid != 0xa0) && (sid != 0xb0))
+ if (((from_host == 0) && ((sid != 0xa0) && (sid != 0xb0))) ||
+ ((from_host == 1) && ((sid != 0x50) && (sid != 0x60))))
{
cnt->bad_sid_count++;
- msg("[DMA %05d] Bad SID: 0x%08x", prod_cnt, sid);
+ msg("[DMA%d %05d] Bad SID: 0x%08x", from_host, prod_cnt, sid);
}
-
+
uint16_t* p16 = input->buffer_p.buffer;
-
+
if (p32[0] & (((uint32_t)1) << 31))
{
- msg("[DMA %05d] Error code: 0x%x (packet len: %d)", prod_cnt, p32[4], p16[0]); // Status
-
- //msg("[DMA] 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", p32[0], p32[1], p32[2], p32[3], p32[4], p32[5]);
+ msg("[DMA%d %05d] Error code: 0x%x (packet len: %05d, buffer count: %05d, seq: %04d)", from_host, prod_cnt, p32[4], p16[0], input->buffer_p.count, (p16[1] & 0x0fff)); // Status
+
+ //msg("[DMA%d] 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", from_host, p32[0], p32[1], p32[2], p32[3], p32[4], p32[5]);
}
else
- {
+ {
if (p16[1] & (((uint16_t)1) << 12))
{
- msg("[DMA %05d] EOB", prod_cnt); // Comes with one sample
+ msg("[DMA%d %05d] EOB (packet len: %05d, buffer count: %05d)", from_host, prod_cnt, p16[0], input->buffer_p.count); // Comes with one sample
}
-
+
if ((p16[0] != input->buffer_p.count) &&
- ((p16[0] + 4) != input->buffer_p.count))
+ ((p16[0] + 4) != input->buffer_p.count)) // Case of overrun packet length being padded (being rounded up)
{
- msg("[DMA %05d] Packet len (%d) != buffer count (%d)", prod_cnt, p16[0], input->buffer_p.count);
+ if (from_host == 0)
+ msg("[DMA%d %05d] Packet len (%05d) != buffer count (%05d), seq: %04d [0x%04x 0x%04x]", from_host, prod_cnt, p16[0], input->buffer_p.count, (p16[1] & 0x0fff), p16[0], p16[1]);
}
-
- //msg("[DMA] 0x%04x 0x%04x 0x%04x 0x%04x", p16[0], p16[1], p16[2], p16[3]);
-
+
+ //msg("[DMA%d] 0x%04x 0x%04x 0x%04x 0x%04x", from_host, p16[0], p16[1], p16[2], p16[3]);
+
if (p16[1] & (((uint16_t)1) << 12))
- msg("[DMA %05d] 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", prod_cnt, p32[0], p32[1], p32[2], p32[3], p32[4], p32[5]);
+ msg("[DMA%d %05d] 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", from_host, prod_cnt, p32[0], p32[1], p32[2], p32[3], p32[4], p32[5]);
}
#endif // ENABLE_DMA_BUFFER_PACKET_DEBUG
status = CyU3PDmaChannelCommitBuffer (chHandle, input->buffer_p.count, 0);
@@ -594,7 +618,7 @@ void dma_callback (
LOCKP(lock);
cnt->ABORTED++;
UNLOCKP(lock);
-
+
msg("! Aborted %i", from_host);
}
else if (type == CY_U3P_DMA_CB_ERROR)
@@ -602,7 +626,7 @@ void dma_callback (
LOCKP(lock);
cnt->ERROR++;
UNLOCKP(lock);
-
+
msg("! Error %i", from_host);
}
else if (type == CY_U3P_DMA_CB_PROD_SUSP)
@@ -610,7 +634,7 @@ void dma_callback (
LOCKP(lock);
cnt->PROD_SUSP++;
UNLOCKP(lock);
-
+
msg("! Prod suspend %i", from_host);
}
else if (type == CY_U3P_DMA_CB_CONS_SUSP)
@@ -618,8 +642,10 @@ void dma_callback (
LOCKP(lock);
cnt->CONS_SUSP++;
UNLOCKP(lock);
-
- msg("! Cons suspend %i", from_host);
+
+ //msg("! Cons suspend %i", from_host);
+
+ CyU3PDmaChannelResume (chHandle, CyFalse, CyTrue);
}
}
@@ -672,7 +698,7 @@ void gpio_interrupt_callback(uint8_t gpio_id) {
* everything will come back up properly. */
void b200_fw_stop(void) {
msg("b200_fw_stop");
-
+
CyU3PEpConfig_t usb_endpoint_config;
/* Update the flag. */
@@ -683,14 +709,14 @@ void b200_fw_stop(void) {
CyU3PUsbFlushEp(DATA_ENDPOINT_CONSUMER);
CyU3PUsbFlushEp(CTRL_ENDPOINT_PRODUCER);
CyU3PUsbFlushEp(CTRL_ENDPOINT_CONSUMER);
-
+
/* Reset the DMA channels */
// SDK 1.3 known issue #1 - probably not necessary since Destroy is next, but just in case
CyU3PDmaChannelReset(&data_cons_to_prod_chan_handle);
CyU3PDmaChannelReset(&data_prod_to_cons_chan_handle);
CyU3PDmaChannelReset(&ctrl_cons_to_prod_chan_handle);
CyU3PDmaChannelReset(&ctrl_prod_to_cons_chan_handle);
-
+
/* Destroy the DMA channels */
CyU3PDmaChannelDestroy(&data_cons_to_prod_chan_handle);
CyU3PDmaChannelDestroy(&data_prod_to_cons_chan_handle);
@@ -716,7 +742,7 @@ void reset_gpif(void) {
CyU3PGpioSetValue(GPIO_FPGA_RESET, CyTrue);
// Bring down GPIF
- CyU3PGpifDisable(CyTrue);
+ CyU3PGpifDisable(/*CyTrue*/CyFalse);
/* Reset the DMA channels */
CyU3PDmaChannelReset(&data_cons_to_prod_chan_handle);
@@ -725,42 +751,41 @@ void reset_gpif(void) {
CyU3PDmaChannelReset(&ctrl_prod_to_cons_chan_handle);
/* Reset the DMA transfers */
- CyU3PDmaChannelSetXfer(&data_cons_to_prod_chan_handle, \
- DMA_SIZE_INFINITE);
-
- CyU3PDmaChannelSetXfer(&data_prod_to_cons_chan_handle, \
- DMA_SIZE_INFINITE);
-
- CyU3PDmaChannelSetXfer(&ctrl_cons_to_prod_chan_handle, \
- DMA_SIZE_INFINITE);
-
- CyU3PDmaChannelSetXfer(&ctrl_prod_to_cons_chan_handle, \
- DMA_SIZE_INFINITE);
+ CyU3PDmaChannelSetXfer(&data_cons_to_prod_chan_handle, DMA_SIZE_INFINITE);
+ CyU3PDmaChannelSetXfer(&data_prod_to_cons_chan_handle, DMA_SIZE_INFINITE);
+ CyU3PDmaChannelSetXfer(&ctrl_cons_to_prod_chan_handle, DMA_SIZE_INFINITE);
+ CyU3PDmaChannelSetXfer(&ctrl_prod_to_cons_chan_handle, DMA_SIZE_INFINITE);
/* Flush the USB endpoints */
CyU3PUsbFlushEp(DATA_ENDPOINT_PRODUCER);
CyU3PUsbFlushEp(DATA_ENDPOINT_CONSUMER);
CyU3PUsbFlushEp(CTRL_ENDPOINT_PRODUCER);
CyU3PUsbFlushEp(CTRL_ENDPOINT_CONSUMER);
-
+
/* Load the GPIF configuration for Slave FIFO sync mode. */
- CyU3PGpifLoad(&CyFxGpifConfig);
-
+ //CyU3PGpifLoad(&CyFxGpifConfig);
+
/* Start the state machine. */
- CyU3PGpifSMStart(RESET, ALPHA_RESET);
-
+ //if (CyU3PGpifSMStart(RESET, ALPHA_RESET) != CY_U3P_SUCCESS)
+ // msg("! CyU3PGpifSMStart");
+
/* Configure the watermarks for the slfifo-write buffers. */
- CyU3PGpifSocketConfigure(0, DATA_TX_PPORT_SOCKET, 5, CyFalse, 1);
- CyU3PGpifSocketConfigure(1, DATA_RX_PPORT_SOCKET, 6, CyFalse, 1);
- CyU3PGpifSocketConfigure(2, CTRL_COMM_PPORT_SOCKET, 5, CyFalse, 1);
- CyU3PGpifSocketConfigure(3, CTRL_RESP_PPORT_SOCKET, 6, CyFalse, 1);
-
+ //CyU3PGpifSocketConfigure(0, DATA_TX_PPORT_SOCKET, 5, CyFalse, 1);
+ //CyU3PGpifSocketConfigure(1, DATA_RX_PPORT_SOCKET, 6, CyFalse, 1);
+ //CyU3PGpifSocketConfigure(2, CTRL_COMM_PPORT_SOCKET, 5, CyFalse, 1);
+ //CyU3PGpifSocketConfigure(3, CTRL_RESP_PPORT_SOCKET, 6, CyFalse, 1);
+
CyU3PGpioSetValue(GPIO_FPGA_RESET, CyFalse);
-
+
CyU3PThreadSleep(FPGA_RESET_SETTLING_TIME);
-
+
+ if (CyU3PGpifSMStart(RESET, ALPHA_RESET) != CY_U3P_SUCCESS)
+ msg("! CyU3PGpifSMStart");
+
+ msg("GPIF reset");
+
b200_start_fpga_sb_gpio();
-
+
g_fx3_state = STATE_RUNNING;
}
@@ -792,11 +817,11 @@ CyU3PReturnStatus_t b200_set_io_matrix(CyBool_t fpga_config_mode) {
io_config_matrix.useI2C = CyTrue;
io_config_matrix.useI2S = CyFalse;
io_config_matrix.useSpi = fpga_config_mode;
-
+
res = CyU3PDeviceConfigureIOMatrix(&io_config_matrix);
if (res != CY_U3P_SUCCESS)
msg("! ConfigureIOMatrix");
-
+
return res;
}
@@ -814,11 +839,11 @@ CyU3PReturnStatus_t b200_gpio_init(CyBool_t set_callback) {
gpio_clock_config.simpleDiv = CY_U3P_GPIO_SIMPLE_DIV_BY_2;
gpio_clock_config.clkSrc = CY_U3P_SYS_CLK;
gpio_clock_config.halfDiv = 0;
-
+
res = CyU3PGpioInit(&gpio_clock_config, (set_callback ? gpio_interrupt_callback : NULL));
if (res != CY_U3P_SUCCESS)
msg("! CyU3PGpioInit");
-
+
return res;
}
@@ -827,36 +852,36 @@ void sb_write(uint8_t reg, uint32_t val) {
#ifdef ENABLE_FPGA_SB
const int len = 32;
int i;
-
+
if (g_fpga_sb_enabled == CyFalse)
return;
-
+
reg += FPGA_SB_UART_ADDR_BASE;
-
+
//CyU3PBusyWait(1); // Can be used after each SetValue to slow down bit changes
-
+
// START
CyU3PGpioSetValue(GPIO_FPGA_SB_SCL, 1); // Should already be 1
CyU3PGpioSetValue(GPIO_FPGA_SB_SDA, 0);
-
+
// ADDR[8]
for (i = 7; i >= 0; i--) {
uint8_t bit = ((reg & (0x1 << i)) ? 0x01 : 0x00);
CyU3PGpioSetValue(GPIO_FPGA_SB_SCL, 0);
CyU3PGpioSetValue(GPIO_FPGA_SB_SDA, bit);
-
+
CyU3PGpioSetValue(GPIO_FPGA_SB_SCL, 1); // FPGA reads bit
}
-
+
// DATA[32]
for (i = (len-1); i >= 0; i--) {
uint8_t bit = ((val & (0x1 << i)) ? 0x01 : 0x00);
CyU3PGpioSetValue(GPIO_FPGA_SB_SCL, 0);
CyU3PGpioSetValue(GPIO_FPGA_SB_SDA, bit);
-
+
CyU3PGpioSetValue(GPIO_FPGA_SB_SCL, 1); // FPGA reads bit
}
-
+
// STOP
CyU3PGpioSetValue(GPIO_FPGA_SB_SDA, 0);
CyU3PGpioSetValue(GPIO_FPGA_SB_SCL, 0);
@@ -888,10 +913,10 @@ void b200_enable_fpga_sb_gpio(CyBool_t enable) {
#ifdef ENABLE_FPGA_SB
CyU3PGpioSimpleConfig_t gpio_config;
CyU3PReturnStatus_t res;
-
+
if (enable == CyFalse) {
g_fpga_sb_enabled = CyFalse;
-
+
return;
}
@@ -900,7 +925,7 @@ void b200_enable_fpga_sb_gpio(CyBool_t enable) {
gpio_config.driveHighEn = CyTrue;
gpio_config.inputEn = CyFalse;
gpio_config.intrMode = CY_U3P_GPIO_NO_INTR;
-
+
res = CyU3PGpioSetSimpleConfig(GPIO_FPGA_SB_SCL, &gpio_config);
if (res != CY_U3P_SUCCESS) {
msg("! GpioSetSimpleConfig GPIO_FPGA_SB_SCL");
@@ -912,9 +937,9 @@ void b200_enable_fpga_sb_gpio(CyBool_t enable) {
CyU3PGpioSetValue(GPIO_FPGA_SB_SCL, 1);
CyU3PGpioSetValue(GPIO_FPGA_SB_SDA, 1);
-
+
g_fpga_sb_enabled = CyTrue;
-
+
msg("Debug SB OK");
#endif // ENABLE_FPGA_SB
}
@@ -923,10 +948,10 @@ void b200_enable_fpga_sb_gpio(CyBool_t enable) {
void b200_start_fpga_sb_gpio(void) {
#ifdef ENABLE_FPGA_SB
LOCK(g_suart_lock);
- sb_write(SUART_CLKDIV, g_fpga_sb_uart_div); // 16-bit reg, master clock = 100 MHz (434*2x = 230400/2)
+ sb_write(SUART_CLKDIV, /*g_fpga_sb_uart_div*/g_config.sb_baud_div); // 16-bit reg, master clock = 100 MHz (434*2x = 230400/2)
_sb_write_string("\r\n B2x0 FPGA reset\r\n");
UNLOCK(g_suart_lock);
-
+
msg("Compat: %d.%d", FX3_COMPAT_MAJOR, FX3_COMPAT_MINOR);
msg("FX3 SDK: %d.%d.%d (build %d)", CYFX_VERSION_MAJOR, CYFX_VERSION_MINOR, CYFX_VERSION_PATCH, CYFX_VERSION_BUILD);
#endif // ENABLE_FPGA_SB
@@ -940,15 +965,15 @@ void b200_start_fpga_sb_gpio(void) {
* application thread will re-configure some of the pins. */
void b200_gpios_pre_fpga_config(void) {
CyU3PGpioSimpleConfig_t gpio_config;
-
+
//b200_enable_fpga_sb_gpio(CyFalse);
-
+
//CyU3PGpioDeInit();
-
+
b200_set_io_matrix(CyTrue);
-
+
//b200_gpio_init(CyTrue); // This now done once during startup
-
+
////////////////////////////////////
/* GPIO[0:32] must be set with the DeviceOverride function, instead of the
@@ -989,24 +1014,24 @@ void b200_gpios_pre_fpga_config(void) {
/* Initialize GPIO output values. */
CyU3PGpioSetValue(GPIO_FPGA_RESET, 0);
CyU3PGpioSetValue(GPIO_PROGRAM_B, 1);
-
+
b200_enable_fpga_sb_gpio(CyTrue); // So SCL/SDA are already high when SB state machine activates
}
void b200_slfifo_mode_gpio_config(void) {
CyU3PGpioSimpleConfig_t gpio_config;
-
+
//b200_enable_fpga_sb_gpio(CyFalse);
-
+
//CyU3PGpioDeInit();
-
+
b200_set_io_matrix(CyFalse);
//b200_gpio_init(CyFalse); // This now done once during startup
-
+
////////////////////////////////////
-
+
/* GPIO[0:32] must be set with the DeviceOverride function, instead of the
* SimpleEn array configuration. */
CyU3PDeviceGpioOverride(GPIO_FPGA_RESET, CyTrue);
@@ -1015,7 +1040,7 @@ void b200_slfifo_mode_gpio_config(void) {
CyU3PDeviceGpioOverride(GPIO_FX3_CE, CyTrue);
CyU3PDeviceGpioOverride(GPIO_FX3_MISO, CyTrue);
CyU3PDeviceGpioOverride(GPIO_FX3_MOSI, CyTrue);
-
+
/* Configure GPIOs:
* Outputs:
* driveLowEn = True
@@ -1031,13 +1056,13 @@ void b200_slfifo_mode_gpio_config(void) {
gpio_config.driveHighEn = CyTrue;
gpio_config.inputEn = CyFalse;
gpio_config.intrMode = CY_U3P_GPIO_NO_INTR;
-
+
CyU3PGpioSetSimpleConfig(GPIO_FPGA_RESET, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_SHDN_SW, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_FX3_SCLK, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_FX3_CE, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_FX3_MOSI, &gpio_config);
-
+
/* Reconfigure the GPIO configure struct for inputs that do NOT require
* interrupts attached to them. */
gpio_config.outValue = CyFalse;
@@ -1045,23 +1070,23 @@ void b200_slfifo_mode_gpio_config(void) {
gpio_config.driveLowEn = CyFalse;
gpio_config.driveHighEn = CyFalse;
gpio_config.intrMode = CY_U3P_GPIO_NO_INTR;
-
+
CyU3PGpioSetSimpleConfig(GPIO_FX3_MISO, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_AUX_PWR_ON, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_PROGRAM_B, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_INIT_B, &gpio_config);
CyU3PGpioSetSimpleConfig(GPIO_DONE, &gpio_config);
-
+
/* Initialize GPIO output values. */
CyU3PGpioSetValue(GPIO_FPGA_RESET, 0);
CyU3PGpioSetValue(GPIO_SHDN_SW, 1);
CyU3PGpioSetValue(GPIO_FX3_SCLK, 0);
CyU3PGpioSetValue(GPIO_FX3_CE, 1);
CyU3PGpioSetValue(GPIO_FX3_MOSI, 0);
-
+
// Disabled here as only useful once FPGA has been programmed
//b200_enable_fpga_sb_gpio(CyTrue);
- //b200_start_fpga_sb_gpio(); // Set set up SB USART
+ //b200_start_fpga_sb_gpio(); // Set up SB USART
}
@@ -1072,7 +1097,7 @@ void b200_slfifo_mode_gpio_config(void) {
* ready to receive data from the host. */
void b200_fw_start(void) {
msg("b200_fw_start");
-
+
CyU3PDmaChannelConfig_t dma_channel_config;
CyU3PEpConfig_t usb_endpoint_config;
CyU3PUSBSpeed_t usb_speed;
@@ -1095,9 +1120,9 @@ void b200_fw_start(void) {
data_buffer_size = 512;
g_vendor_req_buff_size = USB2_VREQ_BUF_SIZE; // Max 64
num_packets_per_burst = USB2_PACKETS_PER_BURST; // 1
-
+
data_buffer_size_to_host = data_buffer_size_from_host = data_buffer_size;
-
+
break;
case CY_U3P_SUPER_SPEED:
@@ -1110,41 +1135,49 @@ void b200_fw_start(void) {
msg("LPMDisable OK");
//#endif // PREVENT_LOW_POWER_MODE
max_packet_size = 1024; // Per USB3 spec
-
+
// SDK ver: total available buffer memory
// 1.2.3: 204KB
// 1.3.1: 188KB
-
+
// These options should be ignored - data_buffer_count *MUST* be 1
// They follow is kept for future testing
-
+
// 1K
//data_buffer_count = 64;
//data_buffer_size = 1024;
-
+
// 4K
//data_buffer_count = 8;
//data_buffer_size = 4096;
-
+
+ // 8K
+ //data_buffer_count = 4;
+ //data_buffer_size = 4096*2;
+
// 16K
//data_buffer_count = 2*2;
//data_buffer_size = 16384; // Default 16K
-
+
// 32K
//data_buffer_count = 2;
//data_buffer_size = 16384*2;
-
- data_buffer_count = 1;
- data_buffer_size = ((1 << 16) - 1);
- data_buffer_size -= (data_buffer_size % 1024); // Align to 1K boundary
-
+
+ //data_buffer_count = 1;
+ //data_buffer_size = ((1 << 16) - 1);
+ //data_buffer_size = 16384;
+ //data_buffer_size -= (data_buffer_size % 1024); // Align to 1K boundary
+
+ data_buffer_count = g_config.dma_buffer_count;
+ data_buffer_size = g_config.dma_buffer_size;
+
data_buffer_size_to_host = data_buffer_size;
data_buffer_size_from_host = data_buffer_size;
-
+
g_vendor_req_buff_size = USB3_VREQ_BUF_SIZE; // Max 512
- num_packets_per_burst = USB3_PACKETS_PER_BURST; // 16
+ num_packets_per_burst = USB3_PACKETS_PER_BURST*1+4*0; // 16
break;
-
+
case CY_U3P_NOT_CONNECTED:
msg("! CY_U3P_NOT_CONNECTED");
return;
@@ -1152,9 +1185,31 @@ void b200_fw_start(void) {
default:
return;
}
-
+
msg("[DMA] to host: %d, from host: %d, depth: %d, burst size: %d", data_buffer_size_to_host, data_buffer_size_from_host, data_buffer_count, num_packets_per_burst);
+#ifdef ENABLE_MANUAL_DMA_XFER
+ msg("[DMA] Callback enabled");
+
+#ifdef ENABLE_P2U_SUSP_EOP
+ msg("[DMA] P2U_SUSP_EOP enabled");
+#endif // ENABLE_P2U_SUSP_EOP
+#ifdef ENABLE_MANUAL_DMA_XFER_FROM_HOST
+ msg("[DMA] Manual transfers from host");
+#endif // ENABLE_MANUAL_DMA_XFER_FROM_HOST
+#ifdef ENABLE_MANUAL_DMA_XFER_TO_HOST
+ msg("[DMA] Manual transfers to host");
+#endif // ENABLE_MANUAL_DMA_XFER_TO_HOST
+#ifdef ENABLE_DMA_BUFFER_PACKET_DEBUG
+ msg("[DMA] Packet debugging enabled");
+#endif // ENABLE_DMA_BUFFER_PACKET_DEBUG
+
+#else
+ msg("[DMA] AUTO transfer mode");
+#endif // ENABLE_MANUAL_DMA_XFER
+
+ msg("[DMA] Transfer override: %s", (g_config.manual_dma ? "manual" : "auto"));
+
/*************************************************************************
* Slave FIFO Data DMA Channel Configuration
*************************************************************************/
@@ -1205,6 +1260,8 @@ CY_U3P_DMA_CB_PROD_SUSP |
CY_U3P_DMA_CB_CONS_SUSP |
#endif // ENABLE_MANUAL_DMA_XFER
0;
+ //if (g_config.manual_dma == 0)
+ // dma_channel_config.notification = 0; // Force all off is manual is disabled
dma_channel_config.cb =
#if defined(ENABLE_MANUAL_DMA_XFER) && defined(ENABLE_MANUAL_DMA_XFER_FROM_HOST)
from_host_dma_callback;
@@ -1218,16 +1275,16 @@ CY_U3P_DMA_CB_CONS_SUSP |
CyU3PDmaChannelCreate (&data_cons_to_prod_chan_handle,
#if defined(ENABLE_MANUAL_DMA_XFER) && defined(ENABLE_MANUAL_DMA_XFER_FROM_HOST)
- /*CY_U3P_DMA_TYPE_AUTO_SIGNAL*/CY_U3P_DMA_TYPE_MANUAL,
+ (g_config.manual_dma ? /*CY_U3P_DMA_TYPE_AUTO_SIGNAL*/CY_U3P_DMA_TYPE_MANUAL : CY_U3P_DMA_TYPE_AUTO),
#else
CY_U3P_DMA_TYPE_AUTO,
#endif // ENABLE_MANUAL_DMA_XFER
&dma_channel_config);
-
+
// By default these will adopt 'usb_endpoint_config.pcktSize'
//CyU3PSetEpPacketSize(DATA_ENDPOINT_PRODUCER, 16384);
//CyU3PSetEpPacketSize(DATA_ENDPOINT_CONSUMER, 16384);
-
+
/* Create a DMA AUTO channel for P2U transfer. */
dma_channel_config.size = data_buffer_size_to_host;
dma_channel_config.prodSckId = DATA_RX_PPORT_SOCKET;
@@ -1244,21 +1301,28 @@ CY_U3P_DMA_CB_ERROR |
CY_U3P_DMA_CB_PROD_SUSP |
CY_U3P_DMA_CB_CONS_SUSP |
#endif // ENABLE_MANUAL_DMA_XFER
+#if defined(ENABLE_MANUAL_DMA_XFER) && defined(ENABLE_P2U_SUSP_EOP)
+CY_U3P_DMA_CB_CONS_SUSP | // For 'CyU3PDmaChannelSetSuspend' below
+#endif // ENABLE_P2U_SUSP_EOP
0;
+ //if (g_config.manual_dma == 0)
+ // dma_channel_config.notification = 0; // Force all off is manual is disabled
dma_channel_config.cb =
-#if defined(ENABLE_MANUAL_DMA_XFER) && defined(ENABLE_MANUAL_DMA_XFER_TO_HOST)
+#if defined(ENABLE_MANUAL_DMA_XFER) && (defined(ENABLE_MANUAL_DMA_XFER_TO_HOST) || defined(ENABLE_P2U_SUSP_EOP))
to_host_dma_callback;
#else
NULL;
#endif // ENABLE_MANUAL_DMA_XFER
CyU3PDmaChannelCreate (&data_prod_to_cons_chan_handle,
#if defined(ENABLE_MANUAL_DMA_XFER) && defined(ENABLE_MANUAL_DMA_XFER_TO_HOST)
- /*CY_U3P_DMA_TYPE_AUTO_SIGNAL*/CY_U3P_DMA_TYPE_MANUAL,
+ (g_config.manual_dma ? /*CY_U3P_DMA_TYPE_AUTO_SIGNAL*/CY_U3P_DMA_TYPE_MANUAL : CY_U3P_DMA_TYPE_AUTO),
#else
CY_U3P_DMA_TYPE_AUTO,
#endif // ENABLE_MANUAL_DMA_XFER
&dma_channel_config);
-
+#ifdef ENABLE_P2U_SUSP_EOP
+ CyU3PDmaChannelSetSuspend(&data_prod_to_cons_chan_handle, CY_U3P_DMA_SCK_SUSP_NONE, CY_U3P_DMA_SCK_SUSP_EOP);
+#endif // ENABLE_P2U_SUSP_EOP
/* Flush the Endpoint memory */
CyU3PUsbFlushEp(DATA_ENDPOINT_PRODUCER);
CyU3PUsbFlushEp(DATA_ENDPOINT_CONSUMER);
@@ -1328,7 +1392,7 @@ CY_U3P_DMA_CB_CONS_SUSP |
/* Set DMA channel transfer size. */
CyU3PDmaChannelSetXfer(&ctrl_cons_to_prod_chan_handle, DMA_SIZE_INFINITE);
CyU3PDmaChannelSetXfer(&ctrl_prod_to_cons_chan_handle, DMA_SIZE_INFINITE);
-
+
//CyU3PUsbEnableEPPrefetch(); // To address USB_EVENT_EP_UNDERRUN on EP 0x86 (didn't fix it though)
/* Update the application status flag. */
@@ -1364,76 +1428,76 @@ void event_usb_callback (CyU3PUsbEventType_t event_type, uint16_t event_data) {
b200_fw_stop();
}
break;
-
+
case CY_U3P_USB_EVENT_CONNECT:
msg("USB_EVENT_CONNECT");
break;
-
+
case CY_U3P_USB_EVENT_SUSPEND:
msg("USB_EVENT_SUSPEND");
break;
-
+
case CY_U3P_USB_EVENT_RESUME: // Known issue: this is called repeatedly after a resume
//msg("USB_EVENT_RESUME");
g_counters.resume_count++; // Not locked
break;
-
+
case CY_U3P_USB_EVENT_SPEED:
msg("USB_EVENT_SPEED");
break;
-
+
case CY_U3P_USB_EVENT_SETINTF:
msg("USB_EVENT_SETINTF");
break;
-
+
case CY_U3P_USB_EVENT_SET_SEL:
msg("USB_EVENT_SET_SEL");
break;
-
+
case CY_U3P_USB_EVENT_SOF_ITP: // CyU3PUsbEnableITPEvent
//msg("USB_EVENT_SOF_ITP");
break;
-
+
case CY_U3P_USB_EVENT_EP0_STAT_CPLT:
//msg("USB_EVENT_EP0_STAT_CPLT"); // Occurs each time there's a control transfer
break;
-
+
case CY_U3P_USB_EVENT_VBUS_VALID:
msg("USB_EVENT_VBUS_VALID");
break;
-
+
case CY_U3P_USB_EVENT_VBUS_REMOVED:
msg("USB_EVENT_VBUS_REMOVED");
break;
-
+
case CY_U3P_USB_EVENT_HOST_CONNECT:
msg("USB_EVENT_HOST_CONNECT");
break;
-
+
case CY_U3P_USB_EVENT_HOST_DISCONNECT:
msg("USB_EVENT_HOST_DISCONNECT");
break;
-
+
case CY_U3P_USB_EVENT_OTG_CHANGE:
msg("USB_EVENT_OTG_CHANGE");
break;
-
+
case CY_U3P_USB_EVENT_OTG_VBUS_CHG:
msg("USB_EVENT_OTG_VBUS_CHG");
break;
-
+
case CY_U3P_USB_EVENT_OTG_SRP:
msg("USB_EVENT_OTG_SRP");
break;
-
+
case CY_U3P_USB_EVENT_EP_UNDERRUN: // See SDK 1.3 known issues 17 if this happens (can probably ignore first logged occurence)
LOCK(g_counters_lock);
++g_counters.usb_ep_underrun_count;
UNLOCK(g_counters_lock);
-
+
msg("! USB_EVENT_EP_UNDERRUN on EP 0x%02x", event_data);
break;
-
+
case CY_U3P_USB_EVENT_LNK_RECOVERY:
msg("USB_EVENT_LNK_RECOVERY");
break;
@@ -1441,16 +1505,16 @@ void event_usb_callback (CyU3PUsbEventType_t event_type, uint16_t event_data) {
case CY_U3P_USB_EVENT_USB3_LNKFAIL:
msg("USB_EVENT_USB3_LNKFAIL");
break;
-
+
case CY_U3P_USB_EVENT_SS_COMP_ENTRY:
msg("USB_EVENT_SS_COMP_ENTRY");
break;
-
+
case CY_U3P_USB_EVENT_SS_COMP_EXIT:
msg("USB_EVENT_SS_COMP_EXIT");
break;
#endif // (CYFX_VERSION_MAJOR >= 1) && (CYFX_VERSION_MINOR >= 3)
-
+
default:
msg("! Unhandled USB event");
break;
@@ -1510,7 +1574,7 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
if(wLength > b200_usb_product_desc[0]) {
wLength = b200_usb_product_desc[0];
}
-
+
//msg("MS string desc");
CyU3PUsbSendEP0Data(wLength, ((uint8_t *) b200_usb_product_desc));
@@ -1540,7 +1604,7 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
CyU3PUsbStall(wIndex, CyFalse, CyTrue);
handled = CyTrue;
CyU3PUsbAckSetup();
-
+
msg("Clear DATA_ENDPOINT_PRODUCER");
}
@@ -1553,7 +1617,7 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
CyU3PUsbStall(wIndex, CyFalse, CyTrue);
handled = CyTrue;
CyU3PUsbAckSetup();
-
+
msg("Clear DATA_ENDPOINT_CONSUMER");
}
@@ -1566,7 +1630,7 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
CyU3PUsbStall(wIndex, CyFalse, CyTrue);
handled = CyTrue;
CyU3PUsbAckSetup();
-
+
msg("Clear CTRL_ENDPOINT_PRODUCER");
}
@@ -1579,7 +1643,7 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
CyU3PUsbStall(wIndex, CyFalse, CyTrue);
handled = CyTrue;
CyU3PUsbAckSetup();
-
+
msg("Clear CTRL_ENDPOINT_CONSUMER");
}
}
@@ -1595,7 +1659,7 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
switch(bRequest) {
case B200_VREQ_BITSTREAM_START: {
CyU3PUsbGetEP0Data(1, g_vendor_req_buffer, &read_count);
-
+
g_fpga_programming_write_count = 0;
CyU3PEventSet(&g_event_usb_config, EVENT_BITSTREAM_START, \
@@ -1614,12 +1678,12 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
}
break;
}
-
+
case B200_VREQ_BITSTREAM_DATA_FILL: {
CyU3PUsbGetEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer, &g_vendor_req_read_count);
break;
}
-
+
case B200_VREQ_BITSTREAM_DATA_COMMIT: {
/*CyU3PReturnStatus_t*/int spi_result = -1;
if (g_fx3_state == STATE_CONFIGURING_FPGA) {
@@ -1670,8 +1734,14 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
case B200_VREQ_GET_LOG: {
LOCK(g_log_lock);
-
- if (log_buffer_idx == 0)
+
+ if (log_buffer_len == 0) {
+ log_buffer[0] = '\0';
+ CyU3PUsbSendEP0Data(1, (uint8_t*)log_buffer);
+ //CyU3PUsbSendEP0Data(0, NULL);
+ //CyU3PUsbAckSetup();
+ }
+ else if (log_buffer_idx == 0)
CyU3PUsbSendEP0Data(log_buffer_len, (uint8_t*)log_buffer);
else {
int len1 = min(LOG_BUFFER_SIZE - log_buffer_idx, log_buffer_len);
@@ -1681,39 +1751,39 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
memcpy(log_contiguous_buffer + len1, log_buffer, log_buffer_len - len1);
CyU3PUsbSendEP0Data(log_buffer_len, (uint8_t*)log_contiguous_buffer);
}
-
+
// FIXME: Necessary? Not used in the other ones
//CyU3PUsbSendEP0Data(0, NULL); // Send ZLP since previous send has resulted in an integral # of packets
-
+
log_reset();
-
+
UNLOCK(g_log_lock);
-
+
//log_reset();
-
+
break;
}
case B200_VREQ_GET_COUNTERS: {
LOCK(g_counters_lock);
-
+
CyU3PUsbSendEP0Data(sizeof(COUNTERS), (uint8_t*)&g_counters);
-
+
counters_auto_reset();
-
+
UNLOCK(g_counters_lock);
-
+
//counters_auto_reset();
-
+
break;
}
-
+
case B200_VREQ_CLEAR_COUNTERS: {
CyU3PUsbAckSetup();
//CyU3PUsbGetEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer, &read_count); // Dummy
-
+
counters_dma_reset();
-
+
break;
}
@@ -1750,14 +1820,14 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
//msg("USB event log [1] %i", (int)len);
}
}
-
+
//if (len > 0) // Send a ZLP, otherwise it'll timeout
CyU3PUsbSendEP0Data(len, g_usb_event_log_contiguous_buf);
-
+
g_last_usb_event_log_index = idx;
break;
}
-
+
case B200_VREQ_SET_CONFIG: {
CyU3PUsbGetEP0Data(sizeof(CONFIG_MOD), (uint8_t*)g_vendor_req_buffer, &read_count);
if (read_count == sizeof(CONFIG_MOD)) {
@@ -1766,7 +1836,7 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
}
break;
}
-
+
case B200_VREQ_GET_CONFIG: {
CyU3PUsbSendEP0Data(sizeof(g_config), (uint8_t*)&g_config);
break;
@@ -1780,64 +1850,77 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {
for (i = 0; i < read_count; ++i)
sb_write(SUART_TXCHAR, g_vendor_req_buffer[i]);
UNLOCK(g_suart_lock);
-
+
msg("Wrote %d SB chars", read_count);
#else
msg("SB is disabled");
#endif // ENABLE_FPGA_SB
break;
}
-
+
case B200_VREQ_SET_SB_BAUD_DIV: {
uint16_t div;
CyU3PUsbGetEP0Data(sizeof(div), (uint8_t*)&div, &read_count);
-
+
if (read_count == sizeof(div)) {
#ifdef ENABLE_FPGA_SB
LOCK(g_suart_lock);
sb_write(SUART_CLKDIV, div);
UNLOCK(g_suart_lock);
msg("SUART_CLKDIV = %d", div);
- g_fpga_sb_uart_div = div; // Store for GPIF (FPGA) reset
+ /*g_fpga_sb_uart_div*/g_config.sb_baud_div = div; // Store for GPIF (FPGA) reset
#else
msg("SB is disabled");
#endif // ENABLE_FPGA_SB
}
else
msg("! SUART_CLKDIV received %d bytes", read_count);
-
+
break;
}
-
+
case B200_VREQ_FLUSH_DATA_EPS: {
//msg("Flushing data EPs...");
-
- CyU3PUsbAckSetup();
-
+
+ //CyU3PUsbAckSetup();
+
+ //CyU3PUsbResetEndpointMemories();
+
// From host
//CyU3PDmaChannelReset(&data_cons_to_prod_chan_handle);
//CyU3PUsbFlushEp(DATA_ENDPOINT_PRODUCER);
//CyU3PUsbResetEp(DATA_ENDPOINT_PRODUCER);
//CyU3PDmaChannelSetXfer(&data_cons_to_prod_chan_handle, DMA_SIZE_INFINITE);
-
+
+ //CyU3PDmaSocketDisable(DATA_RX_PPORT_SOCKET);
+
//CyU3PDmaChannelReset(&data_cons_to_prod_chan_handle);
- CyU3PDmaChannelReset(&data_prod_to_cons_chan_handle);
+ if (CyU3PDmaChannelReset(&data_prod_to_cons_chan_handle) != CY_U3P_SUCCESS)
+ {
+ msg("! CyU3PDmaChannelReset");
+ }
//CyU3PUsbFlushEp(DATA_ENDPOINT_PRODUCER);
CyU3PUsbFlushEp(DATA_ENDPOINT_CONSUMER);
//CyU3PUsbResetEp(DATA_ENDPOINT_PRODUCER);
- CyU3PUsbResetEp(DATA_ENDPOINT_CONSUMER);
+// CyU3PUsbResetEp(DATA_ENDPOINT_CONSUMER);
+ //CyU3PUsbStall(DATA_ENDPOINT_CONSUMER, CyFalse, CyTrue);
//CyU3PDmaChannelSetXfer(&data_cons_to_prod_chan_handle, DMA_SIZE_INFINITE);
+ //CyU3PDmaSocketEnable(DATA_RX_PPORT_SOCKET);
CyU3PDmaChannelSetXfer(&data_prod_to_cons_chan_handle, DMA_SIZE_INFINITE);
-
+
+ //CyU3PUsbResetEndpointMemories();
+
// To host
//CyU3PDmaChannelReset(&data_prod_to_cons_chan_handle);
//CyU3PUsbFlushEp(DATA_ENDPOINT_CONSUMER);
//CyU3PUsbResetEp(DATA_ENDPOINT_CONSUMER);
//CyU3PDmaChannelSetXfer(&data_prod_to_cons_chan_handle, DMA_SIZE_INFINITE);
-
+
+ CyU3PUsbAckSetup();
+
break;
}
-
+
case B200_VREQ_EEPROM_WRITE: {
i2cAddr = 0xA0 | ((wValue & 0x0007) << 1);
CyU3PUsbGetEP0Data(((wLength + 15) & 0xFFF0), g_vendor_req_buffer, NULL);
@@ -1941,6 +2024,97 @@ CyBool_t lpm_request_callback(CyU3PUsbLinkPowerMode link_mode) {
}
+/* Callback function to check for PIB ERROR*/
+void gpif_error_cb(CyU3PPibIntrType cbType, uint16_t cbArg)
+{
+ if (cbType==CYU3P_PIB_INTR_ERROR)
+ {
+ switch (CYU3P_GET_PIB_ERROR_TYPE(cbArg))
+ {
+ case CYU3P_PIB_ERR_NONE:
+ break;
+ case CYU3P_PIB_ERR_THR0_WR_OVERRUN:
+ msg("CYU3P_PIB_ERR_THR0_WR_OVERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR1_WR_OVERRUN:
+ msg("CYU3P_PIB_ERR_THR1_WR_OVERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR2_WR_OVERRUN:
+ msg("CYU3P_PIB_ERR_THR2_WR_OVERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR3_WR_OVERRUN:
+ msg("CYU3P_PIB_ERR_THR3_WR_OVERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR0_RD_UNDERRUN:
+ msg("CYU3P_PIB_ERR_THR0_RD_UNDERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR1_RD_UNDERRUN:
+ msg("CYU3P_PIB_ERR_THR1_RD_UNDERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR2_RD_UNDERRUN:
+ msg("CYU3P_PIB_ERR_THR2_RD_UNDERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR3_RD_UNDERRUN:
+ msg("CYU3P_PIB_ERR_THR3_RD_UNDERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR0_ADAP_UNDERRUN:
+ msg("CYU3P_PIB_ERR_THR0_ADAP_UNDERRUN");
+ break;
+ case CYU3P_PIB_ERR_THR1_ADAP_OVERRUN:
+ msg("CYU3P_PIB_ERR_THR1_ADAP_OVERRUN");
+ break;
+ // FIXME: Other threads
+ case CYU3P_PIB_ERR_THR1_SCK_INACTIVE:
+ //msg("CYU3P_PIB_ERR_THR1_SCK_INACTIVE");
+ ++g_counters.pib_counters[1].socket_inactive; // UNSYNC'd
+ break;
+ default:
+ msg("Unknown CYU3P_PIB_ERR %i", CYU3P_GET_PIB_ERROR_TYPE(cbArg));
+ break;
+ }
+
+ switch (CYU3P_GET_GPIF_ERROR_TYPE(cbArg))
+ {
+ case CYU3P_GPIF_ERR_NONE: /**< No GPIF state machine errors. */
+ //msg("CYU3P_GPIF_ERR_NONE");
+ break;
+ case CYU3P_GPIF_ERR_INADDR_OVERWRITE: /**< Content of INGRESS_ADDR register is overwritten before read. */
+ msg("CYU3P_GPIF_ERR_INADDR_OVERWRITE");
+ break;
+ case CYU3P_GPIF_ERR_EGADDR_INVALID: /**< Attempt to read EGRESS_ADDR register before it is written to. */
+ msg("CYU3P_GPIF_ERR_EGADDR_INVALID");
+ break;
+ case CYU3P_GPIF_ERR_DATA_READ_ERR: /**< Read from DMA data thread which is not ready. */
+ msg("CYU3P_GPIF_ERR_DATA_READ_ERR");
+ break;
+ case CYU3P_GPIF_ERR_DATA_WRITE_ERR: /**< Write to DMA data thread which is not ready. */
+ msg("CYU3P_GPIF_ERR_DATA_WRITE_ERR");
+ break;
+ case CYU3P_GPIF_ERR_ADDR_READ_ERR: /**< Read from DMA address thread which is not ready. */
+ msg("CYU3P_GPIF_ERR_ADDR_READ_ERR");
+ break;
+ case CYU3P_GPIF_ERR_ADDR_WRITE_ERR: /**< Write to DMA address thread which is not ready. */
+ msg("CYU3P_GPIF_ERR_ADDR_WRITE_ERR");
+ break;
+ case CYU3P_GPIF_ERR_INVALID_STATE: /**< GPIF state machine has reached an invalid state. */
+ //msg("CYU3P_GPIF_ERR_INVALID_STATE");
+ ++g_counters.invalid_gpif_state; // UNSYNC'd
+ break;
+ default:
+ msg("Unknown CYU3P_GPIF_ERR %i", CYU3P_GET_GPIF_ERROR_TYPE(cbArg));
+ break;
+ }
+ }
+}
+
+
+void GpifStateChangeCb(uint8_t stateId)
+{
+ //msg("%d", stateId);
+ ++g_counters.state_transition_count;
+}
+
+
/*! Initialize and start the GPIF state machine.
*
* This function starts the GPIF Slave FIFO state machine on the FX3. Because on
@@ -1948,7 +2122,7 @@ CyBool_t lpm_request_callback(CyU3PUsbLinkPowerMode link_mode) {
* after FPGA configuration is complete. */
void b200_gpif_init(void) {
msg("b200_gpif_init");
-
+
CyU3PPibClock_t pib_clock_config;
/* Initialize the p-port block; disable DLL for sync GPIF. */
@@ -1956,19 +2130,34 @@ void b200_gpif_init(void) {
pib_clock_config.clkSrc = CY_U3P_SYS_CLK;
pib_clock_config.isHalfDiv = CyFalse;
pib_clock_config.isDllEnable = CyFalse;
- CyU3PPibInit(CyTrue, &pib_clock_config);
+ if (CyU3PPibInit(CyTrue, &pib_clock_config) != CY_U3P_SUCCESS)
+ msg("! CyU3PPibInit");
/* Load the GPIF configuration for Slave FIFO sync mode. */
- CyU3PGpifLoad(&CyFxGpifConfig);
+ if (CyU3PGpifLoad(&CyFxGpifConfig) != CY_U3P_SUCCESS)
+ msg("! CyU3PGpifLoad");
+
+ msg("GPIF loaded");
+
+ //CyU3PGpifRegisterSMIntrCallback(GpifStateChangeCb);
/* Start the state machine. */
- CyU3PGpifSMStart(RESET, ALPHA_RESET);
+ //CyU3PGpifSMStart(RESET, ALPHA_RESET);
/* Configure the watermarks for the slfifo-write buffers. */
- CyU3PGpifSocketConfigure(0, DATA_TX_PPORT_SOCKET, 5, CyFalse, 1);
- CyU3PGpifSocketConfigure(1, DATA_RX_PPORT_SOCKET, 6, CyFalse, 1);
- CyU3PGpifSocketConfigure(2, CTRL_COMM_PPORT_SOCKET, 5, CyFalse, 1);
- CyU3PGpifSocketConfigure(3, CTRL_RESP_PPORT_SOCKET, 6, CyFalse, 1);
+ if (CyU3PGpifSocketConfigure(0, DATA_TX_PPORT_SOCKET, 5, CyFalse, 1) != CY_U3P_SUCCESS)
+ msg("! CyU3PGpifSocketConfigure 0");
+ if (CyU3PGpifSocketConfigure(1, DATA_RX_PPORT_SOCKET, 6, CyFalse, 1) != CY_U3P_SUCCESS)
+ msg("! CyU3PGpifSocketConfigure 1");
+ if (CyU3PGpifSocketConfigure(2, CTRL_COMM_PPORT_SOCKET, 5, CyFalse, 1) != CY_U3P_SUCCESS)
+ msg("! CyU3PGpifSocketConfigure 2");
+ if (CyU3PGpifSocketConfigure(3, CTRL_RESP_PPORT_SOCKET, 6, CyFalse, 1) != CY_U3P_SUCCESS)
+ msg("! CyU3PGpifSocketConfigure 3");
+
+ //CyU3PGpifSMStart(RESET, ALPHA_RESET);
+
+ /* Register a callback for notification of PIB interrupts*/
+ CyU3PPibRegisterCallback(gpif_error_cb, CYU3P_PIB_INTR_ERROR);
}
@@ -1979,7 +2168,7 @@ void b200_gpif_init(void) {
* 32-bit mode. */
CyU3PReturnStatus_t b200_spi_init(void) {
msg("b200_spi_init");
-
+
CyU3PSpiConfig_t spiConfig;
/* Start the SPI module and configure the master. */
@@ -2000,10 +2189,10 @@ CyU3PReturnStatus_t b200_spi_init(void) {
spiConfig.wordLen = 8;
CyU3PReturnStatus_t res = CyU3PSpiSetConfig(&spiConfig, NULL);
-
+
if (res != CY_U3P_SUCCESS)
msg("! CyU3PSpiSetConfig");
-
+
return res;
}
@@ -2015,7 +2204,7 @@ CyU3PReturnStatus_t b200_spi_init(void) {
*/
void b200_usb_init(void) {
//msg("b200_usb_init");
-
+
/* Initialize the I2C interface for the EEPROM of page size 64 bytes. */
CyFxI2cInit(CY_FX_USBI2C_I2C_PAGE_SIZE);
@@ -2137,48 +2326,53 @@ void b200_usb_init(void) {
CyU3PUsbSetDesc(CY_U3P_USB_SET_STRING_DESCR, 3,
(uint8_t *) dev_serial);
-
+
////////////////////////////////////////////////////////
// FIXME: CyU3PUsbSetTxDeemphasis(0x11); <0x1F // Shouldn't need to change this
- uint32_t tx_swing = /*65*/45; // 65 & 45 are OK, 120 causes much link recovery. <128. 1.2V is USB3 limit.
+ const uint32_t tx_swing = g_config.tx_swing/*65*//*45*/; // 65 & 45 are OK, 120 causes much link recovery. <128. 1.2V is USB3 limit.
if (CyU3PUsbSetTxSwing(tx_swing) == CY_U3P_SUCCESS)
- msg("CyU3PUsbSetTxSwing %d", tx_swing);
+ msg("CyU3PUsbSetTxSwing: %d", tx_swing);
else
- msg("! CyU3PUsbSetTxSwing %d", tx_swing);
+ msg("! CyU3PUsbSetTxSwing: %d", tx_swing);
////////////////////////////////////////////////////////
/* Connect the USB pins, and enable SuperSpeed (USB 3.0). */
- CyU3PConnectState(CyTrue, CyTrue); // connect, ssEnable
+ if (CyU3PConnectState(CyTrue, (g_config.enable_as_superspeed != 0 ? CyTrue : CyFalse)) == CY_U3P_SUCCESS) { // connect, ssEnable
+ CyU3PUSBSpeed_t usb_speed = CyU3PUsbGetSpeed();
+ msg("Link up (speed: USB %d)", (int)usb_speed); // MAGIC: Values happen to map
+ }
+ else
+ msg("! Failed to establish link");
}
void b200_restore_gpio_for_fpga_config(void) {
CyU3PDeviceGpioRestore(GPIO_FPGA_RESET);
CyU3PDeviceGpioRestore(GPIO_DONE);
-
+
CyU3PDeviceGpioRestore(GPIO_FX3_SCLK);
CyU3PDeviceGpioRestore(GPIO_FX3_CE);
CyU3PDeviceGpioRestore(GPIO_FX3_MISO);
CyU3PDeviceGpioRestore(GPIO_FX3_MOSI);
-
+
//CyU3PGpioDeInit(); // Moved to just before init
}
void thread_fpga_config_entry(uint32_t input) {
uint32_t event_flag;
-
+
//msg("thread_fpga_config_entry");
-
+
for(;;) {
-
+
// Event is set through VREQ
if(CyU3PEventGet(&g_event_usb_config, \
(EVENT_FPGA_CONFIG), CYU3P_EVENT_AND_CLEAR, \
&event_flag, CYU3P_WAIT_FOREVER) == CY_U3P_SUCCESS) {
-
+
//uint8_t old_state = g_fx3_state;
uint32_t old_fpga_programming_write_count = 0;
@@ -2200,7 +2394,7 @@ void thread_fpga_config_entry(uint32_t input) {
/* Configure the device GPIOs for FPGA programming. */
b200_gpios_pre_fpga_config();
-
+
CyU3PSysWatchDogClear();
/* Initialize the SPI module that will be used for FPGA programming. */
@@ -2213,7 +2407,7 @@ void thread_fpga_config_entry(uint32_t input) {
/* We can now begin configuring the FPGA. */
g_fx3_state = STATE_FPGA_READY;
-
+
msg("Begin FPGA");
// Event is set through VREQ
@@ -2232,7 +2426,7 @@ void thread_fpga_config_entry(uint32_t input) {
CyU3PThreadSleep(FPGA_PROGRAMMING_POLL_SLEEP);
CyU3PSysWatchDogClear();
}
-
+
if (wait_count >= FPGA_PROGRAMMING_BITSTREAM_START_POLL_COUNT)
continue;
@@ -2243,7 +2437,7 @@ void thread_fpga_config_entry(uint32_t input) {
/* Wait for INIT_B to fall and rise. */
wait_count = 0;
-
+
msg("Wait FPGA");
while(CyU3PEventGet(&g_event_usb_config, \
@@ -2282,9 +2476,9 @@ void thread_fpga_config_entry(uint32_t input) {
/* We are ready to accept the FPGA bitstream! */
wait_count = 0;
g_fx3_state = STATE_CONFIGURING_FPGA;
-
+
msg("Configuring FPGA");
-
+
// g_fpga_programming_write_count is zero'd by VREQ triggering EVENT_BITSTREAM_START
while(CyU3PEventGet(&g_event_usb_config, \
@@ -2308,7 +2502,7 @@ void thread_fpga_config_entry(uint32_t input) {
wait_count = 0;
old_fpga_programming_write_count = g_fpga_programming_write_count;
}
-
+
CyU3PThreadSleep(FPGA_PROGRAMMING_POLL_SLEEP);
CyU3PSysWatchDogClear();
}
@@ -2329,42 +2523,42 @@ void thread_fpga_config_entry(uint32_t input) {
#endif // ENABLE_DONE_WORKAROUND
if (wait_count >= FPGA_PROGRAMMING_DONE_POLL_COUNT)
continue;
-
+
msg("FPGA done");
-
+
/* Tell the host that we are ignoring it for a while. */
g_fx3_state = STATE_BUSY;
-
+
CyU3PSysWatchDogClear();
-
+
/* Now that the FPGA is configured, we need to tear down the current SPI and
* GPIO configs, and re-config for GPIF & bit-banged SPI operation. */
CyU3PSpiDeInit();
b200_restore_gpio_for_fpga_config();
-
+
CyU3PSysWatchDogClear();
-
+
/* Load the GPIO configuration for normal SLFIFO use. */
b200_slfifo_mode_gpio_config();
-
+
/* Tone down the drive strength on the P-port. */
//CyU3PSetPportDriveStrength(CY_U3P_DS_HALF_STRENGTH);
-
+
CyU3PSysWatchDogClear();
-
+
/* FPGA configuration is complete! Time to get the GPIF state machine
* running for Slave FIFO. */
b200_gpif_init();
-
+
CyU3PThreadSleep(1);
b200_start_fpga_sb_gpio(); // Moved here to give SB time to init
-
+
/* RUN, BABY, RUN! */
g_fx3_state = STATE_RUNNING;
-
+
msg("Running");
}
-
+
CyU3PThreadRelinquish();
}
}
@@ -2403,15 +2597,15 @@ void thread_main_app_entry(uint32_t input) {
while((current_state >= CyU3PUsbLPM_U1) \
&& (current_state <= CyU3PUsbLPM_U3)) {
-
+
msg("! LPS = %i", current_state);
CyU3PUsbSetLinkPowerState(CyU3PUsbLPM_U0); // This will wake up the host if it's trying to sleep
CyU3PThreadSleep(1);
-
+
if (CyU3PUsbGetSpeed () != CY_U3P_SUPER_SPEED)
break;
-
+
CyU3PUsbGetLinkPowerState (&current_state);
}
}
@@ -2426,12 +2620,12 @@ static uint32_t g_poll_last_phy_error_status = 0;
void update_error_counters(void) {
if (CyU3PUsbGetSpeed () != CY_U3P_SUPER_SPEED)
return;
-
+
uvint32_t reg = REG_LNK_PHY_ERROR_STATUS;
uint32_t val = 0;
if (CyU3PReadDeviceRegisters((uvint32_t*)reg, 1, &val) == CY_U3P_SUCCESS) {
g_poll_last_phy_error_status |= (val & PHYERR_MASK);
-
+
// Reset after read
uint32_t zero = PHYERR_MASK;
if (CyU3PWriteDeviceRegisters((uvint32_t*)reg, 1, &zero) != CY_U3P_SUCCESS)
@@ -2441,12 +2635,12 @@ void update_error_counters(void) {
// FIXME: Log once
msg("! Reg read fail");
}
-
+
// Equivalent code:
//uint32_t* p = (uint32_t*)REG_LNK_PHY_ERROR_STATUS;
//val = (*p);
//(*p) = PHYERR_MASK;
-
+
uint16_t phy_error_count = 0, link_error_count = 0;
if (CyU3PUsbGetErrorCounts(&phy_error_count, &link_error_count) == CY_U3P_SUCCESS) { // Resets internal counters after call
g_poll_last_phy_error_count += phy_error_count;
@@ -2456,7 +2650,7 @@ void update_error_counters(void) {
// FIXME: Log once
msg("! CyU3PUsbGetErrorCounts");
}
-
+
LOCK(g_counters_lock);
g_counters.usb_error_update_count++;
g_counters.usb_error_counters.phy_error_count += phy_error_count;
@@ -2478,50 +2672,153 @@ void update_error_counters(void) {
void thread_re_enum_entry(uint32_t input) {
uint32_t event_flag;
-
+
//msg("thread_re_enum_entry");
-
+
int keep_alive = 0;
-
+
while (1) {
if (CyU3PEventGet(&g_event_usb_config, \
(EVENT_RE_ENUM), CYU3P_EVENT_AND_CLEAR, \
&event_flag, RE_ENUM_THREAD_SLEEP_TIME) == CY_U3P_SUCCESS) {
msg("Re-config");
-
+
// FIXME: This section is not finished
-
+
// Not locking this since we only expect one write in VREQ and read afterward here
-
- int re_enum = g_config_mod.flags & (CF_RE_ENUM | CF_TX_SWING | CF_TX_DEEMPHASIS);
-
+
+ int re_enum = g_config_mod.flags & (CF_RE_ENUM | CF_TX_SWING | CF_TX_DEEMPHASIS | CF_DISABLE_USB2 | CF_ENABLE_AS_SUPERSPEED);
+
CyU3PThreadSleep(100); // Wait for EP0 xaction to complete
-
+
//b200_fw_stop();
-
+
+/*
+ int tx_swing; // [90] [65] 45
+ int tx_deemphasis; // 0x11
+ int disable_usb2; // 0
+ int enable_as_superspeed; // 1
+ int pport_drive_strength; // CY_U3P_DS_THREE_QUARTER_STRENGTH
+ int dma_buffer_size; // [USB3] (max)
+ int dma_buffer_count; // [USB3] 1
+ int manual_dma; // 0
+ int sb_baud_div; // 434*2
+*/
+
if (re_enum) {
- msg("Link down");
- CyU3PConnectState(CyFalse, CyTrue);
+ if (CyU3PConnectState(CyFalse, (g_config.enable_as_superspeed != 0 ? CyTrue : CyFalse)) == CY_U3P_SUCCESS)
+ msg("Link down");
+ else
+ msg("! Failed to bring link down");
}
-
+
if (g_config_mod.flags & CF_TX_DEEMPHASIS) {
- //g_config_mod.config.tx_deemphasis
- //CyU3PUsbSetTxDeemphasis(0x11); <0x1F
+#if (CYFX_VERSION_MAJOR >= 1) && (CYFX_VERSION_MINOR >= 3)
+ if ((g_config_mod.config.tx_deemphasis < 0x1F) && (CyU3PUsbSetTxDeemphasis(g_config_mod.config.tx_deemphasis) == CY_U3P_SUCCESS)) {
+ msg("TX deemphasis now: %d (was: %d)", g_config_mod.config.tx_deemphasis, g_config.tx_deemphasis);
+ g_config.tx_deemphasis = g_config_mod.config.tx_deemphasis;
+ }
+ else
+#endif // #if (CYFX_VERSION_MAJOR >= 1) && (CYFX_VERSION_MINOR >= 3)
+ msg("! Failed to set TX deemphasis: %d (still: %d)", g_config_mod.config.tx_deemphasis, g_config.tx_deemphasis);
}
+
if (g_config_mod.flags & CF_TX_SWING) {
- //CyU3PUsbSetTxSwing(90); <128
+ if ((g_config_mod.config.tx_swing < 128) && (CyU3PUsbSetTxSwing(g_config_mod.config.tx_swing) == CY_U3P_SUCCESS)) {
+ msg("TX swing now: %d (was: %d)", g_config_mod.config.tx_swing, g_config.tx_swing);
+ g_config.tx_swing = g_config_mod.config.tx_swing;
+ }
+ else
+ msg("! Failed to set TX swing: %d (still: %d)", g_config_mod.config.tx_swing, g_config.tx_swing);
+ }
+
+ if (g_config_mod.flags & CF_DISABLE_USB2) {
+ if (CyU3PUsbControlUsb2Support((g_config_mod.config.disable_usb2 != 0 ? CyTrue : CyFalse)) == CY_U3P_SUCCESS) {
+ msg("USB 2 support now: %s (was: %d)", (g_config_mod.config.disable_usb2 ? "disabled" : "enabled"), (g_config.disable_usb2 ? "disabled" : "enabled"));
+ g_config.disable_usb2 = g_config_mod.config.disable_usb2;
+ }
+ else
+ msg("! Failed to change USB 2 support to: %s (still: %s)", (g_config_mod.config.disable_usb2 ? "enabled" : "disabled"), (g_config.disable_usb2 ? "enabled" : "disabled"));
+ }
+
+ if (g_config_mod.flags & CF_PPORT_DRIVE_STRENGTH) {
+ // CY_U3P_DS_QUARTER_STRENGTH,CY_U3P_DS_HALF_STRENGTH,CY_U3P_DS_THREE_QUARTER_STRENGTH,CY_U3P_DS_FULL_STRENGTH
+ if ((g_config_mod.config.pport_drive_strength >= CY_U3P_DS_QUARTER_STRENGTH) &&
+ (g_config_mod.config.pport_drive_strength <= CY_U3P_DS_FULL_STRENGTH) &&
+ (CyU3PSetPportDriveStrength(g_config_mod.config.pport_drive_strength) == CY_U3P_SUCCESS)) {
+ msg("PPort drive strength now: %d (was: %d)", g_config_mod.config.pport_drive_strength, g_config.pport_drive_strength);
+ g_config.pport_drive_strength = g_config_mod.config.pport_drive_strength;
+ }
+ else
+ msg("! Failed to set PPort drive strength: %d (still: %d)", g_config_mod.config.pport_drive_strength, g_config.pport_drive_strength);
+ }
+
+ int reinit_dma = g_config_mod.flags & (CF_MANUAL_DMA | CF_DMA_BUFFER_COUNT | CF_DMA_BUFFER_SIZE);
+ if (re_enum)
+ reinit_dma = 0; // Don't need to if re-enumerating
+
+ if (g_config_mod.flags & CF_MANUAL_DMA) {
+#ifdef ENABLE_MANUAL_DMA_XFER
+ msg("DMA transfers will be: %s (was: %s)", (g_config_mod.config.manual_dma ? "manual" : "auto"), (g_config.manual_dma ? "manual" : "auto"));
+ g_config.manual_dma = g_config_mod.config.manual_dma;
+#else
+ msg("! Manual DMA transfers not compiled into FW");
+#endif // ENABLE_MANUAL_DMA_XFER
+ }
+
+ if (g_config_mod.flags & CF_DMA_BUFFER_COUNT) {
+ msg("DMA buffer count will be: %d (was: %d)", g_config_mod.config.dma_buffer_count, g_config.dma_buffer_count);
+ g_config.dma_buffer_count = g_config_mod.config.dma_buffer_count;
+ }
+
+ if (g_config_mod.flags & CF_DMA_BUFFER_SIZE) {
+ msg("DMA buffer size will be: %d (was: %d)", g_config_mod.config.dma_buffer_size, g_config.dma_buffer_size);
+ g_config.dma_buffer_size = g_config_mod.config.dma_buffer_size;
+ }
+
+ if (g_config_mod.flags & CF_SB_BAUD_DIV) {
+#ifdef ENABLE_FPGA_SB
+ LOCK(g_suart_lock);
+ sb_write(SUART_CLKDIV, g_config_mod.config.sb_baud_div);
+ UNLOCK(g_suart_lock);
+ msg("SUART_CLKDIV now: %d (was: %d)", g_config_mod.config.sb_baud_div, g_config.sb_baud_div);
+ g_config.sb_baud_div = g_config_mod.config.sb_baud_div;
+#else
+ msg("! Failed to set SUART_CLKDIV: SB is disabled (still: %d)", g_config.sb_baud_div);
+#endif // ENABLE_FPGA_SB
}
- //CyU3PUsbControlUsb2Support();
-
//b200_fw_start()
+ if (g_config_mod.flags & CF_ENABLE_AS_SUPERSPEED) {
+ msg("Enable SuperSpeed: %s (was: %s)", (g_config_mod.config.enable_as_superspeed ? "yes" : "no"), (g_config.enable_as_superspeed ? "yes" : "no"));
+ g_config.enable_as_superspeed = g_config_mod.config.enable_as_superspeed;
+ }
+
+ if (reinit_dma) {
+ if (g_app_running) {
+ msg("Stopping FW...");
+
+ b200_fw_stop();
+ }
+
+ msg("Starting FW...");
+
+ b200_fw_start();
+ }
+ else // Shouldn't be re-init'ing AND re-enum'ing
/* Connect the USB pins, and enable SuperSpeed (USB 3.0). */
if (re_enum) {
- msg("Link up");
- CyU3PConnectState(CyTrue, CyTrue); // CHECK: Assuming all other important state will persist
+ msg("Connecting... (as SuperSpeed: %d)", g_config.enable_as_superspeed);
+
+ if (CyU3PConnectState(CyTrue, (g_config.enable_as_superspeed != 0 ? CyTrue : CyFalse)) == CY_U3P_SUCCESS) { // CHECK: Assuming all other important state will persist
+ CyU3PUSBSpeed_t usb_speed = CyU3PUsbGetSpeed();
+ msg("Link up (speed: USB %d)", (int)usb_speed); // MAGIC: Values happen to map
+ }
+ else
+ msg("! Failed to bring link up");
}
-
+
counters_reset_usb_errors();
}
else {
@@ -2533,7 +2830,7 @@ void thread_re_enum_entry(uint32_t input) {
update_error_counters();
#endif // !ENABLE_FPGA_SB
}
-
+
CyU3PThreadRelinquish();
}
}
@@ -2548,26 +2845,26 @@ void base16_encode(uint8_t v, char out[2], char first) {
#ifdef ENABLE_FPGA_SB
void thread_fpga_sb_poll_entry(uint32_t input) {
//msg("thread_fpga_sb_poll_entry");
-
+
while (1) {
uint16_t i;
uint8_t has_change = 0;
-
+
update_error_counters();
-
+
/*if (g_poll_last_phy_error_count > 0)
has_change = 1;
if (g_poll_last_link_error_count > 0)
has_change = 1;*/
if (g_poll_last_phy_error_status != 0)
has_change = 1;
-
+
uint16_t idx = CyU3PUsbGetEventLogIndex(); // Current *write* pointer
if (idx > (USB_EVENT_LOG_SIZE-1)) {
msg("! USB event log idx = %i", (int)idx);
break;
}
-
+
uint8_t has_usb_events = 0;
// Assuming logging won't wrap around between get calls (i.e. buffer should be long enough)
if (g_fpga_sb_last_usb_event_log_index != idx) {
@@ -2578,7 +2875,7 @@ void thread_fpga_sb_poll_entry(uint32_t input) {
break;
}
}
-
+
if (has_usb_events == 0) {
for (i = 0; i < idx; i++) {
if (g_usb_event_log[i] != 0x14 && g_usb_event_log[i] != 0x15 && g_usb_event_log[i] != 0x16) { // CTRL, STATUS, ACKSETUP
@@ -2597,15 +2894,15 @@ void thread_fpga_sb_poll_entry(uint32_t input) {
}
}
}
-
+
if (has_change || has_usb_events) {
LOCK(g_suart_lock);
-
+
sb_write(SUART_TXCHAR, UPT_USB_EVENTS);
-
+
char out[3];
out[2] = '\0';
-
+
if (has_usb_events) {
if (idx < g_fpga_sb_last_usb_event_log_index) {
for (i = g_fpga_sb_last_usb_event_log_index; i < USB_EVENT_LOG_SIZE; i++) {
@@ -2614,7 +2911,7 @@ void thread_fpga_sb_poll_entry(uint32_t input) {
base16_encode(g_usb_event_log[i], out, 'A');
_sb_write_string(out);
}
-
+
for (i = 0; i < idx; i++) {
if (g_usb_event_log[i] == 0x14 || g_usb_event_log[i] == 0x15 || g_usb_event_log[i] == 0x16) // CTRL, STATUS, ACKSETUP
continue;
@@ -2631,10 +2928,10 @@ void thread_fpga_sb_poll_entry(uint32_t input) {
}
}
}
-
+
// USB events: A-P,A-P
// PHY error status: a,a-i
-
+
if (g_poll_last_phy_error_status != 0) {
uint32_t mask;
size_t offset;
@@ -2645,32 +2942,32 @@ void thread_fpga_sb_poll_entry(uint32_t input) {
}
}
}
-
+
/*char buf[6];
-
+
if (g_poll_last_phy_error_count > 0) {
sb_write(SUART_TXCHAR, 'b');
snprintf(buf, sizeof(buf)-1, "%d", g_poll_last_phy_error_count);
_sb_write_string(buf);
}
-
+
if (g_poll_last_link_error_count > 0) {
sb_write(SUART_TXCHAR, 'c');
snprintf(buf, sizeof(buf)-1, "%d", g_poll_last_link_error_count);
_sb_write_string(buf);
}*/
-
+
_sb_write_string("\r\n");
-
+
UNLOCK(g_suart_lock);
}
-
+
g_poll_last_phy_error_count = 0;
g_poll_last_link_error_count = 0;
g_poll_last_phy_error_status = 0;
-
+
g_fpga_sb_last_usb_event_log_index = idx;
-
+
CyU3PThreadRelinquish();
}
}
@@ -2692,10 +2989,10 @@ void CyFxApplicationDefine(void) {
#ifdef ENABLE_FPGA_SB
void *fpga_sb_poll_thread_ptr;
#endif // ENABLE_FPGA_SB
-
+
g_counters.magic = COUNTER_MAGIC;
- memset(&g_config, 0xFF, sizeof(g_config)); // Initialise to -1
-
+ //memset(&g_config, 0xFF, sizeof(g_config)); // Initialise to -1
+
CyU3PMutexCreate(&g_log_lock, CYU3P_NO_INHERIT);
CyU3PMutexCreate(&g_counters_lock, CYU3P_NO_INHERIT);
CyU3PMutexCreate(&g_counters_dma_from_host_lock, CYU3P_NO_INHERIT);
@@ -2706,36 +3003,37 @@ void CyFxApplicationDefine(void) {
#ifdef ENABLE_USB_EVENT_LOGGING
CyU3PUsbInitEventLog(g_usb_event_log, USB_EVENT_LOG_SIZE);
#endif // ENABLE_USB_EVENT_LOGGING
-
+
////////////////////////////////////////////////////////
-
+
/* Tell the host that we are ignoring it for a while. */
g_fx3_state = STATE_BUSY;
-
+
/* Set the FX3 compatibility number. */
compat_num[0] = FX3_COMPAT_MAJOR;
compat_num[1] = FX3_COMPAT_MINOR;
-
+
/* Initialize the USB system. */
b200_usb_init();
-
+
/* Turn on the Watchdog Timer. */
CyU3PSysWatchDogConfigure(CyTrue, WATCHDOG_TIMEOUT);
-
+
/* Go do something. Probably not useful, because you aren't configured. */
g_fx3_state = STATE_UNCONFIGURED;
-
+
////////////////////////////////////////////////////////
-
+
b200_gpio_init(CyTrue);
-
+
b200_enable_fpga_sb_gpio(CyTrue);
-
+
msg("Compat: %d.%d", FX3_COMPAT_MAJOR, FX3_COMPAT_MINOR);
msg("FX3 SDK: %d.%d.%d (build %d)", CYFX_VERSION_MAJOR, CYFX_VERSION_MINOR, CYFX_VERSION_PATCH, CYFX_VERSION_BUILD);
-
+ msg("FW built: %s %s", __TIME__, __DATE__);
+
////////////////////////////////////////////////////////
-
+
/* Create the USB event group that we will use to track USB events from the
* application thread. */
CyU3PEventCreate(&g_event_usb_config);
@@ -2838,14 +3136,14 @@ int main(void) {
status = CyU3PDeviceCacheControl(CyTrue, CyFalse, CyFalse); // Icache, Dcache, DMAcache
if (status != CY_U3P_SUCCESS)
goto handle_fatal_error;
-
+
/* Configure the IO peripherals on the FX3. The gpioSimpleEn arrays are
* bitmaps, where each bit represents the GPIO of the matching index - the
* second array is index + 32. */
status = b200_set_io_matrix(CyTrue);
if(status != CY_U3P_SUCCESS)
goto handle_fatal_error;
-
+
/* This function calls starts the RTOS kernel.
*
* ABANDON ALL HOPE, YE WHO ENTER HERE */
diff --git a/firmware/fx3/b200/b200_main.h b/firmware/fx3/b200/b200_main.h
index 61048abc9..9fe8b9511 100644
--- a/firmware/fx3/b200/b200_main.h
+++ b/firmware/fx3/b200/b200_main.h
@@ -10,7 +10,7 @@
#include "cyu3types.h"
#include "cyu3usbconst.h"
-#define FX3_COMPAT_MAJOR (uint8_t)(7)
+#define FX3_COMPAT_MAJOR (uint8_t)(8)
#define FX3_COMPAT_MINOR (uint8_t)(0)
/* GPIO Pins */
diff --git a/firmware/fx3/b200/b200_usb_descriptors.c b/firmware/fx3/b200/b200_usb_descriptors.c
index 03dbce74a..53979219b 100644
--- a/firmware/fx3/b200/b200_usb_descriptors.c
+++ b/firmware/fx3/b200/b200_usb_descriptors.c
@@ -1,5 +1,5 @@
//
-// Copyright 2013-2014 Ettus Research LLC
+// Copyright 2013-2015 Ettus Research LLC
//
/* Define the USB 2.0 and USB 3.0 enumeration descriptions for the USRP B200
@@ -303,7 +303,7 @@ const uint8_t b200_usb_ss_config_desc[] __attribute__ ((aligned (32))) =
0x6A,0x00, /* Length of this descriptor and all sub descriptors */
0x05, /* Number of interfaces */
0x01, /* Configuration number */
- 0x00, /* COnfiguration string index */
+ 0x00, /* Configuration string index */
0x80, /* Config characteristics - D6: Self power; D5: Remote wakeup */
0x01, /* Lie about the max power consumption (in 8mA unit) : 8mA */
@@ -424,6 +424,102 @@ const uint8_t b200_usb_ss_config_desc[] __attribute__ ((aligned (32))) =
};
+const uint8_t b200_usb_ss_config_desc_new[] __attribute__ ((aligned (32))) =
+{
+ /* Configuration descriptor */
+ 0x09, /* Descriptor size */
+ CY_U3P_USB_CONFIG_DESCR, /* Configuration descriptor type */
+ 0x4F,0x00, /* Length of this descriptor and all sub descriptors */
+ 0x02, /* Number of interfaces */
+ 0x01, /* Configuration number */
+ 0x00, /* COnfiguration string index */
+ 0x80, /* Config characteristics - D6: Self power; D5: Remote wakeup */
+ 0x01, /* Lie about the max power consumption (in 8mA unit) : 8mA */
+
+ /* Interface descriptor */
+ 0x09, /* Descriptor size */
+ CY_U3P_USB_INTRFC_DESCR, /* Interface Descriptor type */
+ 0x00, /* Interface number */
+ 0x00, /* Alternate setting number */
+ 0x00, /* Number of end points */
+ 0xFF, /* Interface class */
+ 0x00, /* Interface sub class */
+ 0x00, /* Interface protocol code */
+ 0x02, /* Interface descriptor string index */
+
+ /* Interface descriptor */
+ 0x09, /* Descriptor size */
+ CY_U3P_USB_INTRFC_DESCR, /* Interface Descriptor type */
+ 0x01, /* Interface number */
+ 0x00, /* Alternate setting number */
+ 0x04, /* Number of end points */
+ 0xFF, /* Interface class */
+ 0x00, /* Interface sub class */
+ 0x00, /* Interface protocol code */
+ 0x02, /* Interface descriptor string index */
+
+ /* Endpoint descriptor for producer EP */
+ 0x07, /* Descriptor size */
+ CY_U3P_USB_ENDPNT_DESCR, /* Endpoint descriptor type */
+ DATA_ENDPOINT_PRODUCER, /* Endpoint address and description */
+ CY_U3P_USB_EP_BULK, /* Bulk endpoint type */
+ 0x00,0x04, /* Max packet size = 1024 bytes */
+ 0x00, /* Servicing interval for data transfers : 0 for bulk */
+
+ /* Super speed endpoint companion descriptor for producer EP */
+ 0x06, /* Descriptor size */
+ CY_U3P_SS_EP_COMPN_DESCR, /* SS endpoint companion descriptor type */
+ (USB3_PACKETS_PER_BURST - 1), /* Max no. of packets in a burst : 0: burst 1 packet at a time */
+ 0x00, /* Max streams for bulk EP = 0 (No streams) */
+ 0x00,0x00, /* Service interval for the EP : 0 for bulk */
+
+ /* Endpoint descriptor for consumer EP */
+ 0x07, /* Descriptor size */
+ CY_U3P_USB_ENDPNT_DESCR, /* Endpoint descriptor type */
+ DATA_ENDPOINT_CONSUMER, /* Endpoint address and description */
+ CY_U3P_USB_EP_BULK, /* Bulk endpoint type */
+ 0x00,0x04, /* Max packet size = 1024 bytes */
+ 0x00, /* Servicing interval for data transfers : 0 for Bulk */
+
+ /* Super speed endpoint companion descriptor for consumer EP */
+ 0x06, /* Descriptor size */
+ CY_U3P_SS_EP_COMPN_DESCR, /* SS endpoint companion descriptor type */
+ (USB3_PACKETS_PER_BURST - 1), /* Max no. of packets in a burst : 0: burst 1 packet at a time */
+ 0x00, /* Max streams for bulk EP = 0 (No streams) */
+ 0x00,0x00, /* Service interval for the EP : 0 for bulk */
+
+ /* Endpoint descriptor for producer EP */
+ 0x07, /* Descriptor size */
+ CY_U3P_USB_ENDPNT_DESCR, /* Endpoint descriptor type */
+ CTRL_ENDPOINT_PRODUCER, /* Endpoint address and description */
+ CY_U3P_USB_EP_BULK, /* Bulk endpoint type */
+ 0x00,0x04, /* Max packet size = 1024 bytes */
+ 0x00, /* Servicing interval for data transfers : 0 for bulk */
+
+ /* Super speed endpoint companion descriptor for producer EP */
+ 0x06, /* Descriptor size */
+ CY_U3P_SS_EP_COMPN_DESCR, /* SS endpoint companion descriptor type */
+ (USB3_PACKETS_PER_BURST - 1), /* Max no. of packets in a burst : 0: burst 1 packet at a time */
+ 0x00, /* Max streams for bulk EP = 0 (No streams) */
+ 0x00,0x00, /* Service interval for the EP : 0 for bulk */
+
+ /* Endpoint descriptor for consumer EP */
+ 0x07, /* Descriptor size */
+ CY_U3P_USB_ENDPNT_DESCR, /* Endpoint descriptor type */
+ CTRL_ENDPOINT_CONSUMER, /* Endpoint address and description */
+ CY_U3P_USB_EP_BULK, /* Bulk endpoint type */
+ 0x00,0x04, /* Max packet size = 1024 bytes */
+ 0x00, /* Servicing interval for data transfers : 0 for Bulk */
+
+ /* Super speed endpoint companion descriptor for consumer EP */
+ 0x06, /* Descriptor size */
+ CY_U3P_SS_EP_COMPN_DESCR, /* SS endpoint companion descriptor type */
+ (USB3_PACKETS_PER_BURST - 1), /* Max no. of packets in a burst : 0: burst 1 packet at a time */
+ 0x00, /* Max streams for bulk EP = 0 (No streams) */
+ 0x00,0x00 /* Service interval for the EP : 0 for bulk */
+};
+
+
/* Standard Language ID String Descriptor */
const uint8_t b200_string_lang_id_desc[] __attribute__ ((aligned (32))) =
{
diff --git a/firmware/octoclock/CMakeLists.txt b/firmware/octoclock/CMakeLists.txt
index 80df0e9eb..0f2af35e9 100644
--- a/firmware/octoclock/CMakeLists.txt
+++ b/firmware/octoclock/CMakeLists.txt
@@ -31,7 +31,7 @@ if(NOT DEFINED PROGRAMMER)
endif(NOT DEFINED PROGRAMMER)
if(OCTOCLOCK_DEBUG)
- message(STATUS "Debug enabled. Interrupts will be disabled.")
+ message(STATUS "Debug enabled.")
add_definitions(-DDEBUG)
endif(OCTOCLOCK_DEBUG)
diff --git a/firmware/octoclock/bootloader/CMakeLists.txt b/firmware/octoclock/bootloader/CMakeLists.txt
index 04bcfc492..7623a8698 100644
--- a/firmware/octoclock/bootloader/CMakeLists.txt
+++ b/firmware/octoclock/bootloader/CMakeLists.txt
@@ -49,7 +49,7 @@ add_custom_target(
add_custom_target(
upload_bootloader
- ${AVRDUDE} -p atmega128 -c ${PROGRAMMER} -P usb -U efuse:w:0xFF:m -U hfuse:w:0x80:m -U lfuse:w:0xFF:m -U flash:w:octoclock_bootloader.hex:i
+ ${AVRDUDE} -p atmega128 -c ${PROGRAMMER} -P usb -U efuse:w:0xFF:m -U hfuse:w:0x80:m -U lfuse:w:0xEF:m -U flash:w:octoclock_bootloader.hex:i
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS octoclock_bootloader_hex
COMMENT "Uploading OctoClock bootloader to device with ${PROGRAMMER}"
diff --git a/firmware/octoclock/bootloader/main.c b/firmware/octoclock/bootloader/main.c
index 5e2e6f17e..09f740d31 100644
--- a/firmware/octoclock/bootloader/main.c
+++ b/firmware/octoclock/bootloader/main.c
@@ -23,13 +23,13 @@
#include <avr/eeprom.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
+#include <avr/wdt.h>
+#include <avrlibdefs.h>
#include <octoclock.h>
#include <debug.h>
#include <network.h>
-#include <util/delay.h>
-
#include <net/enc28j60.h>
#include "octoclock/common.h"
@@ -40,10 +40,19 @@
*/
#define TIME_PASSED (TCNT1 > (TIMER1_ONE_SECOND*5) || (TIFR & _BV(TOV1)))
-//States
-static bool received_cmd = false;
-static bool done_burning = false;
+/*
+ * States
+ */
+static bool received_cmd = false; // Received "PREPARE_FW_BURN_CMD" signal
+static bool done_burning = false; // Received "FINALIZE_BURNING_CMD" signal
+static bool app_checked = false; // Ran validation check on firmware
+/*
+ * After new firmware is burned onto the device, the bootloader calculates its
+ * CRC and burns it into the EEPROM. When the device boots, this CRC is used
+ * to validate the firmware before loading it. This struct represents how the
+ * information is stored in the EEPROM.
+ */
typedef struct {
uint16_t fw_len;
uint16_t fw_crc;
@@ -51,15 +60,22 @@ typedef struct {
static crc_info_t crc_info;
+/*
+ * What actually burns the firmware onto the device.
+ *
+ * Source: http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__boot.html
+ */
static void boot_program_page(uint8_t *buf, uint16_t page){
- uint16_t i;
+ // Disable interrupts
+ uint8_t sreg = SREG;
+ cli();
eeprom_busy_wait();
boot_page_erase(page);
boot_spm_busy_wait(); // Wait until the memory is erased.
- for(i = 0; i < SPM_PAGESIZE; i += 2){
+ for(uint16_t i = 0; i < SPM_PAGESIZE; i += 2){
// Set up little-endian word.
uint16_t w = *buf++;
w += ((*buf++) << 8);
@@ -68,36 +84,31 @@ static void boot_program_page(uint8_t *buf, uint16_t page){
}
boot_page_write(page); // Store buffer in flash page.
- boot_spm_busy_wait(); // Wait until the memory is written.
+ boot_spm_busy_wait(); // Wait until the memory is written.
// Reenable RWW-section again. We need this if we want to jump back
// to the application after bootloading.
boot_rww_enable();
+
+ // Restore interrupt state
+ SREG = sreg;
+ sei();
}
+/*
+ * Load firmware at given address into packet to send to host.
+ */
static void read_firmware(uint16_t addr, octoclock_packet_t *pkt_out){
for(size_t i = 0; i < SPM_PAGESIZE; i++){
pkt_out->data[i] = pgm_read_byte(addr+i);
}
}
-void handle_udp_query_packet(
- struct socket_address src, struct socket_address dst,
- unsigned char *payload, int payload_len
-){
- const octoclock_packet_t *pkt_in = (octoclock_packet_t*)payload;
-
- //Respond to query packets
- if(pkt_in->code == OCTOCLOCK_QUERY_CMD){
- octoclock_packet_t pkt_out;
- pkt_out.proto_ver = OCTOCLOCK_BOOTLOADER_PROTO_VER;
- pkt_out.sequence = pkt_in->sequence;
- pkt_out.code = OCTOCLOCK_QUERY_ACK;
- pkt_out.len = 0;
- send_udp_pkt(OCTOCLOCK_UDP_CTRL_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t));
- }
-}
-
+/*
+ * Calculate the CRC of the current firmware.
+ *
+ * Adapted from _crc16_update in <util/crc16.h>.
+ */
static void calculate_crc(uint16_t *crc, uint16_t len){
*crc = 0xFFFF;
@@ -110,6 +121,11 @@ static void calculate_crc(uint16_t *crc, uint16_t len){
}
}
+/*
+ * Calculate the CRC of the current firmware. If it matches the
+ * CRC burned into the EEPROM, the firmware is considered valid,
+ * and the bootloader can load it.
+ */
static bool valid_app(){
crc_info_t crc_eeprom_info;
eeprom_read_block(&crc_eeprom_info, (void*)OCTOCLOCK_EEPROM_APP_LEN, 4);
@@ -118,6 +134,26 @@ static bool valid_app(){
return (crc_info.fw_crc == crc_eeprom_info.fw_crc);
}
+/*
+ * UDP handlers
+ */
+void handle_udp_query_packet(
+ struct socket_address src, struct socket_address dst,
+ unsigned char *payload, int payload_len
+){
+ const octoclock_packet_t *pkt_in = (octoclock_packet_t*)payload;
+
+ // Respond to uhd::device::find(), identify as bootloader
+ if(pkt_in->code == OCTOCLOCK_QUERY_CMD){
+ octoclock_packet_t pkt_out;
+ pkt_out.proto_ver = OCTOCLOCK_BOOTLOADER_PROTO_VER;
+ pkt_out.sequence = pkt_in->sequence;
+ pkt_out.code = OCTOCLOCK_QUERY_ACK;
+ pkt_out.len = 0;
+ send_udp_pkt(OCTOCLOCK_UDP_CTRL_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t));
+ }
+}
+
void handle_udp_fw_packet(
struct socket_address src, struct socket_address dst,
unsigned char *payload, int payload_len
@@ -132,24 +168,27 @@ void handle_udp_fw_packet(
case PREPARE_FW_BURN_CMD:
received_cmd = true;
done_burning = false;
+ crc_info.fw_crc = pkt_in->crc;
crc_info.fw_len = pkt_in->len;
pkt_out.code = FW_BURN_READY_ACK;
break;
+ // Burn firmware sent from the host
case FILE_TRANSFER_CMD:
boot_program_page(pkt_in->data, pkt_in->addr);
pkt_out.code = FILE_TRANSFER_ACK;
+ pkt_out.addr = pkt_in->addr;
break;
+ // Send firmware back to the host for verification
case READ_FW_CMD:
pkt_out.code = READ_FW_ACK;
read_firmware(pkt_in->addr, &pkt_out);
break;
+ // Calculate the CRC of the new firmware and finish
case FINALIZE_BURNING_CMD:
- //With stuff verified, burn CRC info into EEPROM
done_burning = true;
- calculate_crc(&(crc_info.fw_crc), crc_info.fw_len);
eeprom_write_block(&crc_info, (void*)OCTOCLOCK_EEPROM_APP_LEN, 4);
pkt_out.code = FINALIZE_BURNING_ACK;
break;
@@ -170,11 +209,12 @@ void handle_udp_eeprom_packet(
pkt_out.sequence = pkt_in->sequence;
pkt_out.len = 0;
+ // Restore OctoClock's EEPROM to factory state
if(pkt_in->proto_ver == OCTOCLOCK_FW_COMPAT_NUM){
switch(pkt_in->code){
case CLEAR_EEPROM_CMD:
received_cmd = true;
- uint8_t blank_eeprom[103];
+ uint8_t blank_eeprom[103]; // 103 is offset of CRC info
memset(blank_eeprom, 0xFF, 103);
eeprom_write_block(blank_eeprom, 0, 103);
pkt_out.code = CLEAR_EEPROM_ACK;
@@ -189,28 +229,45 @@ void handle_udp_eeprom_packet(
int main(void){
- asm("cli");
+ // Disable watchdog timer
+ wdt_disable();
+
+ // Give interrupts to bootloader
+ MCUCR = (1<<IVCE);
+ MCUCR = (1<<IVSEL);
+ cli();
- //Initialization
+ // Atmega128
setup_atmel_io_ports();
+
+ // Start timer
+ TIMER1_INIT();
+
+ // Ethernet stack
network_init();
- init_udp_listeners();
register_udp_listener(OCTOCLOCK_UDP_CTRL_PORT, handle_udp_query_packet);
register_udp_listener(OCTOCLOCK_UDP_FW_PORT, handle_udp_fw_packet);
register_udp_listener(OCTOCLOCK_UDP_EEPROM_PORT, handle_udp_eeprom_packet);
- //Turn LED's on to show we're in the bootloader
+ // Turn LED's on to show we're in the bootloader
PORTC |= 0x20;
PORTC |= (0x20<<1);
PORTC |= (0x20<<2);
- TIMER1_INIT();
- bool app_checked = false;
-
+ /*
+ * This loop determines whether the OctoClock will remain in its bootloader
+ * state or if it will load the main firmware. After five seconds, it will
+ * check to see if valid firmware is installed. If so, it will immediately
+ * load it. Otherwise, it will remain here until firmware is installed.
+ *
+ * This process can be stopped by an instruction from the firmware burner
+ * utility, at which point the OctoClock will remain in bootloader state until
+ * instructed by the utility to exit the loop and load the new firmware.
+ */
while(true){
if(done_burning){
if(valid_app()) break;
- else done_burning = false; //Burning somehow failed and wasn't caught
+ else done_burning = false; // Burning somehow failed and wasn't caught
}
if(!app_checked && !received_cmd && TIME_PASSED){
app_checked = true;
@@ -220,16 +277,18 @@ int main(void){
network_check();
}
- //Turn LED's off before moving to application
+ // Turn LED's off before moving to application
PORTC &= ~0x20;
PORTC &= ~(0x20<<1);
PORTC &= ~(0x20<<2);
/*
- * Whether the bootloader reaches here through five seconds of inactivity
- * or after a firmware burn just finished, it can be assumed that the application
- * is valid.
+ * At this point, the bootloader has determined that there is valid
+ * firmware installed on the device and that it is OK to load it.
*/
+ TIMER1_DISABLE();
+ MCUCR = (1<<IVCE);
+ MCUCR = 0;
+ cli();
asm("jmp 0000");
- return 0; //Will never get here, but AVR-GCC needs it
}
diff --git a/firmware/octoclock/include/clkdist.h b/firmware/octoclock/include/clkdist.h
index 633df9ddf..357daf37b 100644
--- a/firmware/octoclock/include/clkdist.h
+++ b/firmware/octoclock/include/clkdist.h
@@ -23,7 +23,7 @@
#include <octoclock.h>
typedef enum {
- Reg0, Reg1, Reg2, Reg3, Reg4, Reg5, Reg6, Reg7,
+ Reg0=0, Reg1, Reg2, Reg3, Reg4, Reg5, Reg6, Reg7,
Reg8_Status_Control,
Read_Command=0xE,
RAM_EEPROM_Unlock=0x1F,
@@ -46,6 +46,8 @@ void reset_TI_CDCE18005(void);
uint32_t get_TI_CDCE18005(CDCE18005 which_register);
+void set_TI_CDCE18005(CDCE18005 which_register, uint32_t bits);
+
bool check_TI_CDCE18005(TI_Input_10_MHz which_input, CDCE18005 which_register);
#endif /* _CLKDIST_H_ */
diff --git a/firmware/octoclock/include/debug.h b/firmware/octoclock/include/debug.h
index ee0618bc6..1f69896f0 100644
--- a/firmware/octoclock/include/debug.h
+++ b/firmware/octoclock/include/debug.h
@@ -66,8 +66,8 @@
DEBUG_LOG_HEX(((uint8_t*)&num)[0]);
#define DEBUG_LOG_INT(num) DEBUG_LOG_HEX_NNL(((uint8_t*)&num)[3]); \
- DEBUG_LOG_HEX(((uint8_t*)&num)[2]); \
- DEBUG_LOG_HEX(((uint8_t*)&num)[1]); \
+ DEBUG_LOG_HEX_NNL(((uint8_t*)&num)[2]); \
+ DEBUG_LOG_HEX_NNL(((uint8_t*)&num)[1]); \
DEBUG_LOG_HEX(((uint8_t*)&num)[0]);
#else
diff --git a/firmware/octoclock/include/gpsdo.h b/firmware/octoclock/include/gpsdo.h
index fc7d87324..df0440404 100644
--- a/firmware/octoclock/include/gpsdo.h
+++ b/firmware/octoclock/include/gpsdo.h
@@ -27,6 +27,4 @@ gpsdo_cache_state_t gpsdo_state;
void send_gpsdo_cmd(char* buf, uint8_t size);
-void process_gpsdo_output(void);
-
#endif /* _GPSDO_H_ */
diff --git a/firmware/octoclock/include/net/enc28j60.h b/firmware/octoclock/include/net/enc28j60.h
index 463303f3c..dc58b451b 100644
--- a/firmware/octoclock/include/net/enc28j60.h
+++ b/firmware/octoclock/include/net/enc28j60.h
@@ -1,299 +1,276 @@
-/*! \file enc28j60.h \brief Microchip ENC28J60 Ethernet Interface Driver. */
-//*****************************************************************************
-//
-// File Name : 'enc28j60.h'
-// Title : Microchip ENC28J60 Ethernet Interface Driver
-// Author : Pascal Stang (c)2005
-// Created : 9/22/2005
-// Revised : 9/22/2005
-// Version : 0.1
-// Target MCU : Atmel AVR series
-// Editor Tabs : 4
-//
-/// \ingroup network
-/// \defgroup enc28j60 Microchip ENC28J60 Ethernet Interface Driver (enc28j60.c)
-/// \code #include "net/enc28j60.h" \endcode
-/// \par Overview
-/// This driver provides initialization and transmit/receive
-/// functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY.
-/// This chip is novel in that it is a full MAC+PHY interface all in a 28-pin
-/// chip, using an SPI interface to the host processor.
-///
-//
-//*****************************************************************************
-//@{
+/*
+ * Copyright 2015 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
-#ifndef ENC28J60_H
-#define ENC28J60_H
+#ifndef _NET_ENC28J60_H_
+#define _NET_ENC28J60_H_
-#include <avrlibdefs.h>
+#include <avr/io.h>
-#include "enc28j60conf.h"
+#define SPI_DDR DDRB
+#define SPI_PORT PORTB
+#define SPI_CS 0
+#define SPI_MOSI 2
+#define SPI_MISO 3
+#define SPI_SCK 1
-// ENC28J60 Control Registers
-// Control register definitions are a combination of address,
-// bank number, and Ethernet/MAC/PHY indicator bits.
-// - Register address (bits 0-4)
-// - Bank number (bits 5-6)
-// - MAC/PHY indicator (bit 7)
-#define ADDR_MASK 0x1F
-#define BANK_MASK 0x60
-#define SPRD_MASK 0x80
-// All-bank registers
-#define EIE 0x1B
-#define EIR 0x1C
-#define ESTAT 0x1D
-#define ECON2 0x1E
-#define ECON1 0x1F
-// Bank 0 registers
-#define ERDPTL (0x00|0x00)
-#define ERDPTH (0x01|0x00)
-#define EWRPTL (0x02|0x00)
-#define EWRPTH (0x03|0x00)
-#define ETXSTL (0x04|0x00)
-#define ETXSTH (0x05|0x00)
-#define ETXNDL (0x06|0x00)
-#define ETXNDH (0x07|0x00)
-#define ERXSTL (0x08|0x00)
-#define ERXSTH (0x09|0x00)
-#define ERXNDL (0x0A|0x00)
-#define ERXNDH (0x0B|0x00)
-#define ERXRDPTL (0x0C|0x00)
-#define ERXRDPTH (0x0D|0x00)
-#define ERXWRPTL (0x0E|0x00)
-#define ERXWRPTH (0x0F|0x00)
-#define EDMASTL (0x10|0x00)
-#define EDMASTH (0x11|0x00)
-#define EDMANDL (0x12|0x00)
-#define EDMANDH (0x13|0x00)
-#define EDMADSTL (0x14|0x00)
-#define EDMADSTH (0x15|0x00)
-#define EDMACSL (0x16|0x00)
-#define EDMACSH (0x17|0x00)
-// Bank 1 registers
-#define EHT0 (0x00|0x20)
-#define EHT1 (0x01|0x20)
-#define EHT2 (0x02|0x20)
-#define EHT3 (0x03|0x20)
-#define EHT4 (0x04|0x20)
-#define EHT5 (0x05|0x20)
-#define EHT6 (0x06|0x20)
-#define EHT7 (0x07|0x20)
-#define EPMM0 (0x08|0x20)
-#define EPMM1 (0x09|0x20)
-#define EPMM2 (0x0A|0x20)
-#define EPMM3 (0x0B|0x20)
-#define EPMM4 (0x0C|0x20)
-#define EPMM5 (0x0D|0x20)
-#define EPMM6 (0x0E|0x20)
-#define EPMM7 (0x0F|0x20)
-#define EPMCSL (0x10|0x20)
-#define EPMCSH (0x11|0x20)
-#define EPMOL (0x14|0x20)
-#define EPMOH (0x15|0x20)
-#define EWOLIE (0x16|0x20)
-#define EWOLIR (0x17|0x20)
-#define ERXFCON (0x18|0x20)
-#define EPKTCNT (0x19|0x20)
-// Bank 2 registers
-#define MACON1 (0x00|0x40|0x80)
-#define MACON2 (0x01|0x40|0x80)
-#define MACON3 (0x02|0x40|0x80)
-#define MACON4 (0x03|0x40|0x80)
-#define MABBIPG (0x04|0x40|0x80)
-#define MAIPGL (0x06|0x40|0x80)
-#define MAIPGH (0x07|0x40|0x80)
-#define MACLCON1 (0x08|0x40|0x80)
-#define MACLCON2 (0x09|0x40|0x80)
-#define MAMXFLL (0x0A|0x40|0x80)
-#define MAMXFLH (0x0B|0x40|0x80)
-#define MAPHSUP (0x0D|0x40|0x80)
-#define MICON (0x11|0x40|0x80)
-#define MICMD (0x12|0x40|0x80)
-#define MIREGADR (0x14|0x40|0x80)
-#define MIWRL (0x16|0x40|0x80)
-#define MIWRH (0x17|0x40|0x80)
-#define MIRDL (0x18|0x40|0x80)
-#define MIRDH (0x19|0x40|0x80)
-// Bank 3 registers
-#define MAADR1 (0x00|0x60|0x80)
-#define MAADR0 (0x01|0x60|0x80)
-#define MAADR3 (0x02|0x60|0x80)
-#define MAADR2 (0x03|0x60|0x80)
-#define MAADR5 (0x04|0x60|0x80)
-#define MAADR4 (0x05|0x60|0x80)
-#define EBSTSD (0x06|0x60)
-#define EBSTCON (0x07|0x60)
-#define EBSTCSL (0x08|0x60)
-#define EBSTCSH (0x09|0x60)
-#define MISTAT (0x0A|0x60|0x80)
-#define EREVID (0x12|0x60)
-#define ECOCON (0x15|0x60)
-#define EFLOCON (0x17|0x60)
-#define EPAUSL (0x18|0x60)
-#define EPAUSH (0x19|0x60)
-// PHY registers
-#define PHCON1 0x00
-#define PHSTAT1 0x01
-#define PHHID1 0x02
-#define PHHID2 0x03
-#define PHCON2 0x10
-#define PHSTAT2 0x11
-#define PHIE 0x12
-#define PHIR 0x13
-#define PHLCON 0x14
+// Register Masks
+#define ADDR_MASK 0x1F
+#define BANK_MASK 0x60
+#define SPRD_MASK 0x80
-// ENC28J60 EIE Register Bit Definitions
-#define EIE_INTIE 0x80
-#define EIE_PKTIE 0x40
-#define EIE_DMAIE 0x20
-#define EIE_LINKIE 0x10
-#define EIE_TXIE 0x08
-#define EIE_WOLIE 0x04
-#define EIE_TXERIE 0x02
-#define EIE_RXERIE 0x01
-// ENC28J60 EIR Register Bit Definitions
-#define EIR_PKTIF 0x40
-#define EIR_DMAIF 0x20
-#define EIR_LINKIF 0x10
-#define EIR_TXIF 0x08
-#define EIR_WOLIF 0x04
-#define EIR_TXERIF 0x02
-#define EIR_RXERIF 0x01
-// ENC28J60 ESTAT Register Bit Definitions
-#define ESTAT_INT 0x80
-#define ESTAT_LATECOL 0x10
-#define ESTAT_RXBUSY 0x04
-#define ESTAT_TXABRT 0x02
-#define ESTAT_CLKRDY 0x01
-// ENC28J60 ECON2 Register Bit Definitions
-#define ECON2_AUTOINC 0x80
-#define ECON2_PKTDEC 0x40
-#define ECON2_PWRSV 0x20
-#define ECON2_VRPS 0x08
-// ENC28J60 ECON1 Register Bit Definitions
-#define ECON1_TXRST 0x80
-#define ECON1_RXRST 0x40
-#define ECON1_DMAST 0x20
-#define ECON1_CSUMEN 0x10
-#define ECON1_TXRTS 0x08
-#define ECON1_RXEN 0x04
-#define ECON1_BSEL1 0x02
-#define ECON1_BSEL0 0x01
-// ENC28J60 MACON1 Register Bit Definitions
-#define MACON1_LOOPBK 0x10
-#define MACON1_TXPAUS 0x08
-#define MACON1_RXPAUS 0x04
-#define MACON1_PASSALL 0x02
-#define MACON1_MARXEN 0x01
-// ENC28J60 MACON2 Register Bit Definitions
-#define MACON2_MARST 0x80
-#define MACON2_RNDRST 0x40
-#define MACON2_MARXRST 0x08
-#define MACON2_RFUNRST 0x04
-#define MACON2_MATXRST 0x02
-#define MACON2_TFUNRST 0x01
-// ENC28J60 MACON3 Register Bit Definitions
-#define MACON3_PADCFG2 0x80
-#define MACON3_PADCFG1 0x40
-#define MACON3_PADCFG0 0x20
-#define MACON3_TXCRCEN 0x10
-#define MACON3_PHDRLEN 0x08
-#define MACON3_HFRMLEN 0x04
-#define MACON3_FRMLNEN 0x02
-#define MACON3_FULDPX 0x01
-// ENC28J60 MICMD Register Bit Definitions
-#define MICMD_MIISCAN 0x02
-#define MICMD_MIIRD 0x01
-// ENC28J60 MISTAT Register Bit Definitions
-#define MISTAT_NVALID 0x04
-#define MISTAT_SCAN 0x02
-#define MISTAT_BUSY 0x01
-// ENC28J60 PHY PHCON1 Register Bit Definitions
-#define PHCON1_PRST 0x8000
-#define PHCON1_PLOOPBK 0x4000
-#define PHCON1_PPWRSV 0x0800
-#define PHCON1_PDPXMD 0x0100
-// ENC28J60 PHY PHSTAT1 Register Bit Definitions
-#define PHSTAT1_PFDPX 0x1000
-#define PHSTAT1_PHDPX 0x0800
-#define PHSTAT1_LLSTAT 0x0004
-#define PHSTAT1_JBSTAT 0x0002
-// ENC28J60 PHY PHCON2 Register Bit Definitions
-#define PHCON2_FRCLINK 0x4000
-#define PHCON2_TXDIS 0x2000
-#define PHCON2_JABBER 0x0400
-#define PHCON2_HDLDIS 0x0100
+// All Banks Registers
+#define EIE 0x1B
+#define EIR 0x1C
+#define ESTAT 0x1D
+#define ECON2 0x1E
+#define ECON1 0x1F
-// ENC28J60 Packet Control Byte Bit Definitions
-#define PKTCTRL_PHUGEEN 0x08
-#define PKTCTRL_PPADEN 0x04
-#define PKTCTRL_PCRCEN 0x02
-#define PKTCTRL_POVERRIDE 0x01
+// Bank 0 Registers
+#define ERDPTL 0x00
+#define ERDPTH 0x01
+#define EWRPTL 0x02
+#define EWRPTH 0x03
+#define ETXSTL 0x04
+#define ETXSTH 0x05
+#define ETXNDL 0x06
+#define ETXNDH 0x07
+#define ERXSTL 0x08
+#define ERXSTH 0x09
+#define ERXNDL 0x0A
+#define ERXNDH 0x0B
+#define ERXRDPTL 0x0C
+#define ERXRDPTH 0x0D
+#define ERXWRPTL 0x0E
+#define ERXWRPTH 0x0F
+#define EDMASTL 0x10
+#define EDMASTH 0x11
+#define EDMANDL 0x12
+#define EDMANDH 0x13
+#define EDMADSTL 0x14
+#define EDMADSTH 0x15
+#define EDMACSL 0x16
+#define EDMACSH 0x17
-// SPI operation codes
-#define ENC28J60_READ_CTRL_REG 0x00
-#define ENC28J60_READ_BUF_MEM 0x3A
-#define ENC28J60_WRITE_CTRL_REG 0x40
-#define ENC28J60_WRITE_BUF_MEM 0x7A
-#define ENC28J60_BIT_FIELD_SET 0x80
-#define ENC28J60_BIT_FIELD_CLR 0xA0
-#define ENC28J60_SOFT_RESET 0xFF
+// Bank 1 Registers
+#define EHT0 0x20
+#define EHT1 0x21
+#define EHT2 0x22
+#define EHT3 0x23
+#define EHT4 0x24
+#define EHT5 0x25
+#define EHT6 0x26
+#define EHT7 0x27
+#define EPMM0 0x28
+#define EPMM1 0x29
+#define EPMM2 0x2A
+#define EPMM3 0x2B
+#define EPMM4 0x2C
+#define EPMM5 0x2D
+#define EPMM6 0x2E
+#define EPMM7 0x2F
+#define EPMCSL 0x30
+#define EPMCSH 0x31
+#define EPMOL 0x34
+#define EPMOH 0x35
+#define EWOLIE 0x36
+#define EWOLIR 0x37
+#define ERXFCON 0x38
+#define EPKTCNT 0x39
+// Bank 2 Register
+#define MACON1 0xC0
+#define MACON2 0xC1
+#define MACON3 0xC2
+#define MACON4 0xC3
+#define MABBIPG 0xC4
+#define MAIPGL 0xC6
+#define MAIPGH 0xC7
+#define MACLCON1 0xC8
+#define MACLCON2 0xC9
+#define MAMXFLL 0xCA
+#define MAMXFLH 0xCB
+#define MAPHSUP 0xCD
+#define MICON 0xD1
+#define MICMD 0xD2
+#define MIREGADR 0xD4
+#define MIWRL 0xD6
+#define MIWRH 0xD7
+#define MIRDL 0xD8
+#define MIRDH 0xD9
-// buffer boundaries applied to internal 8K ram
-// entire available packet buffer space is allocated
-#define TXSTART_INIT 0x0000 // start TX buffer at 0
-#define RXSTART_INIT 0x0600 // give TX buffer space for one full ethernet frame (~1500 bytes)
-#define RXSTOP_INIT 0x1FFF // receive buffer gets the rest
+// Bank 3 Registers
+#define MAADR1 0xE0
+#define MAADR0 0xE1
+#define MAADR3 0xE2
+#define MAADR2 0xE3
+#define MAADR5 0xE4
+#define MAADR4 0xE5
+#define EBSTSD 0x66
+#define EBSTCON 0x67
+#define EBSTCSL 0x68
+#define EBSTCSH 0x69
+#define MISTAT 0xEA
+#define EREVID 0x72
+#define ECOCON 0x75
+#define EFLOCON 0x77
+#define EPAUSL 0x78
+#define EPAUSH 0x79
-#define MAX_FRAMELEN 1518 // maximum ethernet frame length
+// PHY Registers
+#define PHCON1 0x00
+#define PHSTAT1 0x01
+#define PHHID1 0x02
+#define PHHID2 0x03
+#define PHCON2 0x10
+#define PHSTAT2 0x11
+#define PHIE 0x12
+#define PHIR 0x13
+#define PHLCON 0x14
-// Ethernet constants
-#define ETHERNET_MIN_PACKET_LENGTH 0x3C
-//#define ETHERNET_HEADER_LENGTH 0x0E
+// ERXFCON bit definitions
+#define UCEN 0x80
+#define ANDOR 0x40
+#define CRCEN 0x20
+#define PMEN 0x10
+#define MPEN 0x08
+#define HTEN 0x04
+#define MCEN 0x02
+#define BCEN 0x01
-// setup ports for I/O
-//void ax88796SetupPorts(void);
+// EIE bit definitions
+#define INTIE 0x80
+#define PKTIE 0x40
+#define DMAIE 0x20
+#define LINKIE 0x10
+#define TXIE 0x08
+#define WOLIE 0x04
+#define TXERIE 0x02
+#define RXERIE 0x01
-//! do a ENC28J60 read operation
-u08 enc28j60ReadOp(u08 op, u08 address);
-//! do a ENC28J60 write operation
-void enc28j60WriteOp(u08 op, u08 address, u08 data);
-//! read the packet buffer memory
-void enc28j60ReadBuffer(u16 len, u08* data);
-//! write the packet buffer memory
-void enc28j60WriteBuffer(u16 len, u08* data);
-//! set the register bank for register at address
-void enc28j60SetBank(u08 address);
-//! read ax88796 register
-u08 enc28j60Read(u08 address);
-//! write ax88796 register
-void enc28j60Write(u08 address, u08 data);
-//! read a PHY register
-u16 enc28j60PhyRead(u08 address);
-//! write a PHY register
-void enc28j60PhyWrite(u08 address, u16 data);
+// EIR bit definitions
+#define PKTIF 0x40
+#define DMAIF 0x20
+#define LINKIF 0x10
+#define TXIF 0x08
+#define WOLIF 0x04
+#define TXERIF 0x02
+#define RXERIF 0x01
-//! initialize the ethernet interface for transmit/receive
-void enc28j60Init(u08* macaddr);
+// ESTAT bit definitions
+#define INT 0x80
+#define LATECOL 0x10
+#define RXBUSY 0x04
+#define TXABRT 0x02
+#define CLKRDY 0x01
-//! Packet transmit function.
-/// Sends a packet on the network. It is assumed that the packet is headed by a valid ethernet header.
-/// \param len Length of packet in bytes.
-/// \param packet Pointer to packet data.
-/// \param len2 Length of the secound packet in bytes, can be 0.
-/// \param packet2 Pointer to the secound packet data, can be NULL.
-void enc28j60PacketSend(unsigned int len1, unsigned char* packet1, unsigned int len2, unsigned char* packet2);
+// ECON2 bit definitions
+#define AUTOINC 0x80
+#define PKTDEC 0x40
+#define PWRSV 0x20
+#define VRPS 0x08
-//! Packet receive function.
-/// Gets a packet from the network receive buffer, if one is available.
-/// The packet will by headed by an ethernet header.
-/// \param maxlen The maximum acceptable length of a retrieved packet.
-/// \param buf Pointer to buffer.
-/// \return Packet length in bytes if a packet was retrieved, zero otherwise.
-unsigned int enc28j60PacketReceive(unsigned int maxlen, u08* buf);
+// ECON1 bit definitions
+#define TXRST 0x80
+#define RXRST 0x40
+#define DMAST 0x20
+#define CSUMEN 0x10
+#define TXRTS 0x08
+#define ENCRXEN 0x04
+#define BSEL1 0x02
+#define BSEL0 0x01
-#endif
-//@}
+// MACON1 bit definitions
+#define LOOPBK 0x10
+#define TXPAUS 0x08
+#define RXPAUS 0x04
+#define PASSALL 0x02
+#define MARXEN 0x01
+// MACON2 bit definitions
+#define MARST 0x80
+#define RNDRST 0x40
+#define MARXRST 0x08
+#define RFUNRST 0x04
+#define MATXRST 0x02
+#define TFUNRST 0x01
+
+// MACON3 bit definitions
+#define PADCFG2 0x80
+#define PADCFG1 0x40
+#define PADCFG0 0x20
+#define TXCRCEN 0x10
+#define PHDRLEN 0x08
+#define HFRMLEN 0x04
+#define FRMLNEN 0x02
+#define FULDPX 0x01
+
+// MICMD bit definitions
+#define MIISCAN 0x02
+#define MIIRD 0x01
+
+// MISTAT bit definitions
+#define NVALID 0x04
+#define SCAN 0x02
+#define BUSY 0x01
+
+// PHCON1 bit definitions
+#define PRST 0x8000
+#define PLOOPBK 0x4000
+#define PPWRSV 0x0800
+#define PDPXMD 0x0100
+
+// PHSTAT1 bit definitions
+#define PFDPX 0x1000
+#define PHDPX 0x0800
+#define LLSTAT 0x0004
+#define JBSTAT 0x0002
+
+// PHCON2 bit definitions
+#define FRCLINK 0x4000
+#define TXDIS 0x2000
+#define JABBER 0x0400
+#define HDLDIS 0x0100
+
+// Packet Control bit Definitions
+#define PHUGEEN 0x08
+#define PPADEN 0x04
+#define PCRCEN 0x02
+#define POVERRIDE 0x01
+
+// SPI Instruction Set
+#define RCR 0x00 // Read Control Register
+#define RBM 0x3A // Read Buffer Memory
+#define WCR 0x40 // Write Control Register
+#define WBM 0x7A // Write Buffer Memory
+#define BFS 0x80 // Bit Field Set
+#define BFC 0xA0 // Bit Field Clear
+#define SC 0xFF // Soft Reset
+
+// Buffer
+#define RXSTART_INIT 0x0000
+#define RXSTOP_INIT (0x1FFF-0x0600-1)
+#define TXSTART_INIT (0x1FFF-0x0600)
+#define TXSTOP_INIT 0x1FFF
+#define MAX_FRAMELEN 1500
+
+void enc28j60_init(uint8_t* mac_addr);
+
+uint16_t enc28j60_recv(uint8_t* buffer, uint16_t max_len);
+
+void enc28j60_send(uint8_t* buffer, uint16_t len);
+
+#endif /* _NET_ENC28J60_H_ */
diff --git a/firmware/octoclock/include/net/enc28j60conf.h b/firmware/octoclock/include/net/enc28j60conf.h
deleted file mode 100644
index 0acf5473c..000000000
--- a/firmware/octoclock/include/net/enc28j60conf.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*! \file enc28j60conf.h \brief Microchip ENC28J60 Ethernet Interface Driver Configuration. */
-//*****************************************************************************
-//
-// File Name : 'enc28j60conf.h'
-// Title : Microchip ENC28J60 Ethernet Interface Driver Configuration
-// Author : Pascal Stang
-// Created : 10/5/2004
-// Revised : 8/22/2005
-// Version : 0.1
-// Target MCU : Atmel AVR series
-// Editor Tabs : 4
-//
-// Description : This driver provides initialization and transmit/receive
-// functions for the ENC28J60 10Mb Ethernet Controller and PHY.
-//
-// This code is distributed under the GNU Public License
-// which can be found at http://www.gnu.org/licenses/gpl.txt
-//
-//*****************************************************************************
-
-#ifndef ENC28J60CONF_H
-#define ENC28J60CONF_H
-
-#include <stdint.h>
-typedef uint8_t u08;
-typedef uint16_t u16;
-typedef uint32_t u32;
-
-// ENC28J60 SPI port
-#define ENC28J60_SPI_PORT PORTB
-#define ENC28J60_SPI_DDR DDRB
-#define ENC28J60_SPI_SCK PORTB1
-#define ENC28J60_SPI_MOSI PORTB2
-#define ENC28J60_SPI_MISO PORTB3
-#define ENC28J60_SPI_SS PORTB0
-// ENC28J60 control port
-#define ENC28J60_CONTROL_PORT PORTB
-#define ENC28J60_CONTROL_DDR DDRB
-#define ENC28J60_CONTROL_CS PORTB0
-
-// MAC address for this interface
-#define ENC28J60_MAC0 '0'
-#define ENC28J60_MAC1 'F'
-#define ENC28J60_MAC2 'F'
-#define ENC28J60_MAC3 'I'
-#define ENC28J60_MAC4 'C'
-#define ENC28J60_MAC5 'E'
-
-#endif /* ENC28J60CONF_H */
diff --git a/firmware/octoclock/include/net/eth_mac_addr.h b/firmware/octoclock/include/net/eth_mac_addr.h
index 0c790aa4f..78986bf04 100644
--- a/firmware/octoclock/include/net/eth_mac_addr.h
+++ b/firmware/octoclock/include/net/eth_mac_addr.h
@@ -21,11 +21,8 @@
#include <stdint.h>
// Ethernet MAC address
-
-#pragma pack(push,1)
typedef struct {
uint8_t addr[6];
-} eth_mac_addr_t;
-#pragma pack(pop)
+} eth_mac_addr_t __attribute__((aligned(1)));
#endif /* INCLUDED_ETH_MAC_ADDR_H */
diff --git a/firmware/octoclock/include/network.h b/firmware/octoclock/include/network.h
index 83e398bc5..6d126a197 100644
--- a/firmware/octoclock/include/network.h
+++ b/firmware/octoclock/include/network.h
@@ -69,17 +69,11 @@
#define _IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (_IPH_TTL(hdr) << 8)))
#define _IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
-bool using_network_defaults;
+volatile bool using_network_defaults;
// Ethernet I/O buffers
-uint8_t buf_in[512];
-uint8_t buf_out[512];
-
-// Default values loaded if EEPROM is incomplete
-static const uint32_t blank_eeprom_ip = _IP(255,255,255,255);
-static const uint32_t default_ip = _IP(192,168,10,3);
-static const uint32_t default_dr = _IP(192,168,10,1);
-static const uint32_t default_netmask = _IP(255,255,255,0);
+#define ETH_BUF_SIZE 512
+uint8_t eth_buf[ETH_BUF_SIZE];
typedef void (*udp_receiver_t)(struct socket_address src, struct socket_address dst,
unsigned char *payload, int payload_len);
diff --git a/firmware/octoclock/include/octoclock.h b/firmware/octoclock/include/octoclock.h
index 849ab7f96..34cad1c12 100644
--- a/firmware/octoclock/include/octoclock.h
+++ b/firmware/octoclock/include/octoclock.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Ettus Research LLC
+ * Copyright 2014-2015 Ettus Research LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,26 +24,21 @@
#include <stdint.h>
// Define frequency
-#define F_CPU 12500000UL
+#define F_CPU 7372800UL
/*
- * Timer 0 (8-bit)
- * * Set prescaler to 8
- * * Enable overflow interrupt
- * * Set timer to 0
- */
-#define TIMER0_INIT() TCCR0 = (1 << CS01); \
- TIMSK |= (1 << TOIE0); \
- TCNT0 = 0;
-/*
* Timer 1 (16-bit)
* * Set prescaler to 1024
* * Enable overflow interrupt
* * Set timer to 0
*/
#define TIMER1_INIT() TCCR1B = (1 << CS12) | (1 << CS10); \
- TIMSK |= (1<<TOIE1); \
- TCNT1 = 0;
+ TIMSK |= (1<<TOIE1); \
+ TCNT1 = 0;
+
+#define TIMER1_DISABLE() TCCR1B = 0; \
+ TIMSK = 0; \
+ TCNT1 = 0;
#define TIMER1_ONE_SECOND ((uint32_t)(12207))
@@ -94,12 +89,6 @@
* Bits_32(10000000,11111111,10101010,01010101) = 2164238933
*/
-typedef enum {
- Top,
- Middle,
- Bottom
-} LEDs;
-
void setup_atmel_io_ports(void);
#endif /* _OCTOCLOCK_H_ */
diff --git a/firmware/octoclock/include/state.h b/firmware/octoclock/include/state.h
index 9734948cf..2170c2638 100644
--- a/firmware/octoclock/include/state.h
+++ b/firmware/octoclock/include/state.h
@@ -22,23 +22,24 @@
#include <octoclock.h>
-// NOT PRESENT unless proven so...
-static ref_t global_which_ref = NO_REF;
-static bool global_gps_present = false;
-static bool global_ext_ref_is_present = false;
+// Global state variables
+extern volatile bool g_ext_ref_present;
+extern volatile bool g_gps_present;
+extern volatile switch_pos_t g_switch_pos;
+extern volatile ref_t g_ref;
-void led(LEDs which, int turn_it_on);
+typedef enum {
+ LED_TOP, // Internal
+ LED_MIDDLE, // External
+ LED_BOTTOM // Status
+} led_t;
-void LEDs_off(void);
+void led(led_t which, bool on);
-void force_internal(void);
+void leds_off(void);
void prefer_internal(void);
void prefer_external(void);
-ref_t which_ref(void);
-
-switch_pos_t get_switch_pos(void);
-
#endif /* _STATE_H_ */
diff --git a/firmware/octoclock/include/usart.h b/firmware/octoclock/include/usart.h
index 35ee9eb95..203255988 100644
--- a/firmware/octoclock/include/usart.h
+++ b/firmware/octoclock/include/usart.h
@@ -25,10 +25,6 @@ void usart_init(void);
char usart_getc(void);
-char usart_getc_noblock(void);
-
void usart_putc(char ch);
-void usart_putc_nowait(char ch);
-
#endif /* _USART_H_ */
diff --git a/firmware/octoclock/lib/clkdist.c b/firmware/octoclock/lib/clkdist.c
index ed29510b6..0468ac38e 100644
--- a/firmware/octoclock/lib/clkdist.c
+++ b/firmware/octoclock/lib/clkdist.c
@@ -21,6 +21,8 @@
#include <clkdist.h>
#include <state.h>
+#include <util/delay.h>
+
#define wait() for(uint16_t u=14000; u; u--) asm("nop");
#define CLK (PA0) // Shift by 0 bits
@@ -33,7 +35,7 @@
// Table of 32-bit constants to be written to the TI chip's registers. These are
// from the "Special Settings" on Page 35 of the datasheet.
// For the GPS's 10 MHz output
-static uint32_t table_Pri_Ref[] = {
+static const uint32_t table_Pri_Ref[] = {
Bits_32(1,01010100,0,0), // Reg 0
Bits_32(1,01010100,0,0), // Outputs LVCMOS Positive&Negative Active - Non-inverted
Bits_32(1,01010100,0,0),
@@ -47,7 +49,7 @@ static uint32_t table_Pri_Ref[] = {
// For the External 10 MHz input LVDS with external termination,
// Effectively DC coupled
-static uint32_t table_Sec_Ref[] = {
+static const uint32_t table_Sec_Ref[] = {
Bits_32(0001,01010100,0,100000), // Reg 0 -- use Secondary Reference for all channels
Bits_32(0001,01010100,0,100000), // Outputs LVCMOS Positive&Negative Active - Non-inverted
Bits_32(0001,01010100,0,100000),
@@ -81,7 +83,6 @@ static bool get_bit(uint8_t bit_number) {
// Send 32 bits to TI chip, LSB first.
// Don't worry about reading any bits back at this time
static void send_SPI(uint32_t bits) {
-
// Basically, when the clock is low, one can set MOSI to anything, as it's
// ignored.
set_bit(CE_, Lo); // Start SPI transaction with TI chip
@@ -130,7 +131,8 @@ void setup_TI_CDCE18005(TI_Input_10_MHz which_input) {
for(uint8_t i=0; i<table_size; i++){
temp = table_Pri_Ref[i]<<4;
temp |= i;
- send_SPI(temp); // Make sure the register's address is in the LSBs
+ // Make sure the register's address is in the LSBs
+ send_SPI(temp);
}
} else {
// is Secondary_Ext -- External 10 MHz input from SMA connector
@@ -169,6 +171,10 @@ uint32_t get_TI_CDCE18005(CDCE18005 which_register){
return receive_SPI();
}
+void set_TI_CDCE18005(CDCE18005 which_register, uint32_t bits){
+ send_SPI((bits << 4) | which_register);
+}
+
bool check_TI_CDCE18005(TI_Input_10_MHz which_input,
CDCE18005 which_register) {
diff --git a/firmware/octoclock/lib/enc28j60.c b/firmware/octoclock/lib/enc28j60.c
index f0bbee0e7..ead7e4ec8 100644
--- a/firmware/octoclock/lib/enc28j60.c
+++ b/firmware/octoclock/lib/enc28j60.c
@@ -1,337 +1,211 @@
-/*! \file enc28j60.c \brief Microchip ENC28J60 Ethernet Interface Driver. */
-//*****************************************************************************
-//
-// File Name : 'enc28j60.c'
-// Title : Microchip ENC28J60 Ethernet Interface Driver
-// Author : Pascal Stang (c)2005
-// Created : 9/22/2005
-// Revised : 5/19/2014
-// Version : 0.1
-// Target MCU : Atmel AVR series
-// Editor Tabs : 4
-//
-// Description : This driver provides initialization and transmit/receive
-// functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY.
-// This chip is novel in that it is a full MAC+PHY interface all in a 28-pin
-// chip, using an SPI interface to the host processor.
-//
-//*****************************************************************************
+/*
+ * Copyright 2015 Ettus Research LLC
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
#include <octoclock.h>
#include <net/enc28j60.h>
-#include <net/enc28j60conf.h>
-#include <avr/io.h>
#include <util/delay.h>
-u08 Enc28j60Bank;
-u16 NextPacketPtr;
-
-u08 enc28j60ReadOp(u08 op, u08 address)
-{
- u08 data;
-
- // assert CS
- ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
-
- // issue read command
- SPDR = op | (address & ADDR_MASK);
- while(!(SPSR & (1<<SPIF)));
- // read data
- SPDR = 0x00;
- while(!(SPSR & (1<<SPIF)));
- // do dummy read if needed
- if(address & 0x80)
- {
- SPDR = 0x00;
- while(!(inb(SPSR) & (1<<SPIF)));
- }
- data = SPDR;
-
- // release CS
- ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
-
- return data;
-}
+static uint8_t current_bank;
+static uint16_t next_pkt_ptr;
-void enc28j60WriteOp(u08 op, u08 address, u08 data)
-{
- // assert CS
- ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
+#define SET_CS_ACTIVE() SPI_PORT &= ~(1<<SPI_CS);
+#define SET_CS_PASSIVE() SPI_PORT |= (1<<SPI_CS);
+#define SPI_WAIT() while(!(SPSR & (1<<SPIF)));
- // issue write command
- SPDR = op | (address & ADDR_MASK);
- while(!(SPSR & (1<<SPIF)));
- // write data
- SPDR = data;
- while(!(SPSR & (1<<SPIF)));
+static uint8_t enc28j60_read_op(uint8_t op, uint8_t addr){
+ SET_CS_ACTIVE();
+ SPDR = (op | (addr & ADDR_MASK));
+ SPI_WAIT();
+ SPDR = 0x00;
+ SPI_WAIT();
- // release CS
- ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
-}
+ if(addr & 0x80){
+ SPDR = 0x00;
+ SPI_WAIT();
+ }
-void enc28j60ReadBuffer(u16 len, u08* data)
-{
- // assert CS
- ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
-
- // issue read command
- SPDR = ENC28J60_READ_BUF_MEM;
- while(!(SPSR & (1<<SPIF)));
- while(len--)
- {
- // read data
- SPDR = 0x00;
- while(!(SPSR & (1<<SPIF)));
- *data++ = SPDR;
- }
- // release CS
- ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
+ SET_CS_PASSIVE();
+ return SPDR;
}
-void enc28j60WriteBuffer(u16 len, u08* data)
-{
- // assert CS
- ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
-
- // issue write command
- SPDR = ENC28J60_WRITE_BUF_MEM;
- while(!(SPSR & (1<<SPIF)));
- while(len--)
- {
- // write data
- SPDR = *data++;
- while(!(SPSR & (1<<SPIF)));
- }
- // release CS
- ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
+static void enc28j60_write_op(uint8_t op, uint8_t addr, uint8_t value){
+ SET_CS_ACTIVE();
+
+ SPDR = (op | (addr & ADDR_MASK));
+ SPI_WAIT();
+ SPDR = value;
+ SPI_WAIT();
+
+ SET_CS_PASSIVE();
}
-void enc28j60SetBank(u08 address)
-{
- // set the bank (if needed)
- if((address & BANK_MASK) != Enc28j60Bank)
- {
- // set the bank
- enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
- Enc28j60Bank = (address & BANK_MASK);
- }
+static void enc28j60_read_buffer(uint8_t* buf, uint16_t len){
+ SET_CS_ACTIVE();
+
+ SPDR = RBM;
+ SPI_WAIT();
+ while(len){
+ len--;
+ SPDR = 0x00;
+ SPI_WAIT();
+ *buf = SPDR;
+ buf++;
+ }
+ *buf = '\0';
+
+ SET_CS_PASSIVE();
}
-u08 enc28j60Read(u08 address)
-{
- // set the bank
- enc28j60SetBank(address);
- // do the read
- return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
+static void enc28j60_write_buffer(uint8_t* buf, uint16_t len){
+ SET_CS_ACTIVE();
+
+ SPDR = WBM;
+ SPI_WAIT();
+ while(len){
+ len--;
+ SPDR = *buf;
+ buf++;
+ SPI_WAIT();
+ }
+
+ SET_CS_PASSIVE();
}
-void enc28j60Write(u08 address, u08 data)
-{
- // set the bank
- enc28j60SetBank(address);
- // do the write
- enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
+static void enc28j60_set_bank(uint8_t addr){
+ if((addr & BANK_MASK) != current_bank){
+ enc28j60_write_op(BFC, ECON1, (BSEL1|BSEL0));
+ enc28j60_write_op(BFS, ECON1, ((addr & BANK_MASK) >> 5));
+ current_bank = (addr & BANK_MASK);
+ }
}
-u16 enc28j60PhyRead(u08 address)
-{
- u16 data;
-
- // Set the right address and start the register read operation
- enc28j60Write(MIREGADR, address);
- enc28j60Write(MICMD, MICMD_MIIRD);
-
- // wait until the PHY read completes
- while(enc28j60Read(MISTAT) & MISTAT_BUSY);
-
- // quit reading
- enc28j60Write(MICMD, 0x00);
-
- // get data value
- data = enc28j60Read(MIRDL);
- data |= enc28j60Read(MIRDH);
- // return the data
- return data;
+static uint8_t enc28j60_read(uint8_t addr){
+ enc28j60_set_bank(addr);
+ return enc28j60_read_op(RCR, addr);
}
-void enc28j60PhyWrite(u08 address, u16 data)
-{
- // set the PHY register address
- enc28j60Write(MIREGADR, address);
-
- // write the PHY data
- enc28j60Write(MIWRL, data);
- enc28j60Write(MIWRH, data>>8);
-
- // wait until the PHY write completes
- while(enc28j60Read(MISTAT) & MISTAT_BUSY);
+static void enc28j60_write(uint8_t addr, uint16_t value){
+ enc28j60_set_bank(addr);
+ enc28j60_write_op(WCR, addr, value);
}
-void enc28j60Init(u08* macaddr)
-{
- // initialize I/O
- sbi(ENC28J60_CONTROL_DDR, ENC28J60_CONTROL_CS);
- sbi(ENC28J60_CONTROL_PORT, ENC28J60_CONTROL_CS);
-
- // setup SPI I/O pins
- sbi(ENC28J60_SPI_PORT, ENC28J60_SPI_SCK); // set SCK hi
- sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SCK); // set SCK as output
- cbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MISO); // set MISO as input
- sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MOSI); // set MOSI as output
- sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SS); // SS must be output for Master mode to work
- // initialize SPI interface
- // master mode
- sbi(SPCR, MSTR);
- // select clock phase positive-going in middle of data
- cbi(SPCR, CPOL);
- // Data order MSB first
- cbi(SPCR,DORD);
- // switch to f/4 2X = f/2 bitrate
- cbi(SPCR, SPR0);
- cbi(SPCR, SPR1);
- sbi(SPSR, SPI2X);
- // enable SPI
- sbi(SPCR, SPE);
-
- // perform system reset
- enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
-
- /*
- * "After sending an SPI Reset command, the PHY
- * clock is stopped but the ESTAT.CLKRDY bit is not
- * cleared. Therefore, polling the CLKRDY bit will not
- * work to detect if the PHY is ready.
- *
- * Additionally, the hardware start-up time of 300 us
- * may expire before the device is ready to operate.
- *
- * Work around
- * After issuing the Reset command, wait at least
- * 1 ms in firmware for the device to be ready."
- *
- * Source: http://ww1.microchip.com/downloads/en/DeviceDoc/80349c.pdf
- */
- _delay_ms(1);
-
- // do bank 0 stuff
- // initialize receive buffer
- // 16-bit transfers, must write low byte first
- // set receive buffer start address
- NextPacketPtr = RXSTART_INIT;
- enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
- enc28j60Write(ERXSTH, RXSTART_INIT>>8);
- // set receive pointer address
- enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
- enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
- // set receive buffer end
- // ERXND defaults to 0x1FFF (end of ram)
- enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
- enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
- // set transmit buffer start
- // ETXST defaults to 0x0000 (beginnging of ram)
- enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
- enc28j60Write(ETXSTH, TXSTART_INIT>>8);
-
- // do bank 2 stuff
- // enable MAC receive
- enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
- // bring MAC out of reset
- enc28j60Write(MACON2, 0x00);
- // enable automatic padding and CRC operations
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
- // set inter-frame gap (non-back-to-back)
- enc28j60Write(MAIPGL, 0x12);
- enc28j60Write(MAIPGH, 0x0C);
- // set inter-frame gap (back-to-back)
- enc28j60Write(MABBIPG, 0x12);
- // Set the maximum packet size which the controller will accept
- enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);
- enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);
-
- // do bank 3 stuff
- // write MAC address
- // NOTE: MAC address in ENC28J60 is byte-backward
- enc28j60Write(MAADR5, macaddr[0]);
- enc28j60Write(MAADR4, macaddr[1]);
- enc28j60Write(MAADR3, macaddr[2]);
- enc28j60Write(MAADR2, macaddr[3]);
- enc28j60Write(MAADR1, macaddr[4]);
- enc28j60Write(MAADR0, macaddr[5]);
-
- // no loopback of transmitted frames
- enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
-
- // switch to bank 0
- enc28j60SetBank(ECON1);
- // enable interrutps
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
- // enable packet reception
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
+void enc28j60_init(uint8_t* mac_addr){
+ SPI_DDR |= (1 << SPI_CS);
+ SET_CS_PASSIVE();
+
+ SPI_DDR |= ((1 << SPI_MOSI) | (1 << SPI_SCK));
+ SPI_DDR &= ~(1 << SPI_MISO);
+ SPI_PORT &= ~(1 << SPI_MOSI);
+ SPI_PORT &= ~(1 << SPI_SCK);
+ SPCR = ((1 << SPE) | (1 << MSTR));
+ SPSR |= (1 << SPI2X);
+ enc28j60_write_op(SC, 0, SC);
+ next_pkt_ptr = RXSTART_INIT;
+
+ // Designate RX addresses
+ enc28j60_write(ERXSTL, (RXSTART_INIT & 0xFF));
+ enc28j60_write(ERXSTH, (RXSTART_INIT >> 8));
+ enc28j60_write(ERXNDL, (RXSTOP_INIT & 0xFF));
+ enc28j60_write(ERXNDH, (RXSTOP_INIT >> 8));
+
+ // Designate TX addresses
+ enc28j60_write(ETXSTL, (TXSTART_INIT & 0xFF));
+ enc28j60_write(ETXSTH, (TXSTART_INIT >> 8));
+ enc28j60_write(ETXNDL, (TXSTOP_INIT & 0xFF));
+ enc28j60_write(ETXNDH, (TXSTOP_INIT >> 8));
+
+ // Configure filters
+ enc28j60_write(ERXFCON, (UCEN|CRCEN|PMEN|BCEN));
+ enc28j60_write(EPMM0, 0x3F);
+ enc28j60_write(EPMM1, 0x30);
+ enc28j60_write(EPMCSL, 0xF9);
+ enc28j60_write(EPMCSH, 0xF7);
+
+ // MAC initialization
+ enc28j60_write(MACON1, (MARXEN|TXPAUS|RXPAUS));
+ enc28j60_write(MACON2, 0x00);
+ enc28j60_write_op(BFS, MACON3, (PADCFG0|TXCRCEN|FRMLNEN));
+ enc28j60_write(MAIPGL, 0x12);
+ enc28j60_write(MAIPGH, 0x0C);
+ enc28j60_write(MABBIPG, 0x12);
+ enc28j60_write(MAMXFLL, (MAX_FRAMELEN & 0xFF));
+ enc28j60_write(MAMXFLH, (MAX_FRAMELEN >> 8));
+ enc28j60_write(MAADR5, mac_addr[0]);
+ enc28j60_write(MAADR4, mac_addr[1]);
+ enc28j60_write(MAADR3, mac_addr[2]);
+ enc28j60_write(MAADR2, mac_addr[3]);
+ enc28j60_write(MAADR1, mac_addr[4]);
+ enc28j60_write(MAADR0, mac_addr[5]);
+
+ enc28j60_set_bank(ECON1);
+ enc28j60_write_op(BFS, ECON1, ENCRXEN);
}
-void enc28j60PacketSend(unsigned int len1, unsigned char* packet1, unsigned int len2, unsigned char* packet2)
-{
- //Errata: Transmit Logic reset
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
- enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
-
- // Set the write pointer to start of transmit buffer area
- enc28j60Write(EWRPTL, TXSTART_INIT&0xff);
- enc28j60Write(EWRPTH, TXSTART_INIT>>8);
- // Set the TXND pointer to correspond to the packet size given
- enc28j60Write(ETXNDL, (TXSTART_INIT+len1+len2));
- enc28j60Write(ETXNDH, (TXSTART_INIT+len1+len2)>>8);
-
- // write per-packet control byte
- enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
-
- // copy the packet into the transmit buffer
- enc28j60WriteBuffer(len1, packet1);
- if(len2>0) enc28j60WriteBuffer(len2, packet2);
-
- // send the contents of the transmit buffer onto the network
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
+uint16_t enc28j60_recv(uint8_t* buf, uint16_t max_len){
+ uint16_t rxstat, len;
+
+ // Return if no data is available
+ if(enc28j60_read(EPKTCNT) == 0) return 0;
+
+ enc28j60_write(ERDPTL, (next_pkt_ptr & 0xFF));
+ enc28j60_write(ERDPTH, (next_pkt_ptr >> 8));
+ next_pkt_ptr = enc28j60_read_op(RBM, 0) | ((uint16_t)enc28j60_read_op(RBM, 0) << 8);
+ len = enc28j60_read_op(RBM, 0) | ((uint16_t)enc28j60_read_op(RBM, 0) << 8);
+ len -= 4;
+ rxstat = enc28j60_read_op(RBM, 0) | ((uint16_t)enc28j60_read_op(RBM, 0) << 8);
+
+ // Length sanity check and actual enc28j60_read call
+ if(len > (max_len - 1)) len = max_len - 1;
+ if((rxstat & 0x80) == 0) len = 0;
+ else enc28j60_read_buffer(buf, len);
+
+ // Update next packet pointer
+ enc28j60_write(ERXRDPTL, (next_pkt_ptr & 0xFF));
+ enc28j60_write(ERXRDPTH, (next_pkt_ptr >> 8));
+ if(((next_pkt_ptr - 1) < RXSTART_INIT) || ((next_pkt_ptr - 1) > RXSTOP_INIT)){
+ enc28j60_write(ERXRDPTL, (RXSTOP_INIT & 0xFF));
+ enc28j60_write(ERXRDPTH, (RXSTOP_INIT >> 8));
+ }
+ else{
+ enc28j60_write(ERXRDPTL, ((next_pkt_ptr - 1) & 0xFF));
+ enc28j60_write(ERXRDPTH, ((next_pkt_ptr - 1) >> 8));
+ }
+ enc28j60_write_op(BFS, ECON2, PKTDEC);
+
+ return len;
}
-unsigned int enc28j60PacketReceive(unsigned int maxlen, u08* buf)
-{
- u16 rxstat;
- u16 len;
-
- // check if a packet has been received and buffered
- if( !enc28j60Read(EPKTCNT) )
- return 0;
-
- // Set the read pointer to the start of the received packet
- enc28j60Write(ERDPTL, (NextPacketPtr));
- enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
- // read the next packet pointer
- NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
- // read the packet length
- len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
- // read the receive status
- rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
- rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
-
- // limit retrieve length
- // (we reduce the MAC-reported length by 4 to remove the CRC)
- len = MIN(len, maxlen);
-
- // copy the packet from the receive buffer
- enc28j60ReadBuffer(len, buf);
-
- // Move the RX read pointer to the start of the next received packet
- // This frees the memory we just read out
- enc28j60Write(ERXRDPTL, (NextPacketPtr));
- enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
-
- // decrement the packet counter indicate we are done with this packet
- enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
-
- return len;
+void enc28j60_send(uint8_t* buf, uint16_t len){
+
+ // Wait for any current transmission to finish
+ while(enc28j60_read_op(RCR, ECON1) & TXRTS){
+ if(enc28j60_read(EIR) & TXERIF){
+ enc28j60_write_op(BFS, ECON1, TXRST);
+ enc28j60_write_op(BFC, ECON1, TXRST);
+ }
+ }
+
+ enc28j60_write(EWRPTL, (TXSTART_INIT & 0xFF));
+ enc28j60_write(EWRPTH, (TXSTART_INIT >> 8));
+ enc28j60_write(ETXNDL, ((TXSTART_INIT + len) & 0xFF));
+ enc28j60_write(ETXNDH, ((TXSTART_INIT + len) >> 8));
+ enc28j60_write_op(WBM, 0, 0x00);
+ enc28j60_write_buffer(buf, len);
+ enc28j60_write_op(BFS, ECON1, TXRTS);
}
diff --git a/firmware/octoclock/lib/init.c b/firmware/octoclock/lib/init.c
index 827ccb376..8592aa091 100644
--- a/firmware/octoclock/lib/init.c
+++ b/firmware/octoclock/lib/init.c
@@ -71,7 +71,7 @@ void setup_atmel_io_ports(){
// /pd_cdcd, /sync_code, /ce need to be 1 (disabled) to start
// all bits are outputs, except PA7 (gps_lock) and PA3 (MISO_CDCE) are inputs
-PORTA = Bits_8(00110010);
+PORTA = Bits_8(00100010);
DDRA = 1<<DDA6 | 1<<DDA5 | 1<<DDA4 | 1<<DDA2 | 1<<DDA1 | 1<<DDA0;
/*
@@ -90,8 +90,8 @@ DDRA = 1<<DDA6 | 1<<DDA5 | 1<<DDA4 | 1<<DDA2 | 1<<DDA1 | 1<<DDA0;
*
*/
-PORTB = Bits_8(01100001); // Initial Value is all zeros
-DDRB = 1<<DDB2 | 1<<DDB4 | 1<<DDB7; // MOSI is an output; the Not Connected pins are also outputs
+PORTB = Bits_8(01100001); // Initial Value is all zeros
+DDRB = Bits_8(11110111); // MOSI is an output; the Not Connected pins are also outputs
/*
* Port C
diff --git a/firmware/octoclock/lib/network.c b/firmware/octoclock/lib/network.c
index bb49de4f6..22fc2b54b 100644
--- a/firmware/octoclock/lib/network.c
+++ b/firmware/octoclock/lib/network.c
@@ -27,6 +27,7 @@
#include <debug.h>
#include <octoclock.h>
+#include <state.h>
#include <network.h>
#include <net/enc28j60.h>
@@ -34,12 +35,14 @@
#include <net/if_arp.h>
#include <net/ethertype.h>
+#include <util/delay.h>
+
#include "arp_cache.h"
/***********************************************************************
* Constants + Globals
**********************************************************************/
-static const size_t out_buff_size = 512;
+static const size_t out_buff_size = ETH_BUF_SIZE;
static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
#define MAX_UDP_LISTENERS 10
@@ -139,7 +142,7 @@ send_pkt(
//grab an out buffer and pointer
//select the output buffer based on type of packet
uint8_t *p;
- p = buf_out;
+ p = eth_buf;
size_t total_len = 0;
//create a list of all buffers to copy
@@ -149,7 +152,7 @@ send_pkt(
//copy each buffer into the out buffer
for (size_t i = 0; i < sizeof(buffs)/sizeof(buffs[0]); i++){
total_len += lens[i]; //use full length (not clipped)
- size_t bytes_remaining = out_buff_size - (size_t)(p - (uint8_t*)buf_out);
+ size_t bytes_remaining = out_buff_size - (size_t)(p - (uint8_t*)eth_buf);
if (lens[i] > bytes_remaining) lens[i] = bytes_remaining;
memcpy(p, buffs[i], lens[i]);
p += lens[i];
@@ -161,7 +164,7 @@ send_pkt(
//For some reason, the ENC28J60 won't send the CRC
//if you don't tell it to send another byte after
//the given packet
- enc28j60PacketSend(total_len+1, buf_out, 0, 0);
+ enc28j60_send(eth_buf, total_len);
}
static void
@@ -333,15 +336,15 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size)
void
handle_eth_packet(size_t recv_len)
{
- eth_hdr_t *eth_hdr = (eth_hdr_t *)buf_in;
+ eth_hdr_t *eth_hdr = (eth_hdr_t *)eth_buf;
uint16_t ethertype = htons(eth_hdr->ethertype);
if (ethertype == ETHERTYPE_ARP){
- struct arp_eth_ipv4 *arp = (struct arp_eth_ipv4 *)(buf_in + sizeof(eth_hdr_t));
+ struct arp_eth_ipv4 *arp = (struct arp_eth_ipv4 *)(eth_buf + sizeof(eth_hdr_t));
handle_arp_packet(arp, recv_len-ETH_HLEN);
}
else if (ethertype == ETHERTYPE_IPV4){
- struct ip_hdr *ip = (struct ip_hdr *)(buf_in + sizeof(eth_hdr_t));
+ struct ip_hdr *ip = (struct ip_hdr *)(eth_buf + sizeof(eth_hdr_t));
if (_IPH_V(ip) != 4 || _IPH_HL(ip) != 5) // ignore pkts w/ bad version or options
return;
@@ -357,7 +360,7 @@ handle_eth_packet(size_t recv_len)
bool is_my_ip = memcmp(&ip->dest, &htonl_local_ip_addr, sizeof(_local_ip_addr)) == 0;
if (!is_bcast && !is_my_ip) return;
- arp_cache_update(&ip->src, (eth_mac_addr_t *)(((char *)buf_in)+6));
+ arp_cache_update(&ip->src, (eth_mac_addr_t *)(((char *)eth_buf)+6));
switch (_IPH_PROTO(ip)){
case IP_PROTO_UDP:
@@ -381,7 +384,6 @@ handle_eth_packet(size_t recv_len)
**********************************************************************/
static bool send_garp = false;
-static bool sent_initial_garp = false;
static uint32_t num_overflows = 0;
// Six overflows is the closest overflow count to one minute.
@@ -390,6 +392,7 @@ ISR(TIMER1_OVF_vect){
if(!(num_overflows % 6)) send_garp = true;
}
+// Send a GARP packet once per minute.
static void
send_gratuitous_arp(){
send_garp = false;
@@ -415,18 +418,9 @@ send_gratuitous_arp(){
// Executed every loop
void network_check(void){
- size_t recv_len = enc28j60PacketReceive(512, buf_in);
+ size_t recv_len = enc28j60_recv(eth_buf, ETH_BUF_SIZE);
if(recv_len > 0) handle_eth_packet(recv_len);
- /*
- * Send a gratuitous ARP packet two seconds after Ethernet
- * initialization.
- */
- if(!sent_initial_garp && (num_overflows == 0 && TCNT1 > (TIMER1_ONE_SECOND*2))){
- sent_initial_garp = true;
- send_garp = true;
- }
-
if(send_garp) send_gratuitous_arp();
}
@@ -435,9 +429,10 @@ void network_init(void){
* Read MAC address from EEPROM and initialize Ethernet driver. If EEPROM is blank,
* use default MAC address instead.
*/
+ eeprom_busy_wait();
if(eeprom_read_byte(0) == 0xFF){
_MAC_ADDR(_local_mac_addr.addr, 0x00,0x80,0x2F,0x11,0x22,0x33);
- _local_ip_addr.addr = default_ip;
+ _local_ip_addr.addr = _IP(192,168,10,3);
using_network_defaults = true;
}
else{
@@ -446,5 +441,8 @@ void network_init(void){
using_network_defaults = false;
}
- enc28j60Init((uint8_t*)&_local_mac_addr);
+ enc28j60_init((uint8_t*)&_local_mac_addr);
+ init_udp_listeners();
+
+ send_garp = true;
}
diff --git a/firmware/octoclock/lib/state.c b/firmware/octoclock/lib/state.c
index 0dbcc6ece..26e1b783c 100644
--- a/firmware/octoclock/lib/state.c
+++ b/firmware/octoclock/lib/state.c
@@ -15,110 +15,80 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <avr/interrupt.h>
#include <avr/io.h>
+#include <avrlibdefs.h>
#include <debug.h>
#include <octoclock.h>
#include <clkdist.h>
#include <state.h>
-void led(LEDs which, int turn_it_on) {
+// Global state variables
+volatile bool g_ext_ref_present = false;
+volatile bool g_gps_present = false;
+volatile switch_pos_t g_switch_pos = PREFER_INTERNAL;
+volatile ref_t g_ref = NO_REF;
+void led(led_t which, bool on){
// selects the proper bit
uint8_t LED = 0x20 << which;
- if(turn_it_on)
+ if(on)
PORTC |= LED;
else
PORTC &= ~LED;
}
-void LEDs_Off(void){
- led(Top,false);
- led(Middle,false);
- led(Bottom,false);
+void leds_off(void){
+ led(LED_TOP, false);
+ led(LED_MIDDLE, false);
+ led(LED_BOTTOM, false);
}
-void force_internal(void){
- led(Top,true);
- led(Middle,false);
- led(Bottom,true);
+static void force_internal(void){
+ led(LED_TOP, true);
+ led(LED_MIDDLE, false);
+ led(LED_BOTTOM, true);
+ // Tell ClkDist chip to use internal signals
+ cli();
setup_TI_CDCE18005(Primary_GPS);
+ sei();
- // Set PPS to Primary (1) n.b.: "1" in general means "Internal" for all
- // such signals
+ // Set PPS to internal
PORTA |= (1<<PA6);
}
-void force_external(void){
- led(Top, false);
- led(Middle, true);
- led(Bottom, true);
+static void force_external(void){
+ led(LED_TOP, false);
+ led(LED_MIDDLE, true);
+ led(LED_BOTTOM, true);
+ // Tell Clkdist chip to use external signals
+ cli();
setup_TI_CDCE18005(Secondary_Ext);
+ sei();
- // Set PPS to External
+ // Set PPS to external
PORTA &= ~(1<<PA6);
}
void prefer_internal(void){
- // if internal is NOT OK, then force external
- if(global_gps_present)
+ // If internal is NOT OK, then force external
+ if(g_gps_present)
force_internal();
- else if(global_ext_ref_is_present)
+ else if(g_ext_ref_present)
force_external();
else
- LEDs_Off();
+ leds_off();
}
void prefer_external(void){
- // if external is NOT OK, then force internal
- if(global_ext_ref_is_present)
+ // If external is NOT OK, then force internal
+ if(g_ext_ref_present)
force_external();
- else if(global_gps_present)
+ else if(g_gps_present)
force_internal();
else
- LEDs_Off();
-}
-
-static uint8_t prev_PE7 = 0;
-static uint32_t timer0_num_overflows = 0;
-
-ISR(TIMER0_OVF_vect){
- global_gps_present = (PIND & (1<<DDD4));
-
- // Every ~1/10 second
- if(!(timer0_num_overflows % 610)){
- prev_PE7 = (PINE & (1<<DDE7));
-
- if(get_switch_pos() == UP) prefer_internal();
- else prefer_external();
-
- global_ext_ref_is_present = false;
- }
-
- if(!global_ext_ref_is_present){
- global_ext_ref_is_present = (prev_PE7 != (PINE & (1<<DDE7)));
- }
-
- timer0_num_overflows++;
-}
-
-ref_t which_ref(void){
- if(!global_gps_present && !global_ext_ref_is_present) global_which_ref = NO_REF;
- else if(global_gps_present && !global_ext_ref_is_present) global_which_ref = INTERNAL;
- else if(!global_gps_present && global_ext_ref_is_present) global_which_ref = EXTERNAL;
- else global_which_ref = (get_switch_pos() == UP) ? INTERNAL : EXTERNAL;
-
- return global_which_ref;
-}
-
-switch_pos_t get_switch_pos(void){
- uint8_t portC = PINC;
-
- // UP is prefer internal,
- // DOWN is prefer external
- return (portC & (1<<DDC1)) ? DOWN : UP;
+ leds_off();
}
diff --git a/firmware/octoclock/lib/udp_handlers.c b/firmware/octoclock/lib/udp_handlers.c
index 1f20112c9..49b9b8023 100644
--- a/firmware/octoclock/lib/udp_handlers.c
+++ b/firmware/octoclock/lib/udp_handlers.c
@@ -36,7 +36,7 @@ void handle_udp_ctrl_packet(
pkt_out.proto_ver = OCTOCLOCK_FW_COMPAT_NUM;
pkt_out.sequence = pkt_in->sequence;
- //If the firmware is incompatible, only respond to queries
+ // If the firmware is incompatible, only respond to queries
if(pkt_in->code == OCTOCLOCK_QUERY_CMD){
pkt_out.code = OCTOCLOCK_QUERY_ACK;
pkt_out.len = 0;
@@ -50,44 +50,43 @@ void handle_udp_ctrl_packet(
octoclock_fw_eeprom_t *eeprom_info = (octoclock_fw_eeprom_t*)pkt_out.data;
- //Read values from EEPROM into packet
+ // Read values from EEPROM into packet
+ eeprom_busy_wait();
eeprom_read_block(eeprom_info, 0, sizeof(octoclock_fw_eeprom_t));
- //If EEPROM network fields are not fully populated, copy defaults
+ // If EEPROM network fields are not fully populated, copy defaults
if(using_network_defaults){
_MAC_ADDR(eeprom_info->mac_addr, 0x00,0x80,0x2F,0x11,0x22,0x33);
- eeprom_info->ip_addr = default_ip;
- eeprom_info->dr_addr = default_dr;
- eeprom_info->netmask = default_netmask;
+ eeprom_info->ip_addr = _IP(192,168,10,3);
+ eeprom_info->dr_addr = _IP(192,168,10,1);
+ eeprom_info->netmask = _IP(255,255,255,0);
}
- //Check if strings or revision is empty
- if(eeprom_info->serial[0] == 0xFF) memset(eeprom_info->serial, 0, 10);
- if(eeprom_info->name[0] == 0xFF) memset(eeprom_info->name, 0, 10);
+ // Check if strings or revision is empty
if(eeprom_info->revision == 0xFF) eeprom_info->revision = 0;
break;
case BURN_EEPROM_CMD:{
- //Confirm length of data
+ // Confirm length of data
if(pkt_in->len != sizeof(octoclock_fw_eeprom_t)){
pkt_out.code = BURN_EEPROM_FAILURE_ACK;
break;
}
/*
- * In all cases, a full octoclock_fw_eeprom_t is written to lower the overall
- * number of writes due to this EEPROM's smaller amount of safe writes.
* It is up to the host to make sure that the values that should be
* preserved are present in the octoclock_fw_eeprom_t struct.
*/
const octoclock_fw_eeprom_t *eeprom_pkt = (octoclock_fw_eeprom_t*)pkt_in->data;
pkt_out.len = 0;
- //Write EEPROM data from packet
+ // Write EEPROM data from packet
+ eeprom_busy_wait();
eeprom_write_block(eeprom_pkt, 0, sizeof(octoclock_fw_eeprom_t));
- //Read back and compare to packet to confirm successful write
+ // Read back and compare to packet to confirm successful write
uint8_t eeprom_contents[sizeof(octoclock_fw_eeprom_t)];
+ eeprom_busy_wait();
eeprom_read_block(eeprom_contents, 0, sizeof(octoclock_fw_eeprom_t));
uint8_t n = memcmp(eeprom_contents, eeprom_pkt, sizeof(octoclock_fw_eeprom_t));
pkt_out.code = n ? BURN_EEPROM_FAILURE_ACK
@@ -99,12 +98,12 @@ void handle_udp_ctrl_packet(
pkt_out.code = SEND_STATE_ACK;
pkt_out.len = sizeof(octoclock_state_t);
- //Populate octoclock_state_t fields
+ // Populate octoclock_state_t fields
octoclock_state_t *state = (octoclock_state_t*)pkt_out.data;
- state->external_detected = global_ext_ref_is_present ? 1 : 0;
- state->gps_detected = (PIND & _BV(DDD4)) ? 1 : 0;
- state->which_ref = (uint8_t)which_ref();
- state->switch_pos = (uint8_t)get_switch_pos();
+ state->external_detected = g_ext_ref_present ? 1 : 0;
+ state->gps_detected = g_gps_present ? 1 : 0;
+ state->which_ref = (uint8_t)g_ref;
+ state->switch_pos = (uint8_t)g_switch_pos;
break;
case RESET_CMD:
diff --git a/firmware/octoclock/lib/usart.c b/firmware/octoclock/lib/usart.c
index 3620ac5e9..a267e43c6 100644
--- a/firmware/octoclock/lib/usart.c
+++ b/firmware/octoclock/lib/usart.c
@@ -34,16 +34,8 @@ char usart_getc(void){
return UDR1;
}
-char usart_getc_noblock(void){
- return ((UCSR1A & (1 << RXC))) ? UDR1 : -1;
-}
-
void usart_putc(char ch){
while((UCSR1A & (1 << UDRE1)) == 0);
UDR1 = ch;
}
-
-void usart_putc_nowait(char ch){
- if((UCSR1A & (1 << UDRE1)) != 0) UDR1 = ch;
-}
diff --git a/firmware/octoclock/octoclock_r4/CMakeLists.txt b/firmware/octoclock/octoclock_r4/CMakeLists.txt
index c3559d8d4..9223721c8 100644
--- a/firmware/octoclock/octoclock_r4/CMakeLists.txt
+++ b/firmware/octoclock/octoclock_r4/CMakeLists.txt
@@ -43,7 +43,7 @@ add_custom_target(
)
add_custom_target(
upload_r4
- ${AVRDUDE} -p atmega128 -c ${PROGRAMMER} -P usb -U efuse:w:0xFF:m -U hfuse:w:0x81:m -U lfuse:w:0xFF:m -U flash:w:octoclock_r4_fw.hex:i
+ ${AVRDUDE} -p atmega128 -c ${PROGRAMMER} -P usb -U efuse:w:0xFF:m -U hfuse:w:0x81:m -U lfuse:w:0xEF:m -U flash:w:octoclock_r4_fw.hex:i
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS octoclock_r4_fw_hex
COMMENT "Uploading OctoClock firmware to device with ${PROGRAMMER}"
diff --git a/firmware/octoclock/octoclock_r4/octoclock_r4_main.c b/firmware/octoclock/octoclock_r4/octoclock_r4_main.c
index 5e8e6d09b..b1df34195 100644
--- a/firmware/octoclock/octoclock_r4/octoclock_r4_main.c
+++ b/firmware/octoclock/octoclock_r4/octoclock_r4_main.c
@@ -36,7 +36,7 @@
* JTAGEN = [X]
* SPIEN = [X]
* EESAVE = [X]
- * BOOTSZ = 4096W_F000
+ * BOOTSZ = 4095W_F000
* BOOTRST = [ ]
* CKOPT = [X]
* BODLEVEL = 2V7
@@ -49,57 +49,165 @@
*
*/
+#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/eeprom.h>
+#include <avr/interrupt.h>
#include <avr/io.h>
+#include <avrlibdefs.h>
#include <octoclock.h>
-#include <clkdist.h>
#include <debug.h>
+#include <clkdist.h>
#include <state.h>
#include <network.h>
#include <usart.h>
-#include <gpsdo.h>
-#include <net/enc28j60.h>
#include <net/udp_handlers.h>
+/*
+ * Timer 3 (16-bit)
+ * * Set input capture trigger to rising edge
+ * * Set prescaler to 1
+ * * Enable overflow interrupt
+ * * Set timer to 0
+ */
+#define TIMER3_INIT() TCCR3B = (1 << ICES3) | (1 << CS30); \
+ ETIMSK |= (1 << TOIE3); \
+ TCNT3 = 0; \
+ ICR3 = 0;
+
+/*
+ * We use TIMER3 as a watchdog timer for external reference
+ * detection. Once a signal is detected, we allow for five
+ * timer overflows (~26 ms) without another signal before
+ * deciding that there is no external reference connected.
+ */
+#define EXT_REF_TIMEOUT 5
+
+static volatile uint16_t num_overflows = 0;
+static uint16_t current_num_overflows = 0;
+static uint16_t prev_num_overflows = 0;
+static uint16_t current_ICR3 = 0;
+static uint16_t prev_ICR3 = 0;
+static ref_t prev_ref = NO_REF;
+static switch_pos_t prev_switch_pos = PREFER_EXTERNAL;
+bool top = false;
+
+ISR(TIMER3_OVF_vect){
+ num_overflows++;
+}
+
/*******************************************************************************
* Main Routine
*******************************************************************************/
int main(void){
- asm("cli");
+ /*
+ * Initializations
+ */
+ cli();
+ // Make sure interrupts belong to us
+ MCUCR = (1<<IVCE);
+ MCUCR = 0;
+
+ // Initialize global variables
+ g_ext_ref_present = false;
+ g_gps_present = false;
+ g_switch_pos = PREFER_INTERNAL;
+ g_ref = NO_REF;
+
+ // Atmega128
setup_atmel_io_ports();
- network_init();
- #ifndef DEBUG
- asm("sei");
- #endif
+ // Reset ClkDist chip
+ reset_TI_CDCE18005();
- init_udp_listeners();
- register_udp_listener(OCTOCLOCK_UDP_CTRL_PORT, handle_udp_ctrl_packet);
+ // GPSDO communication
+ usart_init();
+
+ // Ethernet stack
+ network_init();
+ register_udp_listener(OCTOCLOCK_UDP_CTRL_PORT, handle_udp_ctrl_packet);
register_udp_listener(OCTOCLOCK_UDP_GPSDO_PORT, handle_udp_gpsdo_packet);
- DEBUG_INIT(); // Does nothing when not in debug mode
- DEBUG_LOG(" "); //Force a newline between runs
- usart_init();
+ // Timers
+ TIMER1_INIT(); // Network
+ TIMER3_INIT(); // External reference check
+
+ // Debug (does nothing when not in debug mode)
+ DEBUG_INIT();
+ DEBUG_LOG(" "); // Force a newline between runs
+
+ leds_off();
+
+ sei();
+
+ // Check if GPS present (should only need to happen once)
+ g_gps_present = (PIND & (1<<DDD4));
+
+ // State of previous iteration
+ prev_ref = NO_REF;
+ prev_switch_pos = PREFER_EXTERNAL;
+ cli();
+ prev_ICR3 = ICR3;
+ sei();
+ prev_num_overflows = 0;
+
+ /*
+ * Main loop
+ */
+ while(true){
+ // Check switch position
+ g_switch_pos = (PINC & (1<<DDC1)) ? PREFER_EXTERNAL : PREFER_INTERNAL;
+
+ /*
+ * Check input capture pin for external reference detection.
+ *
+ * 16-bit reads could be corrupted during an interrupt, so
+ * disable interrupts for safety.
+ */
+ cli();
+ current_ICR3 = ICR3;
+ current_num_overflows = num_overflows;
+ sei();
+
+ // Signal detected, reset timer
+ if(current_ICR3 != prev_ICR3){
+ cli();
+ TCNT3 = 0;
+ num_overflows = 0;
+ sei();
+ g_ext_ref_present = true;
+ }
+
+ // Timeout, no external reference detected
+ if(current_num_overflows >= EXT_REF_TIMEOUT){
+ g_ext_ref_present = false;
+ }
- //Set initial ClkDist and front panel settings
- led(Middle,true);
- setup_TI_CDCE18005(Primary_GPS); // 10 MHz from Internal Source
+ // Determine and set reference based on state
+ if(!g_gps_present && !g_ext_ref_present) g_ref = NO_REF;
+ else if(g_gps_present && !g_ext_ref_present) g_ref = INTERNAL;
+ else if(!g_gps_present && g_ext_ref_present) g_ref = EXTERNAL;
+ else g_ref = (g_switch_pos == PREFER_INTERNAL) ? INTERNAL : EXTERNAL;
- led(Top,true);
- PORTA |= (1<<PA6); // PPS from Internal source
+ if((g_ref != prev_ref) || (g_switch_pos != prev_switch_pos)){
+ if(g_switch_pos == PREFER_INTERNAL) prefer_internal();
+ else prefer_external();
+ }
- TIMER0_INIT();
- TIMER1_INIT();
+ // Record this iteration's state
+ prev_ref = g_ref;
+ prev_switch_pos = g_switch_pos;
+ prev_ICR3 = current_ICR3;
+ prev_num_overflows = current_num_overflows;
- while(true) {
+ // Handle incoming Ethernet packets
network_check();
}
}
diff --git a/firmware/usrp3/CMakeLists.txt b/firmware/usrp3/CMakeLists.txt
index c25adb68a..f71b79b0c 100644
--- a/firmware/usrp3/CMakeLists.txt
+++ b/firmware/usrp3/CMakeLists.txt
@@ -68,6 +68,20 @@ FIND_PROGRAM(OBJDUMP zpu-elf-objdump)
FIND_PROGRAM(HEXDUMP hexdump)
########################################################################
+# Firmware tracing support
+########################################################################
+# Look at include/trace.h to see what the different trace levels map to.
+SET(TRACE_LEVEL "0" CACHE STRING "Firmware Trace Level") #0 by default
+OPTION(TRACE_LEVEL "Firmware Trace Level" "")
+IF(TRACE_LEVEL)
+ #If TRACE_LEVEL == 0, don't define UHD_FW_TRACE_LEVEL so that the C
+ #code can easily detect if tracing is requested
+ IF(${TRACE_LEVEL} GREATER 0)
+ ADD_DEFINITIONS(-DUHD_FW_TRACE_LEVEL=${TRACE_LEVEL})
+ ENDIF(${TRACE_LEVEL} GREATER 0)
+ENDIF(TRACE_LEVEL)
+
+########################################################################
# helper functions to build output formats
########################################################################
SET(GEN_OUTPUTS_BIN_SIZE "bin_size_not_set") #set before calling
diff --git a/firmware/usrp3/include/ethernet.h b/firmware/usrp3/include/ethernet.h
index 52f14d05b..a6bacfcd0 100644
--- a/firmware/usrp3/include/ethernet.h
+++ b/firmware/usrp3/include/ethernet.h
@@ -31,7 +31,7 @@ typedef void (*ethernet_link_changed_callback_t)(int ethnum, int speed);
/*!
* \brief one time call to initialize ethernet
*/
-void xge_ethernet_init(const uint32_t eth);
+void ethernet_init(const uint32_t eth);
/*!
* \brief Return number of ethernet interfaces
@@ -44,8 +44,7 @@ void dump_mdio_regs(const uint8_t eth, uint32_t mdio_port);
/*!
* \brief Test status of SFP+ modules
*/
-void
-xge_poll_sfpp_status(const uint32_t eth);
+void poll_sfpp_status(const uint32_t eth);
//! get the link status of eth (true for link up)
bool ethernet_get_link_up(const uint32_t eth);
diff --git a/firmware/usrp3/include/trace.h b/firmware/usrp3/include/trace.h
new file mode 100644
index 000000000..0daa231fe
--- /dev/null
+++ b/firmware/usrp3/include/trace.h
@@ -0,0 +1,82 @@
+//
+// Copyright 2015 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_TRACE_H
+#define INCLUDED_TRACE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <printf.h>
+
+/*
+ * Enables basic conditional tracing support
+ * If UHD_FW_TRACE_LEVEL is defined, all messages
+ * with a verbosity >= UHD_FW_TRACE_LEVEL will be
+ * printed.
+ *
+ * An alternate way of defining the level is the "TRACE_LEVEL"
+ * variable in cmake. (eg. -DTRACE_LEVEL=13).
+ */
+//#define UHD_FW_TRACE_LEVEL 13
+
+typedef enum
+{
+ /* 0-9: Use for performance/restricted debugging */
+ ERROR = 10,
+ WARN = 11,
+ INFO = 12,
+ /* 13-19: Use for general debugging */
+ DEBUG = 20, //Verbose!
+} trace_level_t;
+
+static inline int _trace_typecheck_conv(trace_level_t lvl) {
+ return (int)lvl;
+}
+
+#define UHD_FW_PRINTF(...) printf(__VA_ARGS__)
+#define UHD_FW_BEAUTIFY_LVL(lvl) "[" #lvl "] "
+
+/*
+ * UHD_FW_TRACE(<log level>, <message>)
+ * - Simple trace. Print the messages with the log level as the prefix and \n at the end
+ *
+ * UHD_FW_TRACE_FSTR(<log level>, <format string>, <args>)
+ * - Trace format string with the log level as the prefix and \n at the end
+ *
+ * UHD_FW_TRACE_SHORT(<log level>, <message>)
+ * - Simple trace. Print the messages without the log level prefix or \n at the end
+ *
+ * UHD_FW_TRACE_FSTR_SHORT(<log level>, <format string>, <args>)
+ * - Trace format string without the log level prefix or \n at the end
+ */
+#ifdef UHD_FW_TRACE_LEVEL
+ #define UHD_FW_TRACE(lvl, fmt) \
+ if (UHD_FW_TRACE_LEVEL >= _trace_typecheck_conv(lvl)) UHD_FW_PRINTF(UHD_FW_BEAUTIFY_LVL(lvl) fmt "\r\n");
+ #define UHD_FW_TRACE_FSTR(lvl, fmt, ...) \
+ if (UHD_FW_TRACE_LEVEL >= _trace_typecheck_conv(lvl)) UHD_FW_PRINTF(UHD_FW_BEAUTIFY_LVL(lvl) fmt "\r\n", __VA_ARGS__);
+ #define UHD_FW_TRACE_SHORT(lvl, fmt) \
+ if (UHD_FW_TRACE_LEVEL >= _trace_typecheck_conv(lvl)) UHD_FW_PRINTF(fmt);
+ #define UHD_FW_TRACE_FSTR_SHORT(lvl, fmt, ...) \
+ if (UHD_FW_TRACE_LEVEL >= _trace_typecheck_conv(lvl)) UHD_FW_PRINTF(fmt, __VA_ARGS__);
+#else
+ #define UHD_FW_TRACE(lvl, fmt) ;
+ #define UHD_FW_TRACE_FSTR(lvl, fmt, ...) ;
+ #define UHD_FW_TRACE_SHORT(lvl, fmt) ;
+ #define UHD_FW_TRACE_FSTR_SHORT(lvl, fmt, ...) ;
+#endif
+
+#endif /* INCLUDED_TRACE_H */
diff --git a/firmware/usrp3/lib/ethernet.c b/firmware/usrp3/lib/ethernet.c
index 7a86980c7..91efbfe1d 100644
--- a/firmware/usrp3/lib/ethernet.c
+++ b/firmware/usrp3/lib/ethernet.c
@@ -22,7 +22,7 @@
#include "../x300/x300_defs.h"
#include "ethernet.h"
#include "mdelay.h"
-#include "printf.h"
+#include <trace.h>
#include "wb_i2c.h"
#include "wb_utils.h"
//#include "memory_map.h"
@@ -225,7 +225,7 @@ xge_read_sfpp_type(const uint32_t base, const uint32_t delay_ms)
x = xge_i2c_rd(base, MODULE_DEV_ADDR, 3);
// I2C Error?
if (x < 0) {
- printf("DEBUG: I2C error in SFPP_TYPE.\n");
+ UHD_FW_TRACE(ERROR, "I2C error in SFPP_TYPE.");
return x;
}
// Decode module type. These registers and values are defined in SFF-8472
@@ -235,55 +235,55 @@ xge_read_sfpp_type(const uint32_t base, const uint32_t delay_ms)
}
if (x & 0x10)
{
- printf("DEBUG: SFFP_TYPE_SR.\n");
+ UHD_FW_TRACE(DEBUG, "SFFP_TYPE_SR.");
return SFFP_TYPE_SR;
}
if (x & 0x20)
{
- printf("DEBUG: SFFP_TYPE_LR.\n");
+ UHD_FW_TRACE(DEBUG, "SFFP_TYPE_LR.");
return SFFP_TYPE_LR;
}
if (x & 0x40)
{
- printf("DEBUG: SFFP_TYPE_LRM.\n");
+ UHD_FW_TRACE(DEBUG, "SFFP_TYPE_LRM.");
return SFFP_TYPE_LRM;
}
// Search for legacy 1000-Base SFP types
x = xge_i2c_rd(base, MODULE_DEV_ADDR, 0x6);
if (x < 0) {
- printf("DEBUG: I2C error in SFPP_TYPE.\n");
+ UHD_FW_TRACE(ERROR, "I2C error in SFPP_TYPE.");
return x;
}
if (x & 0x01) {
- printf("DEBUG: SFFP_TYPE_1000BASE_SX.\n");
+ UHD_FW_TRACE(DEBUG, "SFFP_TYPE_1000BASE_SX.");
return SFFP_TYPE_1000BASE_SX;
}
if (x & 0x02) {
- printf("DEBUG: SFFP_TYPE_1000BASE_LX.\n");
+ UHD_FW_TRACE(DEBUG, "SFFP_TYPE_1000BASE_LX.");
return SFFP_TYPE_1000BASE_LX;
}
if (x & 0x08) {
- printf("DEBUG: SFFP_TYPE_1000BASE_T.\n");
+ UHD_FW_TRACE(DEBUG, "SFFP_TYPE_1000BASE_T.");
return SFFP_TYPE_1000BASE_T;
}
// Not one of the standard optical types..now try to deduce if it's twinax aka 10GSFP+CU
// which is not covered explicitly in SFF-8472
x = xge_i2c_rd(base, MODULE_DEV_ADDR, 8);
if (x < 0) {
- printf("DEBUG: I2C error in SFPP_TYPE.\n");
+ UHD_FW_TRACE(ERROR, "I2C error in SFPP_TYPE.");
return x;
}
if ((x & 4) == 0) // Passive SFP+ cable type
goto unknown;
// x = xge_i2c_rd(MODULE_DEV_ADDR, 6);
-// printf("SFP+ reg6 read as %x\n",x);
+// UHD_FW_TRACE(DEBUG, "SFP+ reg6 read as %x",x);
// if (x < 0)
// return x;
// if (x != 0x04) // Returns 1000Base-CX as Compliance code
// goto unknown;
x = xge_i2c_rd(base, MODULE_DEV_ADDR, 0xA);
if (x < 0) {
- printf("DEBUG: I2C error in SFPP_TYPE.\n");
+ UHD_FW_TRACE(ERROR, "I2C error in SFPP_TYPE.");
return x;
}
if (x & 0x80) {
@@ -292,117 +292,124 @@ xge_read_sfpp_type(const uint32_t base, const uint32_t delay_ms)
x = xge_i2c_rd(base, MODULE_DEV_ADDR, 0x12);
if (x < 0) {
- printf("DEBUG: I2C error in SFPP_TYPE.\n");
+ UHD_FW_TRACE(ERROR, "I2C error in SFPP_TYPE.");
return x;
}
- printf("DEBUG: TwinAx.\n");
+ UHD_FW_TRACE(DEBUG, "TwinAx.");
// If cable length support is greater than 10M then pick correct type
return x > 10 ? SFFP_TYPE_TWINAX_LONG : SFFP_TYPE_TWINAX;
}
unknown:
- printf("DEBUG: Unknown SFP+ type.\n");
+ UHD_FW_TRACE(WARN, "Unknown SFP+ type.");
// Not a supported Module type
return SFFP_TYPE_UNKNOWN;
}
-
-// Pull reset line low for 100ms then release and wait 100ms
-static void
-xge_hard_phy_reset(const uint32_t base)
+static void xge_mac_init(const uint32_t base)
{
- wb_poke32(base, 1);
- mdelay(100);
- wb_poke32(base, 0);
- mdelay(100);
-
+ UHD_FW_TRACE(DEBUG, "Begining XGE MAC init sequence.");
+ xge_regs->config = XGE_TX_ENABLE;
}
-static void
-xge_mac_init(const uint32_t base)
+// base is pointer to XGE MAC on Wishbone.
+static void xge_phy_init(const uint8_t eth, const uint32_t mdio_port_arg)
{
- printf("INFO: Begining XGE MAC init sequence.\n");
- xge_regs->config = XGE_TX_ENABLE;
+ int x;
+ uint32_t mdio_port = eth==0 ? 1 : mdio_port_arg;
+ // Read LASI Ctrl register to capture state.
+ //y = xge_read_mdio(0x9002,XGE_MDIO_DEVICE_PMA,XGE_MDIO_ADDR_PHY_A);
+ UHD_FW_TRACE(DEBUG, "Begining XGE PHY init sequence.");
+ // Software reset
+ x = read_mdio(eth, 0x0, XGE_MDIO_DEVICE_PMA,mdio_port);
+ x = x | (1 << 15);
+ write_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port,x);
+ while(x&(1<<15)) {
+ x = read_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port);
+ }
}
-// base is pointer to XGE MAC on Wishbone.
-static void
-xge_phy_init(const uint8_t eth, const uint32_t mdio_port)
+void update_eth_state(const uint32_t eth)
{
- int x;
- // Read LASI Ctrl register to capture state.
- //y = xge_read_mdio(0x9002,XGE_MDIO_DEVICE_PMA,XGE_MDIO_ADDR_PHY_A);
- printf("INFO: Begining XGE PHY init sequence.\n");
- // Software reset
- x = read_mdio(eth, 0x0, XGE_MDIO_DEVICE_PMA,mdio_port);
- x = x | (1 << 15);
- write_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port,x);
- while(x&(1<<15))
- x = read_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port);
+ const bool old_link_up = links_up[eth];
+ const uint32_t status_reg_addr = (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1;
+ const bool is_10g = (wb_peek32(SR_ADDR(RB0_BASE, eth == 0 ? RB_ETH_TYPE0 : RB_ETH_TYPE1)) == 1);
+
+ uint32_t sfpp_status = wb_peek32(SR_ADDR(RB0_BASE, status_reg_addr)) & 0xFFFF;
+ if ((sfpp_status & (SFPP_STATUS_RXLOS|SFPP_STATUS_TXFAULT|SFPP_STATUS_MODABS)) == 0) {
+ //SFP+ pin state changed. Reinitialize PHY and MAC
+ if (is_10g) {
+ xge_mac_init((eth==0) ? XGE0_BASE : XGE1_BASE);
+ xge_phy_init(eth ,MDIO_PORT);
+ } else {
+ //No-op for 1G
+ }
+
+ int8_t timeout = 100;
+ bool link_up = false;
+ do {
+ if (is_10g) {
+ link_up = ((read_mdio(eth, XGE_MDIO_STATUS1,XGE_MDIO_DEVICE_PMA,MDIO_PORT)) & (1 << 2)) != 0;
+ } else {
+ link_up = ((wb_peek32(SR_ADDR(RB0_BASE, status_reg_addr)) >> 16) & 0x1) != 0;
+ }
+ } while (!link_up && timeout-- > 0);
+
+ links_up[eth] = link_up;
+ }
+ else
+ {
+ links_up[eth] = false;
+ }
+
+ if (!old_link_up && links_up[eth]) u3_net_stack_send_arp_request(eth, u3_net_stack_get_ip_addr(eth));
+ UHD_FW_TRACE_FSTR(INFO, "The link on eth port %u is %s", eth, links_up[eth]?"up":"down");
}
-void
-xge_poll_sfpp_status(const uint32_t eth)
+void poll_sfpp_status(const uint32_t eth)
{
- uint32_t x;
- // Has MODDET/MODAbS changed since we last looked?
- x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
-
- if (x & SFPP_STATUS_RXLOS_CHG)
- printf("DEBUG: eth%1d RXLOS changed state: %d\n", eth, x & SFPP_STATUS_RXLOS);
- if (x & SFPP_STATUS_TXFAULT_CHG)
- printf("DEBUG: eth%1d TXFAULT changed state: %d\n", eth,(x & SFPP_STATUS_TXFAULT) >> 1 );
- if (x & SFPP_STATUS_MODABS_CHG)
- printf("DEBUG: eth%1d MODABS changed state: %d\n", eth, (x & SFPP_STATUS_MODABS) >> 2);
-
- if (x & (SFPP_STATUS_RXLOS_CHG|SFPP_STATUS_TXFAULT_CHG|SFPP_STATUS_MODABS_CHG))
- {
- if (( x & (SFPP_STATUS_RXLOS|SFPP_STATUS_TXFAULT|SFPP_STATUS_MODABS)) == 0)
+ uint32_t x;
+ // Has MODDET/MODAbS changed since we last looked?
+ x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
+
+ if (x & SFPP_STATUS_RXLOS_CHG)
+ UHD_FW_TRACE_FSTR(DEBUG, "eth%1d RXLOS changed state: %d", eth, (x & SFPP_STATUS_RXLOS));
+ if (x & SFPP_STATUS_TXFAULT_CHG)
+ UHD_FW_TRACE_FSTR(DEBUG, "eth%1d TXFAULT changed state: %d", eth, ((x & SFPP_STATUS_TXFAULT) >> 1));
+ if (x & SFPP_STATUS_MODABS_CHG)
+ UHD_FW_TRACE_FSTR(DEBUG, "eth%1d MODABS changed state: %d", eth, ((x & SFPP_STATUS_MODABS) >> 2));
+
+ //update the link up status
+ if ((x & SFPP_STATUS_RXLOS_CHG) || (x & SFPP_STATUS_TXFAULT_CHG) || (x & SFPP_STATUS_MODABS_CHG))
{
- if (wb_peek32(SR_ADDR(RB0_BASE, eth == 0 ? RB_ETH_TYPE0 : RB_ETH_TYPE1)) == 1)
- {
- xge_ethernet_init(eth);
- dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
- mdelay(100);
- dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
- mdelay(100);
- dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
- }
+ update_eth_state(eth);
}
- }
- if (x & SFPP_STATUS_MODABS_CHG) {
- // MODDET has changed state since last checked
- if (x & SFPP_STATUS_MODABS) {
- // MODDET is high, module currently removed.
- printf("INFO: An SFP+ module has been removed from eth port %d.\n", eth);
- } else {
- // MODDET is low, module currently inserted.
- // Return status.
- printf("INFO: A new SFP+ module has been inserted into eth port %d.\n", eth);
- xge_read_sfpp_type((eth==0) ? I2C0_BASE : I2C2_BASE,1);
+ if (x & SFPP_STATUS_MODABS_CHG) {
+ // MODDET has changed state since last checked
+ if (x & SFPP_STATUS_MODABS) {
+ // MODDET is high, module currently removed.
+ UHD_FW_TRACE_FSTR(INFO, "An SFP+ module has been removed from eth port %d.", eth);
+ } else {
+ // MODDET is low, module currently inserted.
+ // Return status.
+ UHD_FW_TRACE_FSTR(INFO, "A new SFP+ module has been inserted into eth port %d.", eth);
+ xge_read_sfpp_type((eth==0) ? I2C0_BASE : I2C2_BASE,1);
+ }
}
- }
-
- //update the link up status
- const bool old_link_up = links_up[eth];
- links_up[eth] = ((read_mdio(eth, XGE_MDIO_STATUS1,XGE_MDIO_DEVICE_PMA,MDIO_PORT)) & (1 << 2)) != 0;
- //The link became up, send a GARP so everyone knows our mac/ip association
- if (!old_link_up && links_up[eth]) u3_net_stack_send_arp_request(eth, u3_net_stack_get_ip_addr(eth));
}
-
-void
-xge_ethernet_init(const uint32_t eth)
+void ethernet_init(const uint32_t eth)
{
- xge_mac_init((eth==0) ? XGE0_BASE : XGE1_BASE);
- //xge_hard_phy_reset();
- xge_phy_init(eth ,MDIO_PORT);
- uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
- printf(" eth%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d\n",
- eth,
- x & SFPP_STATUS_RXLOS,
- (x & SFPP_STATUS_TXFAULT) >> 1,
- (x & SFPP_STATUS_MODABS) >> 2);
+#ifdef UHD_FW_TRACE_LEVEL
+ uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
+ UHD_FW_TRACE_FSTR(DEBUG, "eth%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d",
+ eth,
+ (x & SFPP_STATUS_RXLOS),
+ ((x & SFPP_STATUS_TXFAULT) >> 1),
+ ((x & SFPP_STATUS_MODABS) >> 2));
+#endif
+ links_up[eth] = false;
+ update_eth_state(eth);
}
//
@@ -412,187 +419,179 @@ xge_ethernet_init(const uint32_t eth)
void decode_reg(uint32_t address, uint32_t device, uint32_t data)
{
+ UHD_FW_TRACE_FSTR(DEBUG,
+ "[MDIO Register Dump for Addr=%x, Device=%x]\n- Raw Value = %x",
+ address, device, data);
int x;
- printf("Device: ");
- printf("%x",device);
- printf(" ");
switch(address) {
case XGE_MDIO_CONTROL1:
- printf("CONTROL1: ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "CONTROL1: %x = ", data);
for (x=15; x >= 0 ; x--)
if ((data & (1 << x)) != 0)
// Bits set.
switch(x) {
- case 15: printf("Reset,"); break;
- case 14: printf("Loopback,"); break;
- case 11: printf("Low Power Mode,"); break;
- case 5:case 4:case 3:case 2: printf("RESERVED speed value,"); break;
- case 0: printf("PMA loopback,"); break;
+ case 15: UHD_FW_TRACE_SHORT(DEBUG, "Reset,"); break;
+ case 14: UHD_FW_TRACE_SHORT(DEBUG, "Loopback,"); break;
+ case 11: UHD_FW_TRACE_SHORT(DEBUG, "Low Power Mode,"); break;
+ case 5:case 4:case 3:case 2: UHD_FW_TRACE_SHORT(DEBUG, "RESERVED speed value,"); break;
+ case 0: UHD_FW_TRACE_SHORT(DEBUG, "PMA loopback,"); break;
} //else
// Bits clear.
//switch (x) {
- //case 13: case 6: printf(" None 10Gb/s speed set!"); break;
+ //case 13: case 6: UHD_FW_TRACE_SHORT(DEBUG, " None 10Gb/s speed set!"); break;
//}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XGE_MDIO_STATUS1:
- printf("STATUS1: ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "STATUS1: %x = ", data);
for (x=15; x >= 0 ; x--)
if ((data & (1 << x)) != 0)
// Bits set.
switch(x) {
- case 7: printf("Fault Detected,"); break;
- case 2: printf("Link is Up,"); break;
- case 1: printf("Supports Low Power,"); break;
+ case 7: UHD_FW_TRACE_SHORT(DEBUG, "Fault Detected,"); break;
+ case 2: UHD_FW_TRACE_SHORT(DEBUG, "Link is Up,"); break;
+ case 1: UHD_FW_TRACE_SHORT(DEBUG, "Supports Low Power,"); break;
} else
// Bits Clear
switch(x) {
- case 2: printf("Link is Down,"); break;
+ case 2: UHD_FW_TRACE_SHORT(DEBUG, "Link is Down,"); break;
}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XGE_MDIO_SPEED:
- printf("SPEED ABILITY: ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "SPEED ABILITY: %x = ", data);
for (x=15; x >= 0 ; x--)
if ((data & (1 << x)) != 0)
// Bits set.
switch(x) {
case 15:case 14:case 13:case 12:case 11:case 10:case 9:
- case 8:case 7:case 6:case 5:case 4:case 3:case 2:case 1: printf("RESERVED bits set!,"); break;
- case 0: printf("Capable of 10Gb/s,");
+ case 8:case 7:case 6:case 5:case 4:case 3:case 2:case 1: UHD_FW_TRACE_SHORT(DEBUG, "RESERVED bits set!,"); break;
+ case 0: UHD_FW_TRACE_SHORT(DEBUG, "Capable of 10Gb/s,");
} else
// Bits clear.
switch(x) {
- case 0: printf("Incapable of 10Gb/s,"); break;
+ case 0: UHD_FW_TRACE_SHORT(DEBUG, "Incapable of 10Gb/s,"); break;
}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XGE_MDIO_DEVICES1:
- printf("DEVICES IN PACKAGE: ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "DEVICES IN PACKAGE: %x = ", data);
for (x=15; x >= 0 ; x--)
if ((data & (1 << x)) != 0)
// Bits set.
switch(x) {
- case 7: printf("Auto-Negotiation,"); break;
- case 6: printf("TC,"); break;
- case 5: printf("DTE XS,"); break;
- case 4: printf("PHY XS,"); break;
- case 3: printf("PCS,"); break;
- case 2: printf("WIS,"); break;
- case 1: printf("PMD/PMA,"); break;
- case 0: printf("Clause 22 registers,"); break;
+ case 7: UHD_FW_TRACE_SHORT(DEBUG, "Auto-Negotiation,"); break;
+ case 6: UHD_FW_TRACE_SHORT(DEBUG, "TC,"); break;
+ case 5: UHD_FW_TRACE_SHORT(DEBUG, "DTE XS,"); break;
+ case 4: UHD_FW_TRACE_SHORT(DEBUG, "PHY XS,"); break;
+ case 3: UHD_FW_TRACE_SHORT(DEBUG, "PCS,"); break;
+ case 2: UHD_FW_TRACE_SHORT(DEBUG, "WIS,"); break;
+ case 1: UHD_FW_TRACE_SHORT(DEBUG, "PMD/PMA,"); break;
+ case 0: UHD_FW_TRACE_SHORT(DEBUG, "Clause 22 registers,"); break;
}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XGE_MDIO_DEVICES2:
- printf("DEVICES IN PACKAGE (cont): ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "DEVICES IN PACKAGE (cont): %x = ", data);
for (x=15; x >= 0 ; x--)
if ((data & (1 << x)) != 0)
// Bits set.
switch(x) {
- case 15: printf("Vendor device 2,"); break;
- case 14: printf("Vendor device 1,"); break;
- case 13: printf("Clause 22 extension,"); break;
+ case 15: UHD_FW_TRACE_SHORT(DEBUG, "Vendor device 2,"); break;
+ case 14: UHD_FW_TRACE_SHORT(DEBUG, "Vendor device 1,"); break;
+ case 13: UHD_FW_TRACE_SHORT(DEBUG, "Clause 22 extension,"); break;
}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XGE_MDIO_CONTROL2:
- printf("CONTROL2: ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "CONTROL2: %x = ", data);
// PMA/PMD
if (device == XGE_MDIO_DEVICE_PMA)
switch((data & 0xf)) {
- case 0xF: printf("10BASE-T,"); break;
- case 0xE: printf("100BASE-TX,"); break;
- case 0xD: printf("1000BASE-KX,"); break;
- case 0xC: printf("1000BASE-T,"); break;
- case 0xB: printf("10GBASE-KR,"); break;
- case 0xA: printf("10GBASE-KX4,"); break;
- case 0x9: printf("10GBASE-T,"); break;
- case 0x8: printf("10GBASE-LRM,"); break;
- case 0x7: printf("10GBASE-SR,"); break;
- case 0x6: printf("10GBASE-LR,"); break;
- case 0x5: printf("10GBASE-ER,"); break;
- case 0x4: printf("10GBASE-LX4,"); break;
- // case 0x3: printf("10GBASE-SW,"); break;
- // case 0x2: printf("10GBASE-LW,"); break;
- // case 0x1: printf("10GBASE-EW,"); break;
- case 0x0: printf("10GBASE-CX4,"); break;
+ case 0xF: UHD_FW_TRACE_SHORT(DEBUG, "10BASE-T,"); break;
+ case 0xE: UHD_FW_TRACE_SHORT(DEBUG, "100BASE-TX,"); break;
+ case 0xD: UHD_FW_TRACE_SHORT(DEBUG, "1000BASE-KX,"); break;
+ case 0xC: UHD_FW_TRACE_SHORT(DEBUG, "1000BASE-T,"); break;
+ case 0xB: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-KR,"); break;
+ case 0xA: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-KX4,"); break;
+ case 0x9: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-T,"); break;
+ case 0x8: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-LRM,"); break;
+ case 0x7: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-SR,"); break;
+ case 0x6: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-LR,"); break;
+ case 0x5: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-ER,"); break;
+ case 0x4: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-LX4,"); break;
+ // case 0x3: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-SW,"); break;
+ // case 0x2: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-LW,"); break;
+ // case 0x1: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-EW,"); break;
+ case 0x0: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-CX4,"); break;
} else if (device == XGE_MDIO_DEVICE_PCS)
// PCS
switch((data & 0x3)) {
- case 0x3: printf("10GBASE-T PCS,"); break;
- case 0x2: printf("10GBASE-W PCS,"); break;
- case 0x1: printf("10GBASE-X PCS,"); break;
- case 0x0: printf("10GBASE-R PCS,"); break;
+ case 0x3: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-T PCS,"); break;
+ case 0x2: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-W PCS,"); break;
+ case 0x1: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-X PCS,"); break;
+ case 0x0: UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-R PCS,"); break;
}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XGE_MDIO_STATUS2:
- printf("STATUS2: ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "STATUS2: %x = ", data);
for (x=15; x >= 0 ; x--)
if ((data & (1 << x)) != 0)
// Bits set.
switch(x) {
- case 15: if ((data & (1 << 14)) == 0) printf("Device responding,"); break;
- case 13: if (device == XGE_MDIO_DEVICE_PMA) printf("Able detect a Tx fault,"); break;
- case 12: if (device == XGE_MDIO_DEVICE_PMA) printf("Able detect an Rx fault,"); break;
- case 11: printf("Fault on Tx path,"); break;
- case 10: printf("Fault on Rx path,"); break;
- case 9: if (device == XGE_MDIO_DEVICE_PMA) printf("Extended abilities in Reg1.11,"); break;
- case 8: if (device == XGE_MDIO_DEVICE_PMA) printf("Able to disable TX,"); break;
- case 7: if (device == XGE_MDIO_DEVICE_PMA) printf("10GBASE-SR,"); break;
- case 6: if (device == XGE_MDIO_DEVICE_PMA) printf("10GBASE-LR,"); break;
- case 5: if (device == XGE_MDIO_DEVICE_PMA) printf("10GBASE-ER,"); break;
- case 4: if (device == XGE_MDIO_DEVICE_PMA) printf("10GBASE-LX4,"); break;
- case 3: if (device == XGE_MDIO_DEVICE_PMA) printf("10GBASE-SW,"); break;
- case 2: if (device == XGE_MDIO_DEVICE_PMA) printf("10GBASE-LW,"); break;
- case 1: if (device == XGE_MDIO_DEVICE_PMA) printf("10GBASE-EW,"); break;
- case 0: if (device == XGE_MDIO_DEVICE_PMA) printf("loopback,"); break;
+ case 15: if ((data & (1 << 14)) == 0) UHD_FW_TRACE_SHORT(DEBUG, "Device responding,"); break;
+ case 13: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "Able detect a Tx fault,"); break;
+ case 12: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "Able detect an Rx fault,"); break;
+ case 11: UHD_FW_TRACE_SHORT(DEBUG, "Fault on Tx path,"); break;
+ case 10: UHD_FW_TRACE_SHORT(DEBUG, "Fault on Rx path,"); break;
+ case 9: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "Extended abilities in Reg1.11,"); break;
+ case 8: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "Able to disable TX,"); break;
+ case 7: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-SR,"); break;
+ case 6: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-LR,"); break;
+ case 5: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-ER,"); break;
+ case 4: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-LX4,"); break;
+ case 3: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-SW,"); break;
+ case 2: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-LW,"); break;
+ case 1: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "10GBASE-EW,"); break;
+ case 0: if (device == XGE_MDIO_DEVICE_PMA) UHD_FW_TRACE_SHORT(DEBUG, "loopback,"); break;
}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XGE_MDIO_LANESTATUS:
- printf("LANE STATUS: ");
- printf("%x",data); printf(" ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "LANE STATUS: %x = ", data);
for (x=15; x >= 0 ; x--)
if ((data & (1 << x)) != 0)
// Bits set.
switch(x) {
- case 12: printf("Lanes aligned,"); break;
- case 11: printf("Able to generate test patterns,"); break;
- case 3: printf("Lane 3 synced,"); break;
- case 2: printf("Lane 2 synced,"); break;
- case 1: printf("Lane 1 synced,"); break;
- case 0: printf("Lane 0 synced,"); break;
+ case 12: UHD_FW_TRACE_SHORT(DEBUG, "Lanes aligned,"); break;
+ case 11: UHD_FW_TRACE_SHORT(DEBUG, "Able to generate test patterns,"); break;
+ case 3: UHD_FW_TRACE_SHORT(DEBUG, "Lane 3 synced,"); break;
+ case 2: UHD_FW_TRACE_SHORT(DEBUG, "Lane 2 synced,"); break;
+ case 1: UHD_FW_TRACE_SHORT(DEBUG, "Lane 1 synced,"); break;
+ case 0: UHD_FW_TRACE_SHORT(DEBUG, "Lane 0 synced,"); break;
} else
// Bits clear
switch(x) {
- case 3: printf("Lane 3 not synced,"); break;
- case 2: printf("Lane 2 not synced,"); break;
- case 1: printf("Lane 1 not synced,"); break;
- case 0: printf("Lane 0 not synced,"); break;
+ case 3: UHD_FW_TRACE_SHORT(DEBUG, "Lane 3 not synced,"); break;
+ case 2: UHD_FW_TRACE_SHORT(DEBUG, "Lane 2 not synced,"); break;
+ case 1: UHD_FW_TRACE_SHORT(DEBUG, "Lane 1 not synced,"); break;
+ case 0: UHD_FW_TRACE_SHORT(DEBUG, "Lane 0 not synced,"); break;
}
- printf(" \n");
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
break;
case XILINX_CORE_VERSION:
- printf("XILINX CORE VERSION: %x ",data);
- printf("Version: %d.%d ",(data&0xf000)>>12,(data&0xf00)>>8);
- printf("Patch: %d ",(data&0xE)>>1);
- if (data&0x1) printf("Evaluation Version of core");
- printf("\n");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "XILINX CORE VERSION: %x ",data);
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "Version: %d.%d ",((data&0xf000)>>12),((data&0xf00)>>8));
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "Patch: %d ",((data&0xE)>>1));
+ UHD_FW_TRACE_SHORT(DEBUG, " \n");
+ if (data&0x1) UHD_FW_TRACE(WARN, "Evaluation Version of core");
break;
default:
- printf("Register @ address: ");
- printf("%x",address);
- printf(" has value: ");
- printf("%x\n",data);
+ UHD_FW_TRACE_SHORT(DEBUG, "Register @ address: ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "%x",address);
+ UHD_FW_TRACE_SHORT(DEBUG, " has value: ");
+ UHD_FW_TRACE_FSTR_SHORT(DEBUG, "%x\n",data);
break;
}
}
@@ -605,7 +604,6 @@ dump_mdio_regs(const uint8_t eth, uint32_t mdio_port)
unsigned int regs_a[9] = {0,1,4,5,6,7,8,32,33};
unsigned int regs_b[10] = {0,1,4,5,6,7,8,10,11,65535};
- printf("\n");
for (y = 0; y < 10; y++)
{
@@ -621,7 +619,6 @@ dump_mdio_regs(const uint8_t eth, uint32_t mdio_port)
decode_reg(regs_a[y],XGE_MDIO_DEVICE_PCS,x);
}
- printf("\n");
/* for (y = 0; y < 8; y++) */
/* { */
diff --git a/firmware/usrp3/lib/u3_net_stack.c b/firmware/usrp3/lib/u3_net_stack.c
index 6b8ef096c..16eb0f9fe 100644
--- a/firmware/usrp3/lib/u3_net_stack.c
+++ b/firmware/usrp3/lib/u3_net_stack.c
@@ -3,7 +3,7 @@
#include <u3_net_stack.h>
#include <string.h> //memcmp
-#include <printf.h>
+#include <trace.h>
#define MAX_NETHS 4
@@ -281,7 +281,7 @@ void u3_net_stack_send_arp_request(const uint8_t ethno, const struct ip_addr *ad
static void handle_arp_packet(const uint8_t ethno, const struct arp_eth_ipv4 *p)
{
- //printf("handle_arp_packet\n");
+ UHD_FW_TRACE(DEBUG, "handle_arp_packet");
if (p->ar_hrd != ARPHRD_ETHER
|| p->ar_pro != ETHERTYPE_IPV4
|| p->ar_hln != sizeof(eth_mac_addr_t)
@@ -291,7 +291,7 @@ static void handle_arp_packet(const uint8_t ethno, const struct arp_eth_ipv4 *p)
//got an arp reply -- injest it into the arp cache
if (p->ar_op == ARPOP_REPLY)
{
- //printf("ARPOP_REPLY\n");
+ UHD_FW_TRACE(DEBUG, "ARPOP_REPLY");
struct ip_addr ip_addr;
memcpy(&ip_addr, p->ar_sip, sizeof(ip_addr));
eth_mac_addr_t mac_addr;
@@ -302,7 +302,7 @@ static void handle_arp_packet(const uint8_t ethno, const struct arp_eth_ipv4 *p)
//got an arp request -- reply if its for our address
if (p->ar_op == ARPOP_REQUEST)
{
- //printf("ARPOP_REQUEST\n");
+ UHD_FW_TRACE(DEBUG, "ARPOP_REQUEST");
if (memcmp(p->ar_tip, u3_net_stack_get_ip_addr(ethno), sizeof(struct ip_addr)) == 0)
{
send_arp_reply(ethno, p, u3_net_stack_get_mac_addr(ethno));
@@ -344,7 +344,7 @@ void u3_net_stack_send_udp_pkt(
eth_mac_addr_t dst_mac_addr;
if (!resolve_ip(dst, &dst_mac_addr))
{
- printf("u3_net_stack_send_udp_pkt arp_cache_lookup fail\n");
+ UHD_FW_TRACE(WARN, "u3_net_stack_send_udp_pkt arp_cache_lookup fail");
return;
}
@@ -396,7 +396,7 @@ static void handle_udp_packet(
return;
}
}
- printf("Unhandled UDP packet src=%u, dest=%u\n", udp->src, udp->dest);
+ UHD_FW_TRACE_FSTR(ERROR, "Unhandled UDP packet src=%u, dest=%u", udp->src, udp->dest);
//TODO send destination unreachable
}
@@ -445,7 +445,7 @@ static void handle_icmp_packet(
return;
}
}
- printf("Unhandled ICMP packet type=%u\n", icmp->type);
+ UHD_FW_TRACE_FSTR(ERROR, "Unhandled ICMP packet type=%u", icmp->type);
}
static void handle_icmp_dur_packet(
@@ -484,7 +484,7 @@ void u3_net_stack_send_icmp_pkt(
eth_mac_addr_t dst_mac_addr;
if (!resolve_ip(dst, &dst_mac_addr))
{
- printf("u3_net_stack_send_echo_request arp_cache_lookup fail\n");
+ UHD_FW_TRACE(WARN, "u3_net_stack_send_echo_request arp_cache_lookup fail");
return;
}
@@ -533,17 +533,17 @@ static void handle_eth_packet(const void *buff, const size_t num_bytes)
{
const padded_eth_hdr_t *eth_hdr = (padded_eth_hdr_t *)buff;
const uint8_t *eth_body = ((const uint8_t *)buff) + sizeof(padded_eth_hdr_t);
- //printf("handle_eth_packet got ethertype 0x%x\n", (unsigned)eth_hdr->ethertype);
+ UHD_FW_TRACE_FSTR(DEBUG, "handle_eth_packet got ethertype 0x%x", (unsigned)eth_hdr->ethertype);
if (eth_hdr->ethertype == ETHERTYPE_ARP)
{
- //printf("eth_hdr->ethertype == ETHERTYPE_ARP\n");
+ UHD_FW_TRACE(DEBUG, "eth_hdr->ethertype == ETHERTYPE_ARP");
const struct arp_eth_ipv4 *arp = (const struct arp_eth_ipv4 *)eth_body;
handle_arp_packet(eth_hdr->ethno, arp);
}
else if (eth_hdr->ethertype == ETHERTYPE_IPV4)
{
- //printf("eth_hdr->ethertype == ETHERTYPE_IPV4\n");
+ UHD_FW_TRACE(DEBUG, "eth_hdr->ethertype == ETHERTYPE_IPV4");
const struct ip_hdr *ip = (const struct ip_hdr *)eth_body;
const uint8_t *ip_body = eth_body + IP_HLEN;
@@ -572,7 +572,7 @@ static void handle_eth_packet(const void *buff, const size_t num_bytes)
);
}
}
- else return; // Not ARP or IPV4, ignore
+ else return; // Not ARP or IPV4, ignore
}
void u3_net_stack_handle_one(void)
@@ -581,7 +581,7 @@ void u3_net_stack_handle_one(void)
const void *ptr = wb_pkt_iface64_rx_try_claim(pkt_iface_config, &num_bytes);
if (ptr != NULL)
{
- //printf("u3_net_stack_handle_one got %u bytes\n", (unsigned)num_bytes);
+ UHD_FW_TRACE_FSTR(DEBUG, "u3_net_stack_handle_one got %u bytes", (unsigned)num_bytes);
incr_stat_counts(ptr);
handle_eth_packet(ptr, num_bytes);
wb_pkt_iface64_rx_release(pkt_iface_config);
diff --git a/firmware/usrp3/x300/x300_defs.h b/firmware/usrp3/x300/x300_defs.h
index 65c5d5a23..c4011bd12 100644
--- a/firmware/usrp3/x300/x300_defs.h
+++ b/firmware/usrp3/x300/x300_defs.h
@@ -51,6 +51,7 @@ static const int RB_SPI_RDY = 1;
static const int RB_SPI_DATA = 2;
static const int RB_ETH_TYPE0 = 4;
static const int RB_ETH_TYPE1 = 5;
+static const int RB_FPGA_COMPAT = 6;
static const int RB_SFPP_STATUS0 = 8;
static const int RB_SFPP_STATUS1 = 9;
diff --git a/firmware/usrp3/x300/x300_init.c b/firmware/usrp3/x300/x300_init.c
index 66fb120f3..ef97412a2 100644
--- a/firmware/usrp3/x300/x300_init.c
+++ b/firmware/usrp3/x300/x300_init.c
@@ -7,7 +7,7 @@
#include <wb_i2c.h>
#include <stdint.h>
#include <stdbool.h>
-#include <printf.h>
+#include <trace.h>
#include <wb_pkt_iface64.h>
#include <u3_net_stack.h>
#include <link_state_route_proto.h>
@@ -73,7 +73,6 @@ const void *pick_inited_field(const void *eeprom, const void *def, const size_t
static void init_network(void)
{
pkt_config = wb_pkt_iface64_init(PKT_RAM0_BASE, 0x1ffc);
- printf("PKT RAM0 BASE 0x%x\n", (&pkt_config)->base);
u3_net_stack_init(&pkt_config);
link_state_route_proto_init();
@@ -115,7 +114,9 @@ static void init_network(void)
static void putc(void *p, char c)
{
-#ifdef X300_DEBUG_UART
+//If FW_TRACE_LEVEL is defined, then the trace level is set
+//to a non-zero number. Turn on the debug UART to enable tracing
+#ifdef UHD_FW_TRACE_LEVEL
wb_uart_putc(UART1_BASE, c);
#endif
}
@@ -129,7 +130,11 @@ void x300_init(void)
//udp_uart_init(UART0_BASE, X300_GPSDO_UDP_PORT);
//now we can init the rest with prints
- printf("X300 ZPU Init Begin -- CPU CLOCK is %d MHz\n", CPU_CLOCK/1000000);
+ UHD_FW_TRACE(INFO, "[ZPU Initializing]");
+ UHD_FW_TRACE_FSTR(INFO, "-- Firmware Compat Number: %u.%u", (int)X300_FW_COMPAT_MAJOR, (int)X300_FW_COMPAT_MINOR);
+ uint32_t fpga_compat = wb_peek32(SR_ADDR(SET0_BASE, RB_FPGA_COMPAT));
+ UHD_FW_TRACE_FSTR(INFO, "-- FPGA Compat Number: %u.%u", (fpga_compat>>16), (fpga_compat&0xFFFF));
+ UHD_FW_TRACE_FSTR(INFO, "-- Clock Frequency: %u MHz", (CPU_CLOCK/1000000));
//i2c rate init
wb_i2c_init(I2C0_BASE, CPU_CLOCK);
@@ -139,30 +144,26 @@ void x300_init(void)
//hold phy in reset
wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), SW_RST_PHY);
- printf("DEBUG: eth0 is %2dG\n",(wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE0))==1) ? 10 : 1);
- printf("DEBUG: eth1 is %2dG\n",(wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE1))==1) ? 10 : 1);
-
//setup net stack and eth state machines
init_network();
//phy reset release
wb_poke32(SR_ADDR(SET0_BASE, SR_SW_RST), 0);
- // For eth interfaces, initialize the PHY's
- mdelay(100);
- if (wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE0)) == 1) {
- xge_ethernet_init(0);
- }
- if (wb_peek32(SR_ADDR(RB0_BASE, RB_ETH_TYPE1)) == 1) {
- xge_ethernet_init(1);
- }
-
//print network summary
for (uint8_t e = 0; e < ethernet_ninterfaces(); e++)
{
- printf(" MAC%u: %s\n", (int)e, mac_addr_to_str(u3_net_stack_get_mac_addr(e)));
- printf(" IP%u: %s\n", (int)e, ip_addr_to_str(u3_net_stack_get_ip_addr(e)));
- printf(" SUBNET%u: %s\n", (int)e, ip_addr_to_str(u3_net_stack_get_subnet(e)));
- printf(" BCAST%u: %s\n", (int)e, ip_addr_to_str(u3_net_stack_get_bcast(e)));
+ uint32_t offset = SR_ADDR(RB0_BASE, ((e==1)?RB_ETH_TYPE1:RB_ETH_TYPE0));
+ UHD_FW_TRACE_FSTR(INFO, "Ethernet Port %u:", (int)e);
+ UHD_FW_TRACE_FSTR(INFO, "-- PHY: %s", ((wb_peek32(offset)==1) ? "10Gbps" : "1Gbps"));
+ UHD_FW_TRACE_FSTR(INFO, "-- MAC: %s", mac_addr_to_str(u3_net_stack_get_mac_addr(e)));
+ UHD_FW_TRACE_FSTR(INFO, "-- IP: %s", ip_addr_to_str(u3_net_stack_get_ip_addr(e)));
+ UHD_FW_TRACE_FSTR(INFO, "-- SUBNET: %s", ip_addr_to_str(u3_net_stack_get_subnet(e)));
+ UHD_FW_TRACE_FSTR(INFO, "-- BCAST: %s", ip_addr_to_str(u3_net_stack_get_bcast(e)));
}
+
+ // For eth interfaces, initialize the PHY's
+ mdelay(100);
+ ethernet_init(0);
+ ethernet_init(1);
}
diff --git a/firmware/usrp3/x300/x300_main.c b/firmware/usrp3/x300/x300_main.c
index d865e1d09..3b812a2c4 100644
--- a/firmware/usrp3/x300/x300_main.c
+++ b/firmware/usrp3/x300/x300_main.c
@@ -13,7 +13,7 @@
#include <udp_uart.h>
#include <u3_net_stack.h>
#include <link_state_route_proto.h>
-#include <printf.h>
+#include <trace.h>
#include <string.h>
#include <print_addrs.h>
@@ -33,7 +33,7 @@ void program_udp_framer(
const eth_mac_addr_t *dst_mac = u3_net_stack_arp_cache_lookup(dst_ip);
const size_t ethbase = (ethno == 0)? SR_ETHINT0 : SR_ETHINT1;
const size_t vdest = (sid >> 16) & 0xff;
- printf("handle_udp_prog_framer sid %u vdest %u\n", sid, vdest);
+ UHD_FW_TRACE_FSTR(INFO, "handle_udp_prog_framer sid %u vdest %u\n", sid, vdest);
//setup source framer
const eth_mac_addr_t *src_mac = u3_net_stack_get_mac_addr(ethno);
@@ -204,7 +204,7 @@ void handle_udp_mtu_detect(
if (buff == NULL) {
return;
} else if (!(request->flags & X300_MTU_DETECT_ECHO_REQUEST)) {
- printf("DEBUG: MTU detect got unknown request\n");
+ UHD_FW_TRACE(WARN, "MTU detect got unknown request");
reply.flags |= X300_MTU_DETECT_ERROR;
}
@@ -445,12 +445,12 @@ int main(void)
static const uint32_t tick_delta = CPU_CLOCK/1000;
if (ticks_passed > tick_delta)
{
+ poll_sfpp_status(0); // Every so often poll XGE Phy to look for SFP+ hotplug events.
+ poll_sfpp_status(1); // Every so often poll XGE Phy to look for SFP+ hotplug events.
handle_link_state(); //deal with router table update
handle_claim(); //deal with the host claim register
update_leds(); //run the link and activity leds
garp(); //send periodic garps
- xge_poll_sfpp_status(0); // Every so often poll XGE Phy to look for SFP+ hotplug events.
- xge_poll_sfpp_status(1); // Every so often poll XGE Phy to look for SFP+ hotplug events.
last_cronjob = wb_peek32(SR_ADDR(RB0_BASE, RB_COUNTER));
}