OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [boot-loader-serial/] [boot-loader-serial.c] - Diff between revs 65 and 67

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 65 Rev 67
Line 1... Line 1...
 
/*----------------------------------------------------------------
 
//                                                              //
 
//  boot-loader.c                                               //
 
//                                                              //
 
//  This file is part of the Amber project                      //
 
//  http://www.opencores.org/project,amber                      //
 
//                                                              //
 
//  Description                                                 //
 
//  The main functions for the boot loader application. This    //
 
//  application is embedded in the FPGA's SRAM and is used      //
 
//  to load larger applications into the DDR3 memory on         //
 
//  the development board.                                      //
 
//                                                              //
 
//  Author(s):                                                  //
 
//      - Conor Santifort, csantifort.amber@gmail.com           //
 
//                                                              //
 
//////////////////////////////////////////////////////////////////
 
//                                                              //
 
// Copyright (C) 2010 Authors and OPENCORES.ORG                 //
 
//                                                              //
 
// This source file may be used and distributed without         //
 
// restriction provided that this copyright statement is not    //
 
// removed from the file and that any derivative work contains  //
 
// the original copyright notice and the associated disclaimer. //
 
//                                                              //
 
// This source file is free software; you can redistribute it   //
 
// and/or modify it under the terms of the GNU Lesser General   //
 
// Public License as published by the Free Software Foundation; //
 
// either version 2.1 of the License, or (at your option) any   //
 
// later version.                                               //
 
//                                                              //
 
// This source 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 Lesser General Public License for more //
 
// details.                                                     //
 
//                                                              //
 
// You should have received a copy of the GNU Lesser General    //
 
// Public License along with this source; if not, download it   //
 
// from http://www.opencores.org/lgpl.shtml                     //
 
//                                                              //
 
----------------------------------------------------------------*/
 
 
 
#include "amber_registers.h"
 
#include "stdio.h"
 
#include "boot-loader.h"
 
#include "fpga-version.h"
 
 
 
 
 
int main ( void ) {
 
    int c, esc = 0;
 
    char buf  [20]; /* current line */
 
    char lbuf [20]; /* last line    */
 
    int i = 0;
 
    int li = 0;
 
    int j;
 
 
 
    /* Enable the UART FIFO */
 
    *(unsigned int *) ADR_AMBER_UART0_LCRH = 0x10;
 
 
 
    printf("%cAmber Boot Loader v%s\n", 0xc, AMBER_FPGA_VERSION );  /* 0xc == new page */
 
 
 
 
 
    /* When ADR_AMBER_TEST_SIM_CTRL is non-zero, its a Verilog simulation.
 
       The  ADR_AMBER_TEST_SIM_CTRL register is always 0 in the real fpga
 
       The register is in vlog/system/test_module.v
 
    */
 
    if ( *(unsigned int *) ADR_AMBER_TEST_SIM_CTRL ) {
 
        load_run(*(unsigned int *) ADR_AMBER_TEST_SIM_CTRL, 0);
 
        }
 
 
 
 
 
    /* Print the instructions */
 
    print_help();
 
    printf("Ready\n> ");
 
 
 
    /* Loop forever on user input */
 
    while (1) {
 
        if ((c = _inbyte (DLY_1S)) >= 0) {
 
 
 
            /* Escape Sequence ? */
 
            if (c == 0x1b) esc = 1;
 
            else if (esc == 1 && c == 0x5b) esc = 2;
 
            else if (esc == 2) {
 
                esc = 0;
 
                if (c == 'A') {
 
                    /* Erase current line using backspaces */
 
                    for (j=0;j<i;j++)  _outbyte(0x08);
 
 
 
                    /* print last line and
 
                       make current line equal to last line  */
 
                    for (j=0;j<li;j++) _outbyte(buf[j] = lbuf[j]);
 
                    i = li;
 
                    }
 
                continue;
 
                }
 
            else esc = 0;
 
 
 
            /* Character not part of escape sequence so print it
 
               and add it to the buffer
 
            */
 
            if (!esc) {
 
                _outbyte (c);
 
                /* Backspace ? */
 
                if (c == 8 && i > 0) { i--; }
 
                else                 { buf[i++] = c; }
 
                }
 
 
 
            /* End of line ? */
 
            if (c == '\r' || i >= 19) {
 
                if (i>1) {
 
                    /* Copy current line buffer to last line buffer */
 
                    for (j=0;j<20;j++) lbuf[j] = buf[j];
 
                    li = i-1;
 
                    }
 
                buf[i] = 0; i = 0;
 
 
 
                /* Process line */
 
                printf("\n");
 
                parse( buf );
 
                printf("> ");
 
                }
 
            }
 
        }
 
}
 
 
 
 
 
/* Parse a command line passed from main and execute the command */
 
void parse ( char * buf )
 
{
 
    unsigned int found, address, data, i, length, bytes, rdata;
 
    int file_size;
 
    char byte;
 
    unsigned int lcount;
 
    char bad_command_msg[] = "Invalid command";
 
 
 
    /* Ignore returns with no trext on the line */
 
    if (!buf[1]) return;
 
 
 
    /* Check if its a single character instruction */
 
    if (buf[1] == '\r') {
 
        switch (buf[0]) {
 
 
 
            case 'h': /* Help */
 
                print_help();
 
                break;
 
 
 
            case 'l': /* Load */
 
                load_run(1,0);
 
                break;
 
 
 
            case 's': /* Status */
 
                _core_status();
 
                /* Flush out the uart with spaces */
 
                print_spaces(16);
 
                printf  ("\n");
 
                break;
 
 
 
            default:
 
                printf  ("%s\n", bad_command_msg);
 
                break;
 
            }
 
        return;
 
        }
 
 
 
 
 
    /* Check for invalid instruction format for multi-word instructions */
 
    else if (buf[1] != 0x20) {
 
        printf ("%s\n", bad_command_msg);
 
        return;
 
        }
 
 
 
 
 
    switch (buf[0]) {
 
 
 
            case 'd': /* Dump block of memory */
 
                /* Dump memory contents <start address> <number of bytes in hex> */
 
                if (get_address_data ( buf, &address, &bytes )) {
 
                    for (i=address;i<address+bytes;i+=4) {
 
                        printm (i);
 
                        }
 
                    }
 
                break;
 
 
 
            case 'j': /* Jump to <address> */
 
                if (get_hex ( buf, 2, &address, &length )) {
 
                    load_run(0, address);
 
                    }
 
                break;
 
 
 
 
 
            case 'p': /* Print String */
 
                /* Recover the address from the string - the address is written in hex */
 
                if (get_hex ( buf, 2, &address, &length )) {
 
                    length = 0;
 
                    lcount = 0;
 
                    byte = * (char *)address++;
 
                    while ( byte < 128 && length < 0x1000 ) {
 
 
 
                        if ( byte != 0 )        _outbyte( byte );
 
                        if ( byte  == '\r' )    printf("\n"); lcount = 0;
 
                        if ( lcount == 79 )     printf("\n"); lcount = 0;
 
 
 
                        byte = * (char *)address++;
 
                        lcount++;
 
                        length++;
 
                        }
 
                    }
 
                break;
 
 
 
            case 'r': /* Read address */
 
                /* Recover the address from the string - the address is written in hex */
 
                if (get_hex ( buf, 2, &address, &length )) {
 
                    printm (address);
 
                    }
 
                break;
 
 
 
            case 'b': /* Load binary file into address */
 
                /* Recover the address from the string - the address is written in hex */
 
                if (get_hex ( buf, 2, &address, &length )) {
 
                    load_run (5, address);
 
                    }
 
                break;
 
 
 
            case 'w': /* Write address */
 
                /* Get the address */
 
                if (get_address_data ( buf, &address, &data )) {
 
                    /* Write to memory */
 
                    * (unsigned int*) address = data;
 
                    /* read back */
 
                    printm (address);
 
                    }
 
                break;
 
 
 
            default:
 
                printf  ("%s\n", bad_command_msg);
 
                break;
 
        }
 
}
 
 
 
 
 
/* Load a binary file into memory via the UART
 
   If its an elf file, copy it into the correct memory areas
 
   and execute it.
 
*/
 
void load_run( int type, unsigned int address )
 
{
 
    int file_size;
 
    char * message = "Send file w/ 1K Xmodem protocol from terminal emulator now...";
 
 
 
    switch (type) {
 
 
 
        case 1: /* Load a binary file to FILE_LOAD_BASE */
 
            /* Load a file using the xmodem protocol */
 
            printf  ("%s\n", message);
 
 
 
                                      /*       Destination,    Destination Size */
 
            file_size = xmodemReceive((char *) FILE_LOAD_BASE, FILE_MAX_SIZE);
 
            if (file_size < 0 || file_size > FILE_MAX_SIZE) {
 
                printf ("Xmodem error file size 0x%x \n", file_size);
 
                return;
 
                }
 
 
 
            printf("\nelf split\n");
 
            elfsplitter(FILE_LOAD_BASE, file_size);
 
            break;
 
 
 
 
 
        case 2: /* testing the boot loader itself in simulation */
 
            print_help();
 
            _core_status();
 
            print_spaces(16);
 
            _testpass();
 
            break;
 
 
 
 
 
        case 3: /* vmlinux in simulation */
 
            printf("j 0x%08x\n", LINUX_JUMP_ADR);
 
            /* Flush the uart tx buffer with spaces */
 
            print_spaces(16);
 
            printf("\n");
 
            /* pc jump */
 
            _jump_to_program(LINUX_JUMP_ADR);
 
            _testpass();
 
            break;
 
 
 
 
 
        case 4: /* programs starting at 0x8000 in simulation */
 
            printf("j 0x%08x\n", APP_JUMP_ADR);
 
            /* Flush the uart tx buffer with spaces */
 
            print_spaces(16);
 
            printf("\n");
 
            /* pc jump */
 
            _jump_to_program(APP_JUMP_ADR);
 
            _testpass();
 
            break;
 
 
 
 
 
        case 5: /* Load a binary file into memory, to 'address' */
 
            /* Load a file using the xmodem protocol */
 
            printf  ("%s\n", message);
 
                                      /*       Destination,    Destination Size */
 
            file_size = xmodemReceive((char *) address, FILE_MAX_SIZE);
 
            if (file_size < 0 || file_size > FILE_MAX_SIZE) {
 
                printf ("Xmodem error file size 0x%x \n", file_size);
 
                return;
 
                }
 
            break;
 
 
 
 
 
        default:    /* Run the program */
 
            printf("j 0x%08x\n", address);
 
            /* Flush the uart tx buffer with spaces */
 
            print_spaces(16);
 
            printf("\n");
 
            /* pc jump */
 
            _jump_to_program(address);
 
            _testpass();
 
            break;
 
        }
 
}
 
 
 
 
 
/* Print a memory location */
 
void printm ( unsigned int address )
 
{
 
    printf ("mem 0x%08x = 0x%08x\n", address, * (unsigned int *)address);
 
}
 
 
 
 
 
void print_help ( void )
 
 
 
{
 
    printf("Commands\n");
 
    printf("l");
 
    print_spaces(29);
 
    printf(": Load elf file\n");
 
 
 
    printf("b <address>");
 
    print_spaces(19);
 
    printf(": Load binary file to <address>\n");
 
 
 
    printf("d <start address> <num bytes> : Dump mem\n");
 
 
 
    printf("h");
 
    print_spaces(29);
 
    printf(": Print help message\n");
 
 
 
    printf("j <address>");
 
    print_spaces(19);
 
    printf(": Execute loaded elf, jumping to <address>\n");
 
 
 
    printf("p <address>");
 
    print_spaces(19);
 
    printf(": Print ascii mem until first 0\n");
 
 
 
    printf("r <address>");
 
    print_spaces(19);
 
    printf(": Read mem\n");
 
 
 
    printf("s");
 
    print_spaces(29);
 
    printf(": Core status\n");
 
 
 
    printf("w <address> <value>");
 
    print_spaces(11);
 
    printf(": Write mem\n");
 
}
 
 
 
 
 
/* Print a number of spaces */
 
void print_spaces ( int num )
 
{
 
    while(num--) printf(" ");
 
}
 
 
 
 
 
/* Return a number recovered from a string of hex digits */
 
int get_hex ( char * buf, int start_position,
 
              unsigned int *address,
 
              unsigned int *length)
 
{
 
 
 
    int cpos = 0, done = 0;
 
 
 
    cpos = start_position; done = 0; *address = 0;
 
 
 
    while (done == 0) {
 
        if ( buf[cpos] >= '0' && buf[cpos] <= '9' ) {
 
           *address = *address<<4;
 
           *address = *address + buf[cpos] - '0';
 
           }
 
        else if ( buf[cpos] >= 'A' && buf[cpos] <= 'F' ) {
 
            *address = *address<<4;
 
            *address = *address + buf[cpos] - 'A' + 10;
 
           }
 
        else if ( buf[cpos] >= 'a' && buf[cpos] <= 'f' ) {
 
            *address = *address<<4;
 
            *address = *address + buf[cpos] - 'a' + 10;
 
           }
 
        else  {
 
            done = 1;
 
            *length = cpos - start_position;
 
            }
 
        if ( cpos >= 8+start_position ) {
 
            done = 1;
 
            *length = 8;
 
            }
 
        cpos++;
 
        }
 
 
 
    /* Return the length of the hexadecimal string */
 
    if (cpos > start_position+1) return 1; else return 0;
 
}
 
 
 
 
 
/* Parse a string for an address and data in hex */
 
int get_address_data ( char * buf, unsigned int *address, unsigned int *data )
 
{
 
    int found, length;
 
 
 
    found = get_hex ( buf, 2, address, &length );
 
    if (found) {
 
        /* Get the data */
 
        found = get_hex ( buf, 3+length, data, &length );
 
        }
 
 
 
    return found;
 
}
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.