Commit df88b2b4 authored by Jose Jimenez's avatar Jose Jimenez

debugger_sw/remote_tools: Code for remote tools added

debugger_sw/remote_tools/eb-cl.c: For remote firmware udpate
debugger_sw/remote_tools/eb-optimizer.c: For RAM optimization
debugger_sw/remote_tools/remote-vuart.cpp: To access vUART register remotely
Signed-off-by: 's avatarJose Jimenez <ppjm@correo.ugr.es>
parent b490c2df
# This work is part of the White Rabbit project
#
# Jose Jimenez <jjimenez.wr@gmail.com>, Copyright (C) 2014.
# Released according to the GNU GPL version 3 (GPLv3) or later.
#
# Makefile to compile remote tools
# ethb-cl : Simple tool for RAM programming
# ethb-mem-tst: Easy way to test RAM usage and optimize memory regions
# remote-vuart: Implements virtual UART remote acces for configuration
#
#
# I know, I know that is a huge mess.
# I know I shouldn't be mixing standard c with c++. In my defense,
# Etherbone API was witten in standard C while CALoE mix C/C++.
# ethb-cl & ethb-mem-tst are in standard C
#
# This RAM-related tools us acces_internals which is
# written in C
#
CC ?= gcc
CPP = g++
DESTDIR ?= /usr/local
ETHERBONE_DIR = ./caloe/etherbone
#
# For standard C tools, we will be compiling only the stuff we really need
# C
progs-cc-y = eb-optimizer
progs-cc-y += eb-cl
CFLAGS = -I -Icaloe/lib -Icaloe/devices -I. -Wno-trigraphs -O2 -Wall -ggdb
LFLAGS = -L. -l:$(ETHERBONE_DIR)/api/libetherbone.a
obj-y = caloe/lib/access_internals.o
OBJS = $(obj-y)
#/C
#CPP
OUTPUT_CPP = remote-vuart
LFLAGS_CPP = -L. -l:caloe/lib/libcaloe.a -l:$(ETHERBONE_DIR)/api/libetherbone.a
obj-cpp-y = caloe/devices/dio/Dio.o
obj-cpp-y += caloe/devices/vuart/Vuart.o
OBJS_CPP = $(obj-cpp-y)
#/CPP
all: $(progs-cc-y) $(OUTPUT_CPP)
clean:
$(RM) -f $(progs-cc-y) $(OUTPUT_CPP) $(OBJS) $(OBJS_CPP) *.o *.a
$(MAKE) -C $(ETHERBONE_DIR)/api -f Makefile clean
$(MAKE) -C caloe/devices -f Makefile clean
$(MAKE) -C caloe/lib -f Makefile clean
$(MAKE) -C caloe/tools -f Makefile clean
$(progs-cc-y): $(OBJS)
install:
install -d $(DESTDIR)/bin
install -D $(progs-cc-y) $(DESTDIR)/bin
install -D $(OUTPUT_CPP) $(DESTDIR)/bin
build-etherbone: git_etherbone caloe/etherbone
$(MAKE) -C $(ETHERBONE_DIR)/api -f Makefile
%: %.c
$(CC) $(CFLAGS) $*.c $(OBJS) $(LFLAGS) -o $@
%.o: build-etherbone %.c
$(CC) $(CFLAGS) -c $*.c -o $@
git_etherbone:
@test -f ./caloe -d $(ETHERBONE_DIR)/api || echo "Checking out submodules"
@test -f ./caloe -d $(ETHERBONE_DIR)/api || \
$(MAKE) -C ./caloe -f Makefile etherbone-submodule
# The vuart thing is based on the cpp-wtritten CALoE files
#
# When using c++, I don't do much work (only very simple rules). I decided to
# keep it simple and relay on the author's Makefiles, saving time.
#
# We will be compiling everthing and using the stuff we really need (sorry)
#
$(OUTPUT_CPP): build-etherbone
$(MAKE) -C caloe/lib -f Makefile
$(MAKE) -C caloe/devices -f Makefile
$(MAKE) -C caloe/tools -f Makefile
$(CPP) -DCURPATH="\"$(CURDIR)"\" $(CFLAGS) $@.cpp $(OBJS_CPP) $(LFLAGS_CPP) -o $@
/*
* This work is part of the White Rabbit project
*
* Jose Jimenez <jjimenez.wr@gmail.com>, Copyright (C) 2014.
* Released according to the GNU GPL version 3 (GPLv3) or later.
*
* Simple tool for secuential WB writing/reading using CALoE/Etherbone.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <getopt.h>
#include <string.h>
#include <caloe/lib/access_internals.h>
#include <errno.h>
#include <unistd.h>
//caloe
#define is_config_int 0
#define nbytes 100
#define line_end 0
//ethb-cl
#define def_init_offset 0x40000
#define conf_buf 256
#define def_ethb_conf "udp/10.10.1.1"
static void help(char *name)
{
fprintf(stderr,
"Use: \"%s [-a base address ] [-e proto/IPv4] <ram file>\"\n", name);
fprintf(stderr,
" -a: RAM base address (default 0x%x)\n", def_init_offset);
fprintf(stderr,
" -e: Transport protocol [udp|tcp]/device IPv4 (default %s)\n",
def_ethb_conf);
fprintf(stderr,
" <ram file>: Path to the .ram file to be loaded\n");
fprintf(stderr, "\nReport bugs to <fmc-delay-1ns-8cha-sa@ohwr.org>\n");
exit(1);
}
static int checkIP(char *ip)
{
struct sockaddr_in sock;
int ret = inet_pton(AF_INET, ip, &(sock.sin_addr));
return (ret != 1);
}
int main (int argc, char ** argv)
{
access_caloe access;
network_connection nc;
int c, i;
unsigned int base = def_init_offset;
FILE *fp;
uint32_t cntr = 0;
char *ptr;
char *s_val[3];
char *line = (char *) malloc (nbytes + 1);
char *ip = (char *) malloc(conf_buf);
uint32_t u_val[2];
strcpy(ip, def_ethb_conf);
while ((c = getopt (argc, argv, "a:e:h")) != -1)
{
char aux[conf_buf];
switch(c)
{
case 'a':
base = (unsigned int)strtol(optarg, &ptr, 16);
if (ptr && *ptr)
{
fprintf(stderr, "%s: \"%s\" is not an hex number\n",
argv[0], optarg);
exit(1);
}
break;
case 'e':
strcpy(aux, optarg);
ptr=strpbrk(aux, "/");
*ptr=0;
if (!strcmp(aux, "tpc"))
{
fprintf(stderr, "%s: Etherbone does not support tcp\n",
argv[0]);
exit(1);
}
else if (strcmp(aux, "udp"))
{
fprintf(stderr, "%s: invalid protocol\"%s\"\n",
argv[0], aux);
exit(1);
}
else if (checkIP(ptr+1))
{
fprintf(stderr, "%s: \"%s\" is not a valid IPv4 address\n",
argv[0], ptr+1);
exit(1);
}
else
strcpy(ip, optarg);
break;
case 'h':
default:
help(argv[0]);
}
}
if (optind >= argc)
{
fprintf(stderr, "%s: Expected new ram file after options.\n",
argv[0]);
exit(1);
}
printf(
"WARNING: RAM located at 0x%x will be overwritten with %s (acces by %s)\n",
base, argv[optind], ip);
printf("Do you want to proceed? (y/n): ");
char proceed;
for(;;)
{
scanf("%s", &proceed);
if (proceed == 'y')
{
printf("Memory overwrite will proceed, please wait... \n");
break;
}
else if (proceed == 'n')
{
printf("Don't panic. Overwrite aborted!\n");
return 0;
}
else
printf("Invalid option, please enter [y|n]: ");
}
// Build an network_connection struct of access_internals
build_network_con_caloe (ip, &nc);
if ((fp = fopen(argv[optind], "r")) == NULL)
{
fprintf(stderr, " %s: ERROR while opening %s file: %s\n",
argv[0], argv[optind], strerror(errno));
exit(1);
}
while (fgets(line, nbytes, fp) != NULL) {
s_val[0] = line; /* wtf? why only works this way? */
/* parse chain */
for (i=1; i<=2; i++)
{
s_val[i]=strpbrk(s_val[i-1], " ");
*s_val[i]=line_end;
s_val[i]++;
}
/* final touches */
s_val[0]=strpbrk(s_val[2], "\n");
*s_val[0]=line_end;
for (i=0; i<=1; i++)
{
u_val[i] = (uint32_t)strtol(s_val[i+1], &ptr, 16)*(4-3*i);
if (ptr && *ptr)
{
fprintf(stderr,
" %s: ERROR \"%c\" is not an hex number\n",
argv[0], s_val[i]);
exit(1);
}
}
cntr++;
build_access_caloe(base, u_val[0], u_val[1], 0, MASK_OR, is_config_int,
WRITE, SIZE_4B, &nc, &access);
if ((execute_caloe(&access)) < 0)
exit(1);
if ((uint32_t) access.value != u_val[1])
{
fprintf(stderr,
" %s: ERROR overwritting RAM: access %0x%08x (%u), \n",
argv[0], cntr, cntr);
fprintf(stderr,
" Values to load from file: offset %s, value to write %s\n",
s_val[0], s_val[1]);
fprintf(stderr,
" Converted values: offset %08x, value %08x\n",
u_val[0], u_val[1]);
fprintf(stderr,
" Written values: offset %08x, value %08x\n",
u_val[1], access.value);
fprintf(stderr,
" Difference (written value - read value): %d\n",
(u_val[1] - (uint32_t) access.value));
exit(1);
}
}
fclose(fp);
// Free access_caloe and network_connection memory
free_access_caloe(&access);
printf("\nRAM successfully overwrited!\n");
return 0;
}
/*
* This work is part of the White Rabbit project
*
* Jose Jimenez <jjimenez.wr@gmail.com>, Copyright (C) 2014 UGR.
* Released according to the GNU GPL version 3 (GPLv3) or later.
*
* Simple tool for testing memory usage usign Etherbone.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <getopt.h>
#include <string.h>
#include <caloe/lib/access_internals.h>
#include <errno.h>
//caloe
#define is_config_int 0
#define nbytes 100
#define line_end 0
//ethb-mem-tst
#define conf_buf 256
#define def_ethb_conf "udp/10.10.1.1"
#define pattern 0xdeafbeef
#define arguments 3
static void help(char *name)
{
fprintf(stderr, "Use: "
"\"%s [-e proto/IPv4] [-y] [-w] <base_address> <num_words> <pattern>\"\n"
"\n", name);
fprintf(stderr,
" -e: Transport protocol [udp|tcp]/device IPv4 (default %s)\n",
def_ethb_conf);
fprintf(stderr,
" [-w]: To write the pattern <pattern> or the default pattern.\n"
" <offset>: Memory base addres.\n"
"<num_words>: Num of word to be written/tested.\n"
" <pattern>: Requires -w\n"
" Pattern to be read/written\n"
" If none, defalut pattern \"0x%08x\" is used.\n", pattern);
fprintf(stderr, "\nReport bugs to <fmc-delay-1ns-8cha-sa@ohwr.org>\n\n");
exit(1);
}
static int checkIP(char *ip)
{
struct sockaddr_in sock;
int ret = inet_pton(AF_INET, ip, &(sock.sin_addr));
return (ret != 1);
}
int main (int argc, char ** argv)
{
access_caloe access;
network_connection nc;
int c, i, do_write = 0, warn = 1, limit=arguments;;
uint32_t cntr = 0;
char *ip = (char *) malloc(conf_buf);
char *end;
uint32_t uarg[arguments], _val;
char *ptr;
strcpy(ip, def_ethb_conf);
while ((c = getopt (argc, argv, "e:ywh")) != -1)
{
char aux[conf_buf];
switch(c)
{
case 'e':
strcpy(aux, optarg);
ptr=strpbrk(aux, "/");
*ptr=0;
if (!strcmp(aux, "tpc"))
{
fprintf(stderr, "%s: Etherbone does not support tcp\n",
argv[0]);
exit(1);
}
else if (strcmp(aux, "udp"))
{
fprintf(stderr, "%s: invalid protocol\"%s\"\n",
argv[0], aux);
exit(1);
}
else if (checkIP(ptr+1))
{
fprintf(stderr, "%s: \"%s\" is not a valid IPv4 address\n",
argv[0], ptr+1);
exit(1);
}
else
strcpy(ip, optarg);
break;
case 'w':
do_write=1;
break;
case 'h':
help(argv[0]);
exit(1);
}
}
if (optind >= argc || optind < argc - arguments)
help(argv[0]);
if(optind != argc - arguments){
uarg[arguments] = pattern;
limit--;
}
/* convert the trailing hex number or numbers */
for(i=0; i<limit; i++){
uarg[i] = strtol(argv[optind+i], &end, abs(16*(1-i)));
if (end && *end) {
fprintf(stderr, "%s: \"%s\" is not a number\n",
argv[0], argv[optind+i]);
exit(1);
}
}
if (uarg[0] & 3) {
fprintf(stderr, "%s: address \"%s\" not multiple of 4\n",
argv[0], argv[optind + 0]);
exit(1);
}
// Build an network_connection struct of access_internals
build_network_con_caloe (ip, &nc);
int last = 0, words = 0;
for(i=uarg[0]; i < uarg[0]+uarg[1]*0x4; i+=0x4){
if (!do_write)
{
build_access_caloe(0x0, i, _val, 0, MASK_OR, is_config_int,
READ, SIZE_4B, &nc, &access);
if ((execute_caloe(&access)) < 0)
exit(1);
if (access.value == uarg[3])
{
if(((i-last) == 0x4) || (last == 0))
{
if(words == 0)
printf("Starting at %08x we have ", i);
words++;
}
}
else
{
if (words == 1)
printf("only one word\n");
else if (words > 1)
{
printf("%u words, the last one at %08x\n", words, last);
}
words = 0;
}
last=i;
}
else{
build_access_caloe(0x0, i, uarg[3], 0, MASK_OR, is_config_int,
WRITE, SIZE_4B, &nc, &access);
if ((execute_caloe(&access)) < 0)
exit(1);
}
}
if (words == 1)
printf("only one word\n");
else if (words > 1)
printf("%u words, the last one at %08x\n", words, last);
// Free access_caloe and network_connection memory
free_access_caloe(&access);
return 0;
}
/*
* This work is part of the White Rabbit project
*
* Jose Jimenez <jjimenez.wr@gmail.com>, Copyright (C) 2014 UGR.
* Released according to the GNU GPL version 3 (GPLv3) or later.
*
* Tool for virtual UART remote acces by CALoE (Etherbone).
*
* Inspiered by cmd_spec.cpp
*
* Modifications:
* - Main function simplification
* - Absolute path building mechainsm for *.cfg files instead of relative path
* for folder independence calling.
*/
#include "../devices/dio/Dio.h"
#include "../devices/vuart/Vuart.h"
#include <arpa/inet.h>
using namespace std;
#define HIDE_GUI_STAT_CONT 0
bool isValidIpAddress(const char *ipAddress)
{
char buff[30];
strcpy(buff,ipAddress);
struct sockaddr_in sa;
int result = inet_pton(AF_INET, buff, &(sa.sin_addr));
return result != 0;
}
string get_ip() {
string ip;
do {
cout << "Node IP: ";
cin >> ip;
if(cin.fail()) {
cout <<endl<<"Error: CIN istream error!"<<endl;
exit(-1);
}
} while(!isValidIpAddress(ip.c_str()));
return ip;
}
char get_vuart_loop_mode() {
char loop;
do {
cout << "Loop mode (y/n)?: ";
cin >> loop;
if(cin.fail()) {
cout <<endl<<"Error: CIN istream error!"<<endl;
exit(-1);
}
} while(loop != 'y' && loop != 'n');
return loop;
}
// Remove additional characters
string delete_format_chars(string s) {
string s2;
int size = s.length();
int i;
for(i = 4 ; i < size ; i = i+5) {
s2.push_back(s.at(i));
}
return s2;
}
// Print vuart command response
void printf_vuart(string res,string cmd) {
vector<string> res_split = split(res,'\n');
vector<string>::iterator it;
vector<string>::iterator itb = res_split.begin();
vector<string>::iterator ite = res_split.end()-1;
string fl = delete_format_chars(*itb);
bool cmd_first_line = (fl.find(cmd) != string::npos);
if(cmd_first_line)
itb++;
for(it = itb ; it != ite ; it++){
cout << *it <<endl;
}
}
int main ()
{
char *vuart_cfg_path = (char *) malloc(2048*sizeof(char));
strcpy(vuart_cfg_path, CURPATH);
vuart_cfg_path = strcat(vuart_cfg_path, "/vuart-dbg.cfg");
Vuart vuart(vuart_cfg_path);
string ip;
string cmd;
string virtual_cmd;
string proto("udp");
cout <<"************************************************************"<<endl;
cout <<"* Fine Delay Stand Alone Mode - Remote Configuration *"<<endl;
cout <<"* by *"<<endl;
cout <<"* Jose Jimenez *"<<endl;
cout <<"* *"<<endl;
cout <<"* *"<<endl;
cout <<"* - WARNING - *"<<endl;
cout <<"* This is a beta version, please report bugs to: *"<<endl;
cout <<"* <fmc-delay-1ns-8cha-sa@ohwr.org> *"<<endl;
cout <<"************************************************************"<<endl;
cout <<endl;
ip = get_ip();
cmd ="vuart";
if (cmd == "exit"){}
else
{
if(cmd == "vuart")
{
string res;
char trash;
cout <<endl<<"Warning: Vuart is also under testing!!"<<endl;
cout <<"Note: Use \"exit\" to quit the applicattion"<<endl<<endl;
cout <<"Note: Type \"help\" to see command list"<<endl;
cout <<"Note: Use \"<command_name -h>\" to explore commands usage"
<<endl<<endl;
trash = getchar();
while (1) /* Dedicated to Nolo from this "poor cable-peeler" */
{
cout << "vuart# ";
getline(cin,virtual_cmd);
if(virtual_cmd == "exit")
break;
res = vuart.execute_cmd(proto+"/"+ip,virtual_cmd,3);
printf_vuart(res,virtual_cmd);
}
}
else
cout<<endl<<endl<<cmd<<": Unrecognized command"<<endl<<endl;
}
return 0;
}
# This work is part of the White Rabbit project
#
# Jose Jimenez <jjimenez.wr@gmail.com>, Copyright (C) 2014 UGR.
#
# Released according to the GNU GPL version 3 (GPLv3) or later.
#
# Adapted from vuart.cfg
#
BOPERATION
NAME vuart_read
DOC Read a value from vuart
BACTION
NETP
ADDRESS 0x60114
MODE R
ALIGN 4
EACTION
EOPERATION
BOPERATION
NAME vuart_ready
DOC Ask if vuart is ready to write
BACTION
NETP
ADDRESS 0x60100
MODE R
MASK 0x2
MSKNEG
ALIGN 4
EACTION
EOPERATION
BOPERATION
NAME vuart_write
DOC Write a value to vuart
BACTION
NETP
VALUEP
ADDRESS 0x60110
MODE W
MASK 0xff
MSKNEG
ALIGN 4
EACTION
EOPERATION
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment