First pass of logic analyzer functionality (GPMC interface and server)

master
Timothy Pearson 10 years ago
parent 1fbfe13066
commit 6ed57d34ca

@ -113,6 +113,7 @@ static void gpmc_setup(void)
*(gpmc + displacement + GPMC_CONFIG) = 0x00000000; // Unlimited address space
*(gpmc + displacement + GPMC_CONFIG1) = 0x00000000; // No burst, async, 8-bit, non multiplexed
// *(gpmc + displacement + GPMC_CONFIG1) = 0x00000010; // No burst, async, 8-bit, non multiplexed, x2 slowed cycle timing
// // 200MHz compatible SRAM device
// *(gpmc + displacement + GPMC_CONFIG2) = 0x00000800; // Assert CS on fclk 0, deassert CS on fclk 8
@ -139,6 +140,27 @@ static void gpmc_setup(void)
}
}
void gpmc_dump_registers(void)
{
gpmc_mapregisters();
if (gpmc != NULL) {
int chipselect = 0;
int displacement = GPMC_CHIPSELECTCONFIGDISPLACEMENT * chipselect;
printf("GPMC_CONFIG0: %08x\n", *(gpmc + displacement + GPMC_CONFIG));
printf("GPMC_CONFIG1: %08x\n", *(gpmc + displacement + GPMC_CONFIG1));
printf("GPMC_CONFIG2: %08x\n", *(gpmc + displacement + GPMC_CONFIG2));
printf("GPMC_CONFIG3: %08x\n", *(gpmc + displacement + GPMC_CONFIG3));
printf("GPMC_CONFIG4: %08x\n", *(gpmc + displacement + GPMC_CONFIG4));
printf("GPMC_CONFIG5: %08x\n", *(gpmc + displacement + GPMC_CONFIG5));
printf("GPMC_CONFIG6: %08x\n", *(gpmc + displacement + GPMC_CONFIG6));
printf("GPMC_CONFIG7: %08x\n", *(gpmc + displacement + GPMC_CONFIG7));
}
gpmc_unmapregisters();
}
static void io_setup(void)
{
printf("sizeof int:\t%d\n", sizeof(int));
@ -343,12 +365,14 @@ static void io_setup(void)
// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\n\r", *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0), *(gpio_char + 0));
//
gpmc_dump_registers();
while (1) {
// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0), *(gpio_char + 1), *(gpio_char + 2), *(gpio_char + 3), *(gpio_char + 4), *(gpio_char + 5), *(gpio_char + 6), *(gpio_char + 7));
// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0), *(gpio_char + 1), *(gpio_char + 2), *(gpio_char + 3), *(gpio_char + 0x1000), *(gpio_char + 0x1001), *(gpio_char + 0x1002), *(gpio_char + 0x1003));
// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0), *(gpio_char + 1), *(gpio_char + 2), *(gpio_char + 3), *(gpio_char + 0x4000), *(gpio_char + 0x4001), *(gpio_char + 0x4002), *(gpio_char + 0x4003));
printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0), *(gpio_char + 1), *(gpio_char + 2), *(gpio_char + 3), *(gpio_char + 0x0a), *(gpio_char + 0x0b), *(gpio_char + 0x0c), *(gpio_char + 0x0d));
// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0x4000), *(gpio_char + 0x4001), *(gpio_char + 0x4002), *(gpio_char + 0x4003), *(gpio_char + 0x4000), *(gpio_char + 0x4001), *(gpio_char + 0x4002), *(gpio_char + 0x4003));
// printf("0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\t0x%02x\r", *(gpio_char + 0x4000), *(gpio_char + 0x4001), *(gpio_char + 0x4002), *(gpio_char + 0x4003), *(gpio_char + 0x4004), *(gpio_char + 0x4005), *(gpio_char + 0x4006), *(gpio_char + 0x4007));
usleep(10);
}
}

@ -28,6 +28,7 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
@ -61,7 +62,6 @@ char *gpio_mem, *gpio_map, *gpmc_map;
// I/O access
volatile unsigned int *gpio = NULL;
volatile unsigned char *gpio_char = NULL;
volatile unsigned char *gpio_llong = NULL;
volatile unsigned int *gpmc = NULL;
void gpmc_mapregisters() {
@ -171,12 +171,44 @@ unsigned char read_gpmc(unsigned int register_offset) {
return *(gpio_char + register_offset);
}
void write_gpmc_llong(unsigned int register_offset, unsigned long long data) {
*(gpio_char + register_offset) = data;
void write_gpmc_uint16_t(unsigned int register_offset, uint16_t data) {
register_offset = register_offset * 2;
*(gpio_char + register_offset + 0) = ((data & 0xff00) >> 8);
*(gpio_char + register_offset + 1) = ((data & 0x00ff) >> 0);
}
unsigned long long read_gpmc_llong(unsigned int register_offset) {
return *(gpio_char + register_offset);
uint16_t read_gpmc_uint16_t(unsigned int register_offset) {
uint16_t result = 0;
register_offset = register_offset * 2;
result = result | ((uint16_t)(*(gpio_char + register_offset + 0)) << 8);
result = result | ((uint16_t)(*(gpio_char + register_offset + 1)) << 0);
return result;
}
void write_gpmc_uint64_t(unsigned int register_offset, uint64_t data) {
register_offset = register_offset * 8;
*(gpio_char + register_offset + 0) = ((data & 0xff00000000000000) >> 56);
*(gpio_char + register_offset + 1) = ((data & 0x00ff000000000000) >> 48);
*(gpio_char + register_offset + 2) = ((data & 0x0000ff0000000000) >> 40);
*(gpio_char + register_offset + 3) = ((data & 0x000000ff00000000) >> 32);
*(gpio_char + register_offset + 4) = ((data & 0x00000000ff000000) >> 24);
*(gpio_char + register_offset + 5) = ((data & 0x0000000000ff0000) >> 16);
*(gpio_char + register_offset + 6) = ((data & 0x000000000000ff00) >> 8);
*(gpio_char + register_offset + 7) = ((data & 0x00000000000000ff) >> 0);
}
uint64_t read_gpmc_uint64_t(unsigned int register_offset) {
uint64_t result = 0;
register_offset = register_offset * 8;
result = result | ((uint64_t)(*(gpio_char + register_offset + 0)) << 56);
result = result | ((uint64_t)(*(gpio_char + register_offset + 1)) << 48);
result = result | ((uint64_t)(*(gpio_char + register_offset + 2)) << 40);
result = result | ((uint64_t)(*(gpio_char + register_offset + 3)) << 32);
result = result | ((uint64_t)(*(gpio_char + register_offset + 4)) << 24);
result = result | ((uint64_t)(*(gpio_char + register_offset + 5)) << 16);
result = result | ((uint64_t)(*(gpio_char + register_offset + 6)) << 8);
result = result | ((uint64_t)(*(gpio_char + register_offset + 7)) << 0);
return result;
}
void memcpy_from_gpmc(char* destination, unsigned int register_offset, unsigned int length) {

@ -25,8 +25,11 @@ int setup_gpmc_bbb();
void write_gpmc(unsigned int register_offset, unsigned char data);
unsigned char read_gpmc(unsigned int register_offset);
void write_gpmc_llong(unsigned int register_offset, unsigned long long data);
unsigned long long read_gpmc_llong(unsigned int register_offset);
void write_gpmc_uint16_t(unsigned int register_offset, uint16_t data);
uint16_t read_gpmc_uint16_t(unsigned int register_offset);
void write_gpmc_uint64_t(unsigned int register_offset, uint64_t data);
uint64_t read_gpmc_uint64_t(unsigned int register_offset);
void memcpy_from_gpmc(char* destination, unsigned int register_offset, unsigned int length);
void memcpy_to_gpmc(char* source, unsigned int register_offset, unsigned int length);

@ -235,7 +235,7 @@ int FPGASocket::setupSerial() {
newtio.c_cc[VTIME] = 0; // Inter-character timer unused
newtio.c_cc[VMIN] = 0; // Blocking read unused
tcflush(m_fd_tty, TCIFLUSH);
tcsetattr(m_fd_tty, TCSANOW, &newtio);
@ -305,14 +305,14 @@ void FPGASocket::commandLoop() {
cc = readBlock(buffer, 1024);
if (cc > 0) {
ret = write(m_fd_tty, buffer, cc);
// HACK
// This works around a buffer overflow on FTDI serial devices
// It may not be sufficient for baudrates less than 115200!
if (cc > 128) {
usleep(100000);
}
while ((ret < 0) && (errno == EAGAIN)) {
usleep(1000);
ret = write(m_fd_tty, buffer, cc);
@ -354,7 +354,7 @@ void FPGASocket::commandLoop() {
char data[42];
// Read state data from memory map and assemble a reply
memcpy_from_gpmc(data+0, 0x20, 0x1f); // LCD display
memcpy_from_gpmc(data+0, 0x20, 0x20); // LCD display
data[32] = 1; // Input mode (locked to Remote)
data[33] = read_gpmc(0x0b); // Number of address bits of DSP RAM
data[34] = read_gpmc(0x02); // 4-bit LEDs

@ -60,6 +60,8 @@ struct exit_exception {
exit_exception(int c):c(c) { }
};
void gpmc_clear_channel_traces();
/*
The LogicAnalyzerSocket class provides a socket that is connected with a client.
For every client that connects to the server, the server creates a new
@ -166,7 +168,6 @@ void LogicAnalyzerSocket::finishKerberosHandshake() {
}
int LogicAnalyzerSocket::setupGPMC() {
int i;
int ret;
ret = setup_gpmc_bbb();
@ -175,10 +176,11 @@ int LogicAnalyzerSocket::setupGPMC() {
unsigned char model = read_gpmc(0x00);
unsigned char version = read_gpmc(0x01);
if ((model != 0x42) || (version < 1)) {
printf("A compatible uLab hardware debug interface was not detected! Please verify your configuration.\n");
printf("A compatible uLab hardware debug interface was not detected! Please verify your configuration.\n");
return -1;
}
printf("[DEBUG] Detected a compatible uLab hardware debug interface (model number 0x%02x, firmware version 0x%02x)\n", model, version);
printf("[DEBUG] Detected a compatible uLab hardware debug interface (model number 0x%02x, firmware version 0x%02x)\n", model, version);
gpmc_clear_channel_traces();
}
return 0;
@ -192,16 +194,65 @@ int gpmc_sample_count() {
return 2048;
}
double gpmc_timestep() {
return ((read_gpmc_uint16_t(0x0e/2))*1e-9);
}
int gpmc_get_running() {
return read_gpmc(0x0d) & 0x1;
}
void gpmc_set_running(bool running) {
if (running) {
write_gpmc(0x0d, read_gpmc(0x0d) | 0x1);
}
else {
write_gpmc(0x0d, read_gpmc(0x0d) & ~0x1);
}
}
int gpmc_get_channel_name(TQString &name, unsigned int traceNumber) {
int offset;
char rawName[32];
memcpy_from_gpmc(rawName, 0x800 + (traceNumber * 32), 32);
for (offset=0; offset<32; offset++) {
if (rawName[offset] != 0) {
break;
}
}
name = TQString(rawName + offset);
name.replace("<", "&lt;");
name.replace(">", "&gt;");
return 0;
}
void gpmc_clear_channel_traces() {
unsigned int i;
int traceLength;
traceLength = gpmc_sample_count();
for (i=0; i<traceLength; i++) {
write_gpmc_uint64_t(0x800 + i, 0x0);
}
}
int gpmc_get_channel_traces(TQDoubleArray& traceData, TQDoubleArray& positionData, unsigned int traceNumber) {
unsigned int i;
int traceLength;
double timestep;
double position;
traceLength = gpmc_sample_count();
timestep = gpmc_timestep();
traceData.resize(traceLength);
positionData.resize(traceLength);
position = 0;
for (i=0; i<traceLength; i++) {
traceData[i] = ((read_gpmc_llong(0x800 + i) & (1 << traceNumber)) >> traceNumber);
positionData[i] = i;
traceData[i] = ((read_gpmc_uint64_t(0x800 + i) & ((uint64_t)1 << traceNumber)) >> traceNumber);
positionData[i] = position;
position = position + timestep;
}
return traceLength;
@ -221,7 +272,16 @@ void LogicAnalyzerSocket::commandLoop() {
ds >> instrumentCommand;
if (instrumentCommand != "") {
if ((instrumentCommand == "GETLOGICTRACES")) { // Want all channel traces
if ((instrumentCommand == "LOGICANALYZER")) { // requesting logic analyzer access
ds << TQString("ACK");
writeEndOfFrame();
}
else if ((instrumentCommand == "RESET")) { // requesting reset
// Nothing to reset...
ds << TQString("ACK");
writeEndOfFrame();
}
else if ((instrumentCommand == "GETLOGICTRACES")) { // Want all channel traces
ds << TQString("ACK");
int i;
int channels = gpmc_channel_count();
@ -234,11 +294,12 @@ void LogicAnalyzerSocket::commandLoop() {
}
writeEndOfFrame();
}
else if (instrumentCommand == "GETTRACESAMPLECOUNT") { // Want to get number of samples in a trace
TQ_INT32 samples = gpmc_sample_count();
if (samples > 0) {
else if (instrumentCommand == "GETHORIZONTALDIVCOUNT") { // Want the number of horizontal divisions available
// One horizontal division per sample
TQ_INT16 divisions = gpmc_sample_count();
if (divisions >= 0) {
ds << TQString("ACK");
ds << samples;
ds << divisions;
writeEndOfFrame();
}
else {
@ -246,7 +307,17 @@ void LogicAnalyzerSocket::commandLoop() {
writeEndOfFrame();
}
}
else if (instrumentCommand == "GETNUMBEROFCHANNELS") { // Want the number of channels available
else if (instrumentCommand == "GETTRACESAMPLECOUNT") { // Want to get number of samples in a trace
int i;
int channels = gpmc_channel_count();
TQ_INT32 samples = gpmc_sample_count();
ds << TQString("ACK");
for (i=0; i<channels; i++) {
ds << samples;
}
writeEndOfFrame();
}
else if (instrumentCommand == "GETNUMBEROFCHANNELS") { // Want the number of channels available
TQ_INT32 channels = gpmc_channel_count();
if (channels > 0) {
ds << TQString("ACK");
@ -258,6 +329,53 @@ void LogicAnalyzerSocket::commandLoop() {
writeEndOfFrame();
}
}
else if (instrumentCommand == "GETCHANNELNAME") { // Want to get channel name
TQString name;
int i;
int channels = gpmc_channel_count();
ds << TQString("ACK");
for (i=0; i<channels; i++) {
gpmc_get_channel_name(name, i);
ds << name;
}
writeEndOfFrame();
}
else if (instrumentCommand == "GETCHANNELACTIVE") { // Want to get channel activity
TQ_INT16 state;
int i;
int channels = gpmc_channel_count();
ds << TQString("ACK");
for (i=0; i<channels; i++) {
// All channels are always active
state = 1;
ds << state;
}
writeEndOfFrame();
}
else if (instrumentCommand == "GETSECONDSSDIV") { // Want to get seconds per division
double secondsdiv;
int i;
int channels = gpmc_channel_count();
ds << TQString("ACK");
for (i=0; i<channels; i++) {
secondsdiv = gpmc_timestep();
ds << secondsdiv;
}
writeEndOfFrame();
}
else if (instrumentCommand == "GETRUNNING") { // Want to get run status
TQ_INT16 running = gpmc_get_running();
ds << TQString("ACK");
ds << running;
writeEndOfFrame();
}
else if (instrumentCommand == "SETRUNNING") { // Want to change run status
TQ_INT16 value;
ds >> value;
gpmc_set_running(value);
ds << TQString("ACK");
writeEndOfFrame();
}
else {
printf("[WARNING] Received unknown command %s from host %s\n\r", instrumentCommand.ascii(), m_remoteHost.ascii()); fflush(stdout);
ds << TQString("NCK");

Loading…
Cancel
Save