diff --git a/bootloader01/Makefile b/bootloader01/Makefile new file mode 100644 index 0000000..f3ca9af --- /dev/null +++ b/bootloader01/Makefile @@ -0,0 +1,46 @@ + +ARMGNU ?= arm-none-eabi + +COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding + +all : kernel.img blinker.hex prograspi + +clean : + rm -f *.o + rm -f *.bin + rm -f *.elf + rm -f *.list + rm -f *.img + rm -f *.hex + rm -f prograspi + +novectors.o : novectors.s + $(ARMGNU)-as novectors.s -o novectors.o + +bootloader01.o : bootloader01.c + $(ARMGNU)-gcc $(COPS) -c bootloader01.c -o bootloader01.o + +kernel.img : loader novectors.o bootloader01.o + $(ARMGNU)-ld novectors.o bootloader01.o -T loader -o bootloader01.elf + $(ARMGNU)-objdump -D bootloader01.elf > bootloader01.list + $(ARMGNU)-objcopy bootloader01.elf -O binary kernel.img + + + +start.o : start.s + $(ARMGNU)-as start.s -o start.o + +blinker.o : blinker.c + $(ARMGNU)-gcc $(COPS) -c blinker.c -o blinker.o + +blinker.hex : memmap start.o blinker.o + $(ARMGNU)-ld start.o blinker.o -T memmap -o blinker.elf + $(ARMGNU)-objdump -D blinker.elf > blinker.list + $(ARMGNU)-objcopy blinker.elf -O binary blinker.bin + $(ARMGNU)-objcopy blinker.elf -O ihex blinker.hex + + +prograspi : prograspi.c ser.c ser.h + gcc -O2 -Wall prograspi.c ser.c -o prograspi + + diff --git a/bootloader01/README b/bootloader01/README new file mode 100644 index 0000000..4dfeb15 --- /dev/null +++ b/bootloader01/README @@ -0,0 +1,52 @@ + +See the top level README for information on where to find the +schematic and programmers reference manual for the ARM processor +on the raspberry pi. + +Derived from uart02 and code of various ages (yes some from 1996), this +is a very simple bootloader. Instead of removing, writing, and replcing +the sd card numerous times. This makes that a bit simpler. Using the +uart on the card and some sort of uart on the host (see below) you only +need to load the bootloader (kernel.img derived from bootloader01.elf) +one time. From then on just power cycle the raspberry pi and use the +host loader program (prograspi) to load and start the program under +development on the raspberry pi. + +This bootloader sits at 0x200000 so that you have 0x200000 bytes to +develop with. And that way if you like your program you can just +copy a .bin version to kernel.img on the sd card and use it. I had +the bootloader closer to 0x0000000 and test programs would be after it +but that means to make a real program for the sd card would be another +link step. Very easy to change this, both bootloader01.c and prograspi.c +use the same number 0x200000. + +On the host you will want to use something like this: +http://www.sparkfun.com/products/718 +to connect to the uart pins on the raspi. Do not connect the raspberry +pi pins directly to a com port on a computer you will fry the board. +The above board happens to have pins in the same order as the raspberry +pi. On connector P1 on the raspberry pi connect pin 6 to ground on the +usb to serial board. Pin 8 on P1 to RX on the usb to serial board, and +pin 10 on P1 to TX on the usb to serial board. I use these +http://www.sparkfun.com/products/8430 +to connect the ftdi board to the raspberry pi. No soldering required, +at least not at the moment. If down the road the raspberri pi does +not have P1 header pins then there will be some soldering or something +required. + +You do not use a dumb terminal program. The program on the host +that loads your ARM program is called prograspi. There is a test +program derived from blinker03 called blinker. Once you have copied +kernel.img to the sd card on the raspberry pi. You have hooked up +the usb to serial board to the raspberry pi. Plug the usb into +the usb to serial board and use dmesg to note the /dev/ttyUSBX port. +Plug in the raspberry pi to power it and then run: + +./prograspi blinker.hex /dev/ttyUSBX + +where /dev/ttyUSBX is the port you are connecting through, it could +be a real serial port if you have a tranciever for the raspberry pi +side. (MAX232 for example). + +Now you can go back and try my other examples without the dozens/hundreds +of sd card insertions it took me to get to this point. diff --git a/bootloader01/blinker.c b/bootloader01/blinker.c new file mode 100644 index 0000000..2e6388d --- /dev/null +++ b/bootloader01/blinker.c @@ -0,0 +1,57 @@ + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +extern void PUT32 ( unsigned int, unsigned int ); +extern unsigned int GET32 ( unsigned int ); +extern void dummy ( unsigned int ); + +#define ARM_TIMER_LOD 0x2000B400 +#define ARM_TIMER_VAL 0x2000B404 +#define ARM_TIMER_CTL 0x2000B408 +#define ARM_TIMER_DIV 0x2000B41C +#define ARM_TIMER_CNT 0x2000B420 + +#define SYSTIMERCLO 0x20003004 +#define GPFSEL1 0x20200004 +#define GPSET0 0x2020001C +#define GPCLR0 0x20200028 + +#define TIMEOUT 1000000 + +//------------------------------------------------------------------------- +int notmain ( void ) +{ + unsigned int ra; + unsigned int rb; + + ra=GET32(GPFSEL1); + ra&=~(7<<18); + ra|=1<<18; + PUT32(GPFSEL1,ra); + + PUT32(ARM_TIMER_CTL,0x00F90000); + PUT32(ARM_TIMER_CTL,0x00F90200); + + rb=GET32(ARM_TIMER_CNT); + while(1) + { + PUT32(GPSET0,1<<16); + while(1) + { + ra=GET32(ARM_TIMER_CNT); + if((ra-rb)>=TIMEOUT) break; + } + rb+=TIMEOUT; + PUT32(GPCLR0,1<<16); + while(1) + { + ra=GET32(ARM_TIMER_CNT); + if((ra-rb)>=TIMEOUT) break; + } + rb+=TIMEOUT; + } + return(0); +} +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- diff --git a/bootloader01/bootloader01.c b/bootloader01/bootloader01.c new file mode 100644 index 0000000..93e3546 --- /dev/null +++ b/bootloader01/bootloader01.c @@ -0,0 +1,257 @@ + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +extern void PUT32 ( unsigned int, unsigned int ); +extern void PUT16 ( unsigned int, unsigned int ); +extern unsigned int GET32 ( unsigned int ); +extern void BRANCHTO ( unsigned int ); +extern void dummy ( unsigned int ); + +#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); +} +//------------------------------------------------------------------------ +// Packet Format +// [0] 0x7C start sync +// [1] datalen +// [2] ~datalen +// datalen bytes: +// [3] type +// [4] sequence +// [5] pass=0/fail!=0 +// [6] +// [7] +// [8] payload starts +// ... +// datalen ends +// [n-2] 0x7D end sync +// [n-1] checksum +//------------------------------------------------------------------------ +unsigned char xstring[512]; +//------------------------------------------------------------------------ +int recv_packet ( void ) +{ + unsigned int len; + unsigned int ra; + unsigned int rb; + unsigned int rc; + + while(1) + { + ra=uart_recv(); + if(ra!=0x7C) + { + continue; + } + ra=0; + xstring[ra++]=0x7C; //sync + xstring[ra++]=uart_recv(); //datalen + xstring[ra++]=uart_recv(); //~datalen + if(xstring[ra-2]!=(~xstring[ra-1]&0xFF)) + { + continue; + } + len=xstring[ra-2]; + while(len--) xstring[ra++]=uart_recv(); + xstring[ra++]=uart_recv(); //sync + xstring[ra++]=uart_recv(); //checksum + if(xstring[ra-2]!=0x7D) + { + continue; + } + for(rb=0,rc=0x00;rb ram + .bss : { *(.bss*) } > ram +} + diff --git a/bootloader01/memmap b/bootloader01/memmap new file mode 100644 index 0000000..203c50d --- /dev/null +++ b/bootloader01/memmap @@ -0,0 +1,12 @@ + +MEMORY +{ + ram : ORIGIN = 0x00000000, LENGTH = 0x200000 +} + +SECTIONS +{ + .text : { *(.text*) } > ram + .bss : { *(.bss*) } > ram +} + diff --git a/bootloader01/novectors.s b/bootloader01/novectors.s new file mode 100644 index 0000000..b28882f --- /dev/null +++ b/bootloader01/novectors.s @@ -0,0 +1,35 @@ + +.globl _start +_start: + b reset + +.space 0x200000-4,0 + +reset: + mov sp,#0x10000000 + bl notmain +hang: b hang + +.globl PUT32 +PUT32: + str r1,[r0] + bx lr + +.globl PUT16 +PUT16: + strh r1,[r0] + bx lr + +.globl GET32 +GET32: + ldr r0,[r0] + bx lr + +.globl BRANCHTO +BRANCHTO: + bx r0 + +.globl dummy +dummy: + bx lr + diff --git a/bootloader01/prograspi.c b/bootloader01/prograspi.c new file mode 100644 index 0000000..9f275e3 --- /dev/null +++ b/bootloader01/prograspi.c @@ -0,0 +1,317 @@ + +//----------------------------------------------------------------------------- +// Copyright (C) David Welch, 2000, 2003, 2008, 2009, 2012 +//----------------------------------------------------------------------------- + +#include +#include +#include + +FILE *fp; + +#include "ser.h" + +unsigned int seq; +unsigned int ra,rb,rc,rd; +unsigned int addr; +unsigned int firstaddr; + +unsigned char data[128]; +unsigned char sdata[512]; +unsigned char rdata[5000]; + +//----------------------------------------------------------------------------- +int check_packet ( void ) +{ + unsigned int ra; + unsigned int rb; + unsigned int rc; + + + if(rdata[0]!=0x7C) return(2); + if(rdata[1]!=(~rdata[2]&0xFF)) return(2); + if(rdata[3]!=sdata[3]) return(2); + if(rdata[4]!=sdata[4]) return(2); + if(rdata[3+rdata[1]]!=0x7D) return(2); + ra=3; + ra=rdata[1]+5; + for(rb=0,rc=0;rb>24)&0xFF; + sdata[ra++]=(addr>>16)&0xFF; + sdata[ra++]=(addr>> 8)&0xFF; + sdata[ra++]=(addr>> 0)&0xFF; +// for(rd=0;rd>8)&0xFF; + sdata[ra++]=(data>>0)&0xFF; + } + // + sdata[ra++]=0x7D; + for(rd=0,rc=0;rd no colon\n",line); + continue; + } + gstring[0]=newline[1]; + gstring[1]=newline[2]; + gstring[2]=0; + len=strtoul(gstring,NULL,16); + for(ra=0;ra<(len+5);ra++) + { + gstring[0]=newline[(ra<<1)+1]; + gstring[1]=newline[(ra<<1)+2]; + gstring[2]=0; + hexline[ra]=(unsigned char)strtoul(gstring,NULL,16); + } + checksum=0; + for(ra=0;ra<(len+5);ra++) checksum+=hexline[ra]; + //checksum&=0xFF; + if(checksum) + { + printf("checksum error <%u>\n",line); + } + add=hexline[1]; add<<=8; + add|=hexline[2]; + add|=addhigh; + if(add>RAMMASK) + { + printf("address too big 0x%08X\n",add); + //return(1); + continue; + } + if(add&3) + { + printf("bad address 0x%08X\n",add); + return(1); + } + t=hexline[3]; + if(t!=0x02) + { + if(len&3) + { + printf("bad length\n"); + return(1); + } + } + + //:0011223344 + //;llaaaattdddddd + //01234567890 + switch(t) + { + default: + printf("UNKNOWN type %02X <%u>\n",t,line); + break; + case 0x00: + for(ra=0;raRAMMASK) + { + printf("address too big 0x%08X\n",add); + break; + } + data= hexline[ra+4+1]; + data<<=8; data|=hexline[ra+4+0]; + if(raspload(add,data)) return(1); + add+=2; + + data= hexline[ra+4+3]; + data<<=8; data|=hexline[ra+4+2]; + if(raspload(add,data)) return(1); + add+=2; + if(add>maxadd) maxadd=add; + } + break; + case 0x01: +// printf("End of data\n"); + break; + case 0x02: + addhigh=hexline[5]; + addhigh<<=8; + addhigh|=hexline[4]; + addhigh<<=16; + break; + case 0x03: + data= hexline[4+0]; + data<<=8; data|=hexline[4+1]; + data<<=8; data|=hexline[4+2]; + data<<=8; data|=hexline[4+3]; + printf("TYPE 3 0x%08X\n",data); + break; + } + } + + //printf("%u lines processed\n",line); + //printf("%08X\n",maxadd); + //for(ra=0;ra>2]); + //} + return(0); + + +} + + + + +//----------------------------------------------------------------------------- +int main ( int argc, char *argv[] ) +{ + unsigned int ra; + //unsigned int rb; + unsigned int rc; + + if(argc<3) + { + printf("prograspi filename.hex /dev/ttyXYZ\n"); + return(1); + } + fp=fopen(argv[1],"rt"); + if(fp==NULL) + { + printf("Error opening file [%s]\n",argv[1]); + return(1); + } + printf("file opened\n"); + + + if(ser_open(argv[2])) + { + printf("ser_open() failed\n"); + return(1); + } + printf("port opened\n"); + + seq=17; + firstaddr=0xFFFFFFFF; + if(readhex(fp)) + { + return(1); + } + + printf("Entry point: 0x%08X\n",firstaddr); + + ra=0; + sdata[ra++]=0x7C; + sdata[ra++]=5+4; + sdata[ra]=~sdata[ra-1]; ra++; + // + sdata[ra++]=0x08; + sdata[ra++]=seq&0xFF; seq++; + sdata[ra++]=0; + sdata[ra++]=0; + sdata[ra++]=0; + + sdata[ra++]=(firstaddr>>24)&0xFF; + sdata[ra++]=(firstaddr>>16)&0xFF; + sdata[ra++]=(firstaddr>> 8)&0xFF; + sdata[ra++]=(firstaddr>> 0)&0xFF; + // + sdata[ra++]=0x7D; + for(rd=0,rc=0;rd +#include +#include +#include +#include +#include + +#include +#include + +int ser_hand; +unsigned short ser_buffcnt; +unsigned short ser_maincnt; +unsigned char ser_buffer[(0xFFF+1)<<1]; + +//----------------------------------------------------------------------------- +unsigned char ser_open ( char *devname ) +{ + struct termios options; + + ser_hand=open(devname,O_RDWR|O_NOCTTY|O_NDELAY); + if(ser_hand==-1) + { + fprintf(stderr,"ser_open: error - %s\n",strerror(errno)); + return(1); + } + fcntl(ser_hand,F_SETFL,FNDELAY); + bzero(&options,sizeof(options)); + options.c_cflag=B115200|CS8|CLOCAL|CREAD; + options.c_iflag=IGNPAR; + tcflush(ser_hand,TCIFLUSH); + tcsetattr(ser_hand,TCSANOW,&options); + ser_maincnt=ser_buffcnt=0; + + return(0); +} +//---------------------------------------------------------------------------- +void ser_close ( void ) +{ + close(ser_hand); +} +//----------------------------------------------------------------------------- +void ser_senddata ( unsigned char *s, unsigned short len ) +{ + unsigned int wlen; + wlen=(unsigned int)write(ser_hand,s,len); + tcdrain(ser_hand); +} +//----------------------------------------------------------------------------- +void ser_sendstring ( char *s ) +{ + unsigned int wlen; + + wlen=(unsigned int)write(ser_hand,s,strlen(s)); + tcdrain(ser_hand); +} +//----------------------------------------------------------------------------- +void ser_update ( void ) +{ + int r; + + r=read(ser_hand,&ser_buffer[ser_maincnt],4000); + if(r>0) + { + ser_maincnt+=r; + if(ser_maincnt>0xFFF) + { + ser_maincnt&=0xFFF; + memcpy(ser_buffer,&ser_buffer[0xFFF+1],ser_maincnt); + } + } +} +//----------------------------------------------------------------------------- +unsigned short ser_copystring ( unsigned char *d ) +{ + unsigned short r; + unsigned short buffcnt; + unsigned short maincnt; + + ser_update(); + buffcnt=ser_buffcnt; + maincnt=ser_maincnt; + for(r=0;buffcnt!=maincnt;buffcnt=(buffcnt+1)&0xFFF,r++) *d++=ser_buffer[buffcnt]; + return(r); +} +//----------------------------------------------------------------------------- +unsigned short ser_dump ( unsigned short x ) +{ + unsigned short r; + + for(r=0;r