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!

Attachment: lm3s8962_tools.tar.gz
Description: application/compressed-tar

_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to