[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[microblaze-uclinux] Simple bootloader for custom board
Hello,
I'm still working on my custom board with a Virtex-II on it with some SDRAM.
So now my system is pretty ok in the hardware and FPGA part. I'm at the
moment working on the bootloader. I have chosen as a base the bootloader
that comes with the current uClinux-auto project. But since I have no
Flash memory on my board, I have to reload the kernel everytime, and I
want to use the serial port to do that.
So there is code in that bootloader, but it handles srec files. What is
the way to produce a srec file containing the kernel image AND the
filesystem so that I could use the current bootloader ?
I have also started working on a more simple bootlader that takes the
image file from the serial port, taking the raw data ... I can write the
file very well in the memory (I can check and the value are the same in
memory and my hard disk), but when starting the kernel, I just get
nothing ! The problem is that I have never been able to boot uClinux
with that card, so I've got no Idea where it could come from ! And has
someone already made that kind of work, and maybe with some protocol
implemented (Y or Z modem for example), because with my version, I have
to hard code the image size ? If you want to check my version, it is
attached to this message.
Thanks for your support
Valentin
/**********************************************************************
*
* bootloader.c
*
* Simple menu-driven bootloader for microblaze/uclinux on ROPES board
*
* uClinux kernel command line parameter handling
* by Brett Boren <borenb@eng.uah.edu>
*
*************************************************************************
* Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au>
* Copyright (C) 2004 Brett Boren <borenb@eng.uah.edu>
* Copyright (C) 2005 Valentin Longchamp <valentin.longchamp@epfl.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/* Get general hardware memory map */
#include "xparameters.h"
#include "xbasic_types.h"
#include "xstatus.h"
#include "xuartlite_l.h"
#include "xuartlite.h"
#include "xgpio.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "flash.h"
/* Software flow control characters */
#define XON 17
#define XOFF 19
#define FLASH_BASEADDR 0xff000000
/* Length of the Memory test */
#define TAB_SIZE 0x10
/* For now, hard code image length at 2MB */
unsigned int gImageLen=0;
/* Start and end of SDRAM ram */
unsigned int *sdram_start = (unsigned int *)XPAR_SDRAM_CONTROLLER_BASEADDR;
unsigned int *sdram_end = (unsigned int *)XPAR_SDRAM_CONTROLLER_HIGHADDR;
/* Start and end of SRAM */
unsigned int *ram_start = (unsigned int *)0xffe00000;
unsigned int *ram_end = (unsigned int *)0xfff00000;
/* Static buffer to store kernel command line */
char cmdline[512];
/* hard coded size of the Linux image */
unsigned int imageSize = 644793;
/* the UART IP */
XUartLite uart;
/* Prototypes for menu functions */
typedef int (*menu_function)(void);
int menu_download_kernel(void);
int menu_test_memory(void);
int menu_launch_kernel(void);
typedef struct {
menu_function fn;
char *menu_string;
} menu_item;
menu_item main_menu[]={
{menu_test_memory,"Test the SDRAM"},
{menu_download_kernel,"Download Kernel from serial port"},
{menu_launch_kernel,"Launch the Kernel from memory"},
{0,0}};
// take an argument for the cmdline buffer
typedef void (*void_fn)(void *);
void_fn kernel_start;
extern int _start;
void set_intvecs(void)
{
unsigned int *ptr=(unsigned int *)0x0;
/* Only care about reset vector, make sure it points at
the startup code */
*ptr=(unsigned)&_start;
}
void memory_test(unsigned int *start, unsigned int *end)
{
unsigned int *dst;
print("\n\r\n\rTesting memory...");
for(dst=start; dst<end; dst++)
*dst=(unsigned int)dst;
for(dst=start; dst<end; dst++)
if(*dst!=(unsigned int)dst)
{
print("failed at 0x");
putnum((int)dst);
print("\n\rContents:0x");
putnum((int)*dst);
print(" expected 0x");
putnum((unsigned int)dst);
print("\n\rHalting...");
for(;;)
;
}
}
void clear_memory(unsigned int *start, unsigned int *end)
{
unsigned int *dst;
for(dst=start; dst< end; dst++)
*dst=0;
}
void copy_image(unsigned int *src, unsigned int *dst, unsigned int len)
{
flash_read_reset();
print("\n\rCopying kernel image...");
while(len--)
{
*dst++=*src++;
}
print("done\n\r");
}
int menu_test_memory(void) {
int *SDRAM_pointer = (int *) (XPAR_SDRAM_CONTROLLER_BASEADDR);
int i = 0;
int write_value = 0x12345600;
xil_printf("Memory Test Program\r\n");
//we erase memory to be sure of its state
xil_printf("Erasing SDRAM\r\n");
for (i=0; i<TAB_SIZE;i++) {
*SDRAM_pointer = 0;
SDRAM_pointer++;
}
xil_printf("Erasing done\r\n checking erase\r\n");
SDRAM_pointer = (int *) (XPAR_SDRAM_CONTROLLER_BASEADDR);
for (i = 0; i<TAB_SIZE; i++) {
int value = *SDRAM_pointer;
xil_printf("address : 0x%x value : 0x%x \r\n", SDRAM_pointer , value);
SDRAM_pointer++;
}
SDRAM_pointer = (int *) (XPAR_SDRAM_CONTROLLER_BASEADDR);
// we write into the memory
xil_printf("Writing to the SDRAM\r\n");
for (i=0; i<TAB_SIZE;i++) {
*SDRAM_pointer = write_value;
xil_printf("address : 0x%x value to be written : 0x%x \r\n", SDRAM_pointer, write_value);
SDRAM_pointer++;
write_value++;
}
xil_printf("write operations finished\r\n");
SDRAM_pointer = (int *) (XPAR_SDRAM_CONTROLLER_BASEADDR);
xil_printf("Reading back from the SDRAM\r\n");
for (i=0; i<TAB_SIZE;i++) {
int value = *SDRAM_pointer;
xil_printf("address : 0x%x read value : 0x%x \r\n", SDRAM_pointer , value);
SDRAM_pointer++;
}
xil_printf("end of Memory Test program\r\n");
return 0;
}
int menu_download_kernel(void)
{
unsigned int received = 0;
Xuint8 *write_address = (Xuint8 *) sdram_start;
Xuint32 *read_address = (Xuint32 *) sdram_start;
XUartLite_Initialize(&uart, XPAR_CONSOLE_UART_DEVICE_ID);
XUartLite_ResetFifos(&uart);
xil_printf("\r\nImage will be loaded to %08x\n\r",write_address);
xil_printf("Initiate file transfer now\n\r");
gImageLen=0;
while(received<imageSize)
{
int recv = XUartLite_Recv(&uart,write_address,16);
if (recv > 0) {
received += recv;
gImageLen += recv;
write_address += recv;
}
}
xil_printf("%d bytes received\n\r",gImageLen);
for(received = 0; received<12; received++){
Xuint32 value = *read_address;
xil_printf("address : 0x%x read value : 0x%x \r\n", read_address++ , value);
}
return 0;
}
int menu_launch_kernel(void)
{
if(!gImageLen)
{
print("Error - no image downloaded yet!\n\r");
return -1;
}
kernel_start = (void_fn)sdram_start;
kernel_start(cmdline); /* Never returns */
return 0;
}
/* simple routine to get a number typed on stdin */
int get_number(void)
{
char ch, buffer[100];
int num_chars;
num_chars=0;
/* Read chars until buffer full or enter pressed */
while((ch=inbyte()) != '\r' && num_chars < 99)
if(isdigit(ch))
outbyte(buffer[num_chars++]=ch);
print("\n\r");
buffer[num_chars]='\0';
return atoi(buffer);
}
int do_menu(menu_item *menu)
{
int menu_choice, num_items=0;
num_items=0;
print("\n\n\r");
print("ROPES bootloader Menu\n\r");
print("---------------------\n\r");
print("\n\r");
while(menu[num_items].fn)
{
xil_printf("%d. %s\n\r",num_items+1,
menu[num_items].menu_string);
num_items++;
}
print("\n\r");
print("\n\r");
do
{
print("Make your choice>");
menu_choice = get_number();
} while (menu_choice<1 || menu_choice > num_items);
return menu[menu_choice-1].fn();
}
int menu_set_cmdline(void)
{
/* overwrite the first part of the address space since we're
pretty well guaranteed not to have to use it again */
int i = 0;
char ch = '\0';
outbyte(XON);
print("Enter cmdline: ");
ch = inbyte();
// 0x0d is the carriage return (Enter) ascii value
// cmdline buffer is only 512 bytes
while (ch != 0x0d && i < 512-1)
{
cmdline[i++] = ch;
outbyte(XON);
outbyte(ch);
ch = inbyte();
}
cmdline[i] = '\0';
outbyte(XON);
return 1;
}
void reset_uarts(void)
{
unsigned int *uartp;
uartp=(unsigned int *)XPAR_CONSOLE_UART_BASEADDR;
uartp[XUL_CONTROL_REG_OFFSET/4]=0x0;
#ifdef XPAR_DEBUG_UART_BASEADDR
uartp=(unsigned int *)XPAR_DEBUG_UART_BASEADDR;
uartp[XUL_CONTROL_REG_OFFSET/4]=0x0;
#endif
}
int main(void)
{
//set_intvecs();
reset_uarts();
flash_set_base((unsigned int *)FLASH_BASEADDR);
flash_read_reset();
/* Ensure cmdline defaults to null (zero-length) string */
cmdline[0]='\0';
while(1)
do_menu(main_menu);
}