//------------------------------------------------------------------------- //------------------------------------------------------------------------- //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 void BRANCHTO ( unsigned int ); extern void dummy ( unsigned int ); #define ARM_TIMER_CTL 0x2000B408 #define ARM_TIMER_CNT 0x2000B420 #define GPFSEL1 0x20200004 #define GPSET0 0x2020001C #define GPCLR0 0x20200028 #define GPPUD 0x20200094 #define GPPUDCLK0 0x20200098 #define AUX_ENABLES 0x20215004 #define AUX_MU_IO_REG 0x20215040 #define AUX_MU_IER_REG 0x20215044 #define AUX_MU_IIR_REG 0x20215048 #define AUX_MU_LCR_REG 0x2021504C #define AUX_MU_MCR_REG 0x20215050 #define AUX_MU_LSR_REG 0x20215054 #define AUX_MU_MSR_REG 0x20215058 #define AUX_MU_SCRATCH 0x2021505C #define AUX_MU_CNTL_REG 0x20215060 #define AUX_MU_STAT_REG 0x20215064 #define AUX_MU_BAUD_REG 0x20215068 //GPIO14 TXD0 and TXD1 //GPIO15 RXD0 and RXD1 //------------------------------------------------------------------------ unsigned int uart_recv ( void ) { while(1) { if(GET32(AUX_MU_LSR_REG)&0x01) break; } return(GET32(AUX_MU_IO_REG)&0xFF); } //------------------------------------------------------------------------ void uart_send ( unsigned int c ) { while(1) { if(GET32(AUX_MU_LSR_REG)&0x20) break; } PUT32(AUX_MU_IO_REG,c); } //------------------------------------------------------------------------ void hexstrings ( unsigned int d ) { //unsigned int ra; unsigned int rb; unsigned int rc; rb=32; while(1) { rb-=4; rc=(d>>rb)&0xF; if(rc>9) rc+=0x37; else rc+=0x30; uart_send(rc); if(rb==0) break; } uart_send(0x20); } //------------------------------------------------------------------------ void hexstring ( unsigned int d ) { hexstrings(d); uart_send(0x0D); uart_send(0x0A); } //------------------------------------------------------------------------ unsigned char xstring[256]; //------------------------------------------------------------------------ int notmain ( void ) { unsigned int ra; //unsigned int rb; unsigned int rx; unsigned int addr; unsigned int block; unsigned int crc; PUT32(AUX_ENABLES,1); PUT32(AUX_MU_IER_REG,0); PUT32(AUX_MU_CNTL_REG,0); PUT32(AUX_MU_LCR_REG,3); PUT32(AUX_MU_MCR_REG,0); PUT32(AUX_MU_IER_REG,0); PUT32(AUX_MU_IIR_REG,0xC6); PUT32(AUX_MU_BAUD_REG,270); ra=GET32(GPFSEL1); ra&=~(7<<12); //gpio14 ra|=2<<12; //alt5 ra&=~(7<<15); //gpio15 ra|=2<<15; //alt5 PUT32(GPFSEL1,ra); PUT32(GPPUD,0); for(ra=0;ra<150;ra++) dummy(ra); PUT32(GPPUDCLK0,(1<<14)|(1<<15)); for(ra=0;ra<150;ra++) dummy(ra); PUT32(GPPUDCLK0,0); PUT32(AUX_MU_CNTL_REG,3); PUT32(ARM_TIMER_CTL,0x00F90000); PUT32(ARM_TIMER_CTL,0x00F90200); hexstring(0x12345678); //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 //this is a very crude solution, worked for a small test program though //if it slips one byte it is all over. Need to make a more robust //solution. rx=GET32(ARM_TIMER_CNT); while(1) { ra=GET32(ARM_TIMER_CNT); if((ra-rx)>=4000000) { uart_send(0x15); rx+=4000000; } if(GET32(AUX_MU_LSR_REG)&0x01) break; } block=1; addr=ARMBASE; while(1) { xstring[0]=uart_recv(); if(xstring[0]==0x04) { uart_send(0x06); break; } if(xstring[0]!=0x01) break; crc=0x01; for(ra=1;ra<132;ra++) { xstring[ra]=uart_recv(); crc+=xstring[ra]; } if(xstring[2]!=(255-xstring[1])) break; crc-=xstring[131]; crc&=0xFF; if(xstring[131]!=crc) { uart_send(0x15); } for(ra=0;ra<128;ra++) { PUT8(addr++,xstring[ra+3]); } if(addr>0x200000) { uart_send(0x15); break; } uart_send(0x06); block=(block+1)&0xFF; } if(xstring[0]==0x04) { BRANCHTO(ARMBASE); } return(0); } //------------------------------------------------------------------------- //-------------------------------------------------------------------------