Files
raspberrypi/bootloader04/bootloader04.c

167 lines
4.3 KiB
C

//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
//The raspberry pi wants you to not have your kernel.img file loaded
//at address 0x0000. Using a bootloader like this it works just fine
//but to avoid having example binaries that are at 0x8000 for running
//from the sd card and a binary at 0x0000 for loading with the
//bootloader, instead the bootloader is going to default to 0x8000
//as well.
#define ARMBASE 0x8000
extern void PUT32 ( unsigned int, unsigned int );
extern void PUT16 ( unsigned int, unsigned int );
extern void PUT8 ( unsigned int, unsigned int );
extern unsigned int GET32 ( unsigned int );
extern unsigned int GETPC ( void );
extern void BRANCHTO ( unsigned int );
extern void dummy ( unsigned int );
extern void uart_init ( void );
extern unsigned int uart_lcr ( void );
extern void uart_send ( unsigned int );
extern unsigned int uart_recv ( void );
extern void hexstring ( unsigned int );
extern void hexstrings ( unsigned int );
extern void timer_init ( void );
extern unsigned int timer_tick ( void );
extern void timer_init ( void );
extern unsigned int timer_tick ( void );
//------------------------------------------------------------------------
unsigned char xstring[256];
//------------------------------------------------------------------------
int notmain ( void )
{
unsigned int ra;
//unsigned int rb;
unsigned int rx;
unsigned int addr;
unsigned int block;
unsigned int state;
unsigned int crc;
uart_init();
hexstring(0x12345678);
hexstring(GETPC());
timer_init();
//SOH 0x01
//ACK 0x06
//NAK 0x15
//EOT 0x04
//block numbers start with 1
//132 byte packet
//starts with SOH
//block number byte
//255-block number
//128 bytes of data
//checksum byte (whole packet)
//a single EOT instead of SOH when done, send an ACK on it too
block=1;
addr=ARMBASE;
state=0;
crc=0;
rx=timer_tick();
while(1)
{
ra=timer_tick();
if((ra-rx)>=4000000)
{
uart_send(0x15);
rx+=4000000;
}
if((uart_lcr()&0x01)==0) continue;
xstring[state]=uart_recv();
rx=timer_tick();
if(state==0)
{
if(xstring[state]==0x04)
{
uart_send(0x06);
BRANCHTO(ARMBASE);
break;
}
}
switch(state)
{
case 0:
{
if(xstring[state]==0x01)
{
crc=xstring[state];
state++;
}
else
{
//state=0;
uart_send(0x15);
}
break;
}
case 1:
{
if(xstring[state]==block)
{
crc+=xstring[state];
state++;
}
else
{
state=0;
uart_send(0x15);
}
break;
}
case 2:
{
if(xstring[state]==(0xFF-xstring[state-1]))
{
crc+=xstring[state];
state++;
}
else
{
uart_send(0x15);
state=0;
}
break;
}
case 131:
{
crc&=0xFF;
if(xstring[state]==crc)
{
for(ra=0;ra<128;ra++)
{
PUT8(addr++,xstring[ra+3]);
}
uart_send(0x06);
block=(block+1)&0xFF;
}
else
{
uart_send(0x15);
}
state=0;
break;
}
default:
{
crc+=xstring[state];
state++;
break;
}
}
}
return(0);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------