Le mercredi 06 juillet 2011 à 18:50 -0700, Rodrigo Rosa a écrit : > On Mon, Jul 4, 2011 at 4:13 PM, Maxim Cournoyer > <[email protected]> wrote: > > On Jul 2, 2011 6:15 PM +0200, Øyvind Harboe wrote: > > > > Use the Source Luke. The end of the command is not linefeed but 0x??. There > > ought to be updated docs. Patch? > > > > Great tip! I found it inside the tcl_server.c file; the end of character > > used by the openocd tcl server is 0x1a. > > I managed to get the result I was looking for, a simple application which > > usage goes like: > > > > program </path/to/romfile.bin> > > > > The objective was to automate the ROM flashing procedure from Eclipse IDE > > when working with the LM3S8962 kit. The app can be configured as an > > "external tool" and launched at the touch of a button. It could also be > > called inside a custom makefile. The use of the tcl_server is a great > > feature to me, because an openocd daemon is already running most of the > > time, to provide debugging facility. > > > > I have made a C version and a BASH (w/ netcat) version of such a small app. > > I also toyed with tcl to make a telnet-like utility to test openocd's tcl > > server. > > > > I also gathered a LM3S8962.cfg file on the internet and refactored it in to > > a similar way to what could be seen inside the /usr/share/openocd/scripts > > folder. I can post all that stuff if anyone is interested. > > > > i'm working on something similar. > would you mind posting your stuff? > thanks!
Hello Rodrigo! I'm happy to share the small tools I made with you and
the openocd community.
The following scripts/program are tailored for flashing an LM3S8962
target (except the tcl one), although they should be quite simple to
adapt to do anything.
Here's a general telnet like utility written in tcl, for quick testing
(tclnet.tcl):
#!/usr/bin/tclsh
# Simple tcl client to test OpenOCD tcl_server
#
# Based on a script written by Charles Hardin
#
<http://lists.berlios.de/pipermail/openocd-development/2008-July/002368.html>
#
# Author: Maxim Cournoyer, 2011
# OpenOCD server settings
set server localhost
set port 6666
set EOC \x1a
set BUFSIZE 256
puts "Use empty line to exit."
# Open TCP socket
set fo [socket $server $port]
# The following tells the 'read' command to return on EOC.
fconfigure $fo -eofchar $EOC
puts -nonewline stdout "> "
flush stdout
while { [gets stdin line] > 0 } {
puts -nonewline "Sending \"$line\" ... "
puts -nonewline $fo "$line$EOC"
flush $fo
# Server reply reception
set line {}
if { [catch {set line [read $fo $BUFSIZE]}] } {
close $fo
puts "\nConnection or server error."
exit 1
}
# Server returns empty string (only EOC received) if OK. Longer
output is
# returned in case of wrong command name or if the user
specified the command name
# with the capture parameter, e.g.: capture { halt }
if { [string equal $line {}] } {
puts "OK."
} else {
puts "\nServer: $line"
}
puts -nonewline stdout "> "
flush stdout
}
# We need to reconfigure the channel to normal before closing,
# else we'd get a TCP RST fault.
fconfigure $fo -eofchar \n
close $fo
exit 0
Next is a bash written tool to flash the binary ROM onto my LM3S8962
board (flashROM.sh):
#!/bin/bash
#
# Simple script that allows flashing ROM onto LM3S8962 target
# by sending commands to the tcl_server of OpenOCD
#
# Author: Maxim Cournoyer, 2011
server=localhost
port=6666
#-------------------------------------------------------------------------------
# Function definitions
#-------------------------------------------------------------------------------
# USAGE: send_commands "cmd1 \"cmd2 with spaces\" cmd3"
# Useful to send multiple commands with a single tcp connection.
# Tip : also works for single commands!
send_commands ()
{
local argc=$(echo $1 | sed 's/[^,]//g' | wc -m)
local cmds_string="$(echo $1 | sed 's/,/\\x1a/g')\x1a"
local received=$(echo -e $cmds_string | nc $server $port)
local received_symbols=$(( $(echo $received | wc -m) -1 ))
# Error checking: only good for command names. Wrong args to
commands
# (e.g. the path to a .bin file) will not be detected here.
if [ $received_symbols == $argc ]; then
echo "Success!"
else
echo "Failed. Check commands synthax."
exit 1
fi
}
# USAGE: get_extension "filepath" "extension_length"
# Credits: KenJackson's post at
http://www.linuxforums.org/forum/programming-scripting/67818-get-last-three-characters-string.html
get_extension()
{
local length=$(echo $1 | wc -c)
local offset=$(( $lenght - $2 ))
local extension="${1:$offset}"
echo $extension
}
#-------------------------------------------------------------------------------
# Main section
#-------------------------------------------------------------------------------
# Argument parsing + file path formatting for relative path
support
if [ "$1" ]; then
if [ ! ${1##/*} ]; then
ROM_path="$1"
else
ROM_path="$(pwd)/$1"
fi
else
echo "USAGE: flashROM <absolute ROM file path>"
exit 1
fi
# Make sure the file exists
if [ ! -f "$ROM_path" ]; then
echo "Error: the file specified does not exist."
exit 1
fi
# Verify that ROM suffix is valid
ROM_suffix="$(get_extension "$ROM_path" 4)"
if [ "$ROM_suffix" != ".bin" ] && [ "$ROM_suffix" != ".hex" ];
then
echo "Error: the file extension is not not valid."
exit 1
fi
# Flash ROM routine for LM3S8962
command1=halt
command2="flash write_image erase \"$ROM_path\""
command3=reset
send_commands "$command1,$command2,$command3"
#done
exit 0
The next listing is the same program, flashROM.c, is yet another version
of the same program in C:
/* Simple ROM flash utility for the EK-LM3S8962 board
development kit
* for use with OpenOCD.
*
* Based on simple echoserver program written by David Mertz,
see
* http://gnosis.cx/publish/programming/sockets.html
*
* Maxim Cournoyer, 2011
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define BUFFSIZE 128
void Die(const char *mess)
{
perror(mess);
exit(1);
}
int main(int argc, const char *argv[])
{
/* server parameters */
const char server_ip[] = "127.0.0.1";
const int server_port = 6666;
/* Supported ROM suffixes */
const char *suffix1 = "bin";
const char *suffix2 = "hex";
/* Base of each command */
char word1[] = "halt";
const char word2[] = "flash write_image erase ";
const char word3[] = "reset";
const char EOC[] = "\x1a"; /* End Of Command delimiter */
char command1[strlen(word1)+strlen(EOC)+1];
char *command2; /* will be malloc further */
char command3[strlen(word3)+strlen(EOC)+1];
const char *ROM_path_tmp;
char *ROM_path;
char *path_buf;
if ((path_buf = getcwd(NULL, 0)) == NULL) /* automatic malloc
*/
{
Die("Failed to allocate memory.");
}
int i = strlen(path_buf);
/* Process arguments */
if (argc != 2)
{
fprintf(stderr, "USAGE: flashrom
<rom_absolute_path>\n");
exit(1);
}
ROM_path_tmp = argv[1];
/* File path formatting for relative path support */
if (ROM_path_tmp[0] == '/')
{
ROM_path = (char *) ROM_path_tmp;
}
else
{
/* Relative path */
ROM_path = (char *) malloc(i + strlen(ROM_path_tmp) +
2); /*
+1 for '/', +1 for '\0' = 2 */
if (ROM_path == NULL)
{
Die("Failed to allocate memory.");
}
strcpy(ROM_path, path_buf);
strcat(ROM_path, "/");
strcat(ROM_path, ROM_path_tmp);
}
free(path_buf);
/* Make sure the ROM_path points to an existing file */
if( access(ROM_path, F_OK) == -1 ) {
Die("Invalid ROM file path specified");
}
/* Make sure the last 3 chars of the file are "bin" */
char ROM_suffix[4];
int ROM_path_len = strlen(ROM_path);
int tmp = 0;
for (int a = ROM_path_len - 3; a < ROM_path_len; a++)
{
ROM_suffix[tmp] = ROM_path[a];
tmp++;
}
ROM_suffix[tmp]='\0';
if ( strcmp(ROM_suffix,suffix1) && strcmp(ROM_suffix,suffix2) )
{
printf("File suffix is not \"%s\" or \"%s\"!
Aborting.\n",
suffix1, suffix2);
exit(1);
}
int sock;
struct sockaddr_in openocd_server;
char buffer[BUFFSIZE]; /* Size of the buffer for received data
*/
/* Commands definition */
strcpy(command1, word1);
/* Allocate dynamic memory for absolute rom's path */
command2 = (char*) malloc(strlen(word2) + strlen(ROM_path) +
strlen(EOC) + 3); /* Two double quote + '\0' = 3 */
if ( command2 == NULL )
{
Die("Failed to allocate memory.");
}
strcpy(command2, word2);
strcat(command2,"\"");
strcat(command2, ROM_path);
strcat(command2,"\"");
if ( ROM_path != ROM_path_tmp )
{
free(ROM_path);
}
strcpy(command3, word3);
/* Command sequence : commands will be sent in this order */
char *command_sequence[] = { command1, command2, command3 };
/* Create the TCP socket */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
Die("Failed to create socket");
}
/* Construct the server sockaddr_in structure */
memset(&openocd_server, 0, sizeof(openocd_server)); /* Clear
struct */
openocd_server.sin_family = AF_INET; /* Internet/IP */
openocd_server.sin_addr.s_addr = inet_addr(server_ip); /* IP
address */
openocd_server.sin_port = htons(server_port); /* server port */
/* Establish connection */
if (connect(sock, (struct sockaddr *) &openocd_server,
sizeof(openocd_server)) < 0)
{
Die("Failed to connect with server");
}
/* Loop for sending the commands */
for (int j = 0; j < 3; j++)
{
/* Send the word to the server */
printf("Sending %s... ", command_sequence[j]);
/* Now we add the EOC char */
strcat(command_sequence[j], EOC);
int msg_len = strlen(command_sequence[j]);
if (send(sock, command_sequence[j], msg_len, 0) !=
msg_len)
{
Die("Mismatch in number of sent bytes");
}
/* Receive the word back from the server */
int bytes = 0;
if ((bytes = recv(sock, buffer, BUFFSIZE - 1, 0)) < 1)
{
Die("Failed to receive bytes from server");
}
buffer[bytes] = '\0'; /* Assure null terminated string
*/
if (bytes == 1 && (strcmp(buffer, EOC) == 0))
{
printf("OK.\n");
}
else
{
printf("FAIL\n");
}
}
/* Cleanup and close socket */
free(command2);
close(sock);
exit(0);
}
Now for the OpenOCD configuration scripts (for EK-LM3S8962 dev board).
The base of it was found on the Internet and reformatted to respect the
presentation of other OpenOCD scripts.
This one would go in the "target" folder of openocd's scripts dir:
# file: lm3s8962.cfg
# Script for TI/Luminary Stellaris LM3S8962
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME lm3s8962
}
if { [info exists CPUTAPID ] } {
set _CPUTAPID $CPUTAPID
} else {
set _CPUTAPID 0x3ba00477
}
#jtag scan chain
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 1 -irmask 0xf
-expected-id $_CPUTAPID
#gdb debug target
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m3 -chain-position
$_CHIPNAME.cpu -variant lm3s
#set a work area of 16kb starting at address 20000000 (sram
start)
$_TARGETNAME configure -work-area-phys 0x20000000
-work-area-size 0x4000
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME stellaris 0 0 0 0 $_TARGETNAME
The next one would go in the "board" folder:
# file: eki-lm3s8962.cfg
# TI/Luminary Stellaris LM3S8962 Evaluation Kits
#
http://www.luminarymicro.com/products/eki-lm3s8962_can_ethernet_evaluation_kit.html
# include the FT2232 interface config for on-board JTAG
interface
source [find interface/luminary.cfg]
# include the target config
source [find target/lm3s8962.cfg]
# jtag speed
jtag_khz 500
jtag_nsrst_delay 100
#LM3S8962 Evaluation Board has only srst
reset_config srst_only
Then the OpenOCD daemon could be launched with a simple "openocd -f
board/ek-lm3s8962.cfg"
That's a lot of info, hopefully you'll find something useful in it! I've
attached a gunzipped tarball of these files for convenience.
Have a nice day!
lm3s8962_tools.tar.gz
Description: application/compressed-tar
_______________________________________________ Openocd-development mailing list [email protected] https://lists.berlios.de/mailman/listinfo/openocd-development
