diff --git a/spi01/Makefile b/spi01/Makefile index 8e10655..c3491df 100644 --- a/spi01/Makefile +++ b/spi01/Makefile @@ -12,11 +12,17 @@ clean : rm -f *.elf rm -f *.list rm -f *.img + rm -f *.bc + rm -f *.opt.s + rm -f *.norm.s + rm -f blinker01.s.* + rm -f blinker02.s.* + rm -f dumphex novectors.o : novectors.s $(ARMGNU)-as novectors.s -o novectors.o -spi01.o : spi01.c +spi01.o : spi01.c blinker.h $(ARMGNU)-gcc $(COPS) -c spi01.c -o spi01.o spi01.elf : memmap novectors.o spi01.o @@ -30,3 +36,19 @@ spi01.hex : spi01.elf $(ARMGNU)-objcopy spi01.elf -O ihex spi01.hex +dumphex : dumphex.c + gcc -o dumphex dumphex.c + +blinker.h : blinker02.s + gcc -o dumphex dumphex.c + avra -fI blinker02.s + ./dumphex blinker02.s.hex + + +blinker01.s.hex : blinker01.s + avra -fI blinker01.s + +blinker02.s.hex : blinker02.s + avra -fI blinker02.s + + diff --git a/spi01/README b/spi01/README index ea437bd..c5142b9 100644 --- a/spi01/README +++ b/spi01/README @@ -7,4 +7,60 @@ these programs. See the top level README for information on how to connect the raspi uart to your host computer. -This is a work in progress, learning how to use the spi master. +This example is using the raspberry pi as an AVR ISP. + +The AVR board used initially is the Sparkfun pro micro 8Mhz/3.3v + +http://www.sparkfun.com/products/10999 + +From an AVR document the chips with this serial isp are either byte +mode or page mode. This chip atmega32u4 is page mode so you load a +temporary buffer with 64 instructions, then send one command to program +that buffer into a page of flash. + +The serial protocol is quite trivial so writing code to use it or modify +this program is simple. + +At this time the code only supports one page/buffer, 64 instructions. + +At this time not worrying about exact timing, it works with count to +N loops. + +Raspberry pi interesting pins + +//GPIO7 SPI0_CE1_N P1-26 +//GPIO8 SPI0_CE0_N P1-24 +//GPIO9 SPI0_MISO P1-21 +//GPIO10 SPI0_MOSI P1-19 +//GPIO11 SPI0_SCLK P1-23 +//alt function 0 for all of the above + +//P1 1 +3V3 +//P1 25 GND +//p1 26 GPIO_CE1 + +Pro micro to raspi + +(GND) P1-25 GND +(RST) P1-26 CE1_N +(VCC) P1-1 +3V3 +(15) SCK JP6-9 P1-23 SCLK +(14) MISO JP6-10 P1-21 MISO +(16) MOSI JP6-11 P1-19 MOSI + +The ATmega32U4 breakout board has a cluster of 6 pins (an AVR ISP header) +with all 6 labelled, you connect the raspberry pi signals (right side +of table above) to those six pins, nothing else. That breakout board +does not have an led at least not in the same place so you would have +to add one or use a scope or meter to see the I/O pin toggle after +programming. + +The AVR doesnt use the chip select for communication, so I support CS0 +but didnt wire it. The AVR is strange in that way, it does need the +chip held in reset so I abused CS1 (CE1_N) and mucked with its +non-asserted state as if it were a gpio pin to assert and deassert reset +on the AVR. Normal spi stuff derived from this example should use CE0_N +(CS0). + +The avr samples use the avra assembler apt-get install avra + diff --git a/spi01/blinker.h b/spi01/blinker.h new file mode 100644 index 0000000..fab5dfc --- /dev/null +++ b/spi01/blinker.h @@ -0,0 +1,27 @@ + +const unsigned short rom[0x80]= +{ + 0xC000, //00000000 + 0xE000, //00000001 + 0xBD04, //00000002 + 0xE005, //00000003 + 0xBD05, //00000004 + 0xE001, //00000005 + 0xB904, //00000006 + 0xE010, //00000007 + 0xE041, //00000008 + 0xEF20, //00000009 + 0xB516, //0000000A + 0x3010, //0000000B + 0xF7E9, //0000000C + 0xB516, //0000000D + 0x3010, //0000000E + 0xF3E9, //0000000F + 0x9523, //00000010 + 0x3020, //00000011 + 0xF7B9, //00000012 + 0x2704, //00000013 + 0xB905, //00000014 + 0xCFF3, //00000015 +}; + diff --git a/spi01/blinker01.s b/spi01/blinker01.s new file mode 100644 index 0000000..fbf3071 --- /dev/null +++ b/spi01/blinker01.s @@ -0,0 +1,34 @@ +.device ATmega168 +.equ DDRB = 0x04 +.equ PORTB = 0x05 + +.org 0x0000 + rjmp RESET + +RESET: + ldi R16,0x01 + out DDRB,R16 + + ldi R18,0x00 + ldi R17,0x00 + ldi R20,0x01 +Loop: + + ldi R19,0xE8 +aloop: + inc R17 + cpi R17,0x00 + brne aloop + + inc R18 + cpi R18,0x00 + brne aloop + + inc R19 + cpi R19,0x00 + brne aloop + + eor R16,R20 + out PORTB, R16 + rjmp Loop + diff --git a/spi01/blinker02.s b/spi01/blinker02.s new file mode 100644 index 0000000..5019ed6 --- /dev/null +++ b/spi01/blinker02.s @@ -0,0 +1,53 @@ + +.device ATmega168 + +.equ DDRB = 0x04 +.equ PORTB = 0x05 +.equ TCCR0A = 0x24 +.equ TCCR0B = 0x25 +.equ TCNT0 = 0x26 + +;.equ CLKPR = 0x61 + +.org 0x0000 + rjmp RESET + +RESET: + +; ldi r16,0x80 +; ldi r17,0x00 +; sts CLKPR,r16 +; sts CLKPR,r17 + + + ldi R16,0x00 + out TCCR0A,R16 + ldi R16,0x05 + out TCCR0B,R16 + + ldi R16,0x01 + out DDRB,R16 + + ldi R17,0x00 + ldi R20,0x01 +Loop: + + + ldi R18,0xF0 ;; change this to change the blink rate +aloop: + in R17,TCNT0 + cpi R17,0x00 + brne aloop + +bloop: + in R17,TCNT0 + cpi R17,0x00 + breq bloop + + inc R18 + cpi R18,0x00 + brne aloop + + eor R16,R20 + out PORTB, R16 + rjmp Loop diff --git a/spi01/dumphex.c b/spi01/dumphex.c new file mode 100644 index 0000000..16afc7c --- /dev/null +++ b/spi01/dumphex.c @@ -0,0 +1,193 @@ + +//------------------------------------------------------------------- +//------------------------------------------------------------------- +//------------------------------------------------------------------- +#include +#include +#include +//------------------------------------------------------------------- +unsigned char mem[0x10000]; +#define ROMMASK 0x00FFFF +unsigned short rom[ROMMASK+1]; + +FILE *fpout; + +unsigned char gstring[80]; +unsigned char newline[1024]; + + +//----------------------------------------------------------------------------- +int readhex ( FILE *fp ) +{ +//unsigned int errors; + +unsigned int addhigh; +unsigned int add; + +unsigned int ra; +//unsigned int rb; + +//unsigned int pages; +//unsigned int page; + +unsigned int line; + +unsigned char checksum; + +unsigned int len; +unsigned int maxadd; + +unsigned char t; + + addhigh=0; + memset(rom,0x55,sizeof(rom)); + + line=0; + while(fgets(newline,sizeof(newline)-1,fp)) + { + line++; + //printf("%s",newline); + if(newline[0]!=':') + { + printf("Syntax error <%u> no colon\n",line); + continue; + } + gstring[0]=newline[1]; + gstring[1]=newline[2]; + gstring[2]=0; + + len=strtoul(gstring,NULL,16); + checksum=0; + for(ra=0;ra<(len+5);ra++) + { + gstring[0]=newline[(ra<<1)+1]; + gstring[1]=newline[(ra<<1)+2]; + gstring[2]=0; + checksum+=(unsigned char)strtoul(gstring,NULL,16); + } + if(checksum) + { + printf("checksum error <%u>\n",line); + } + gstring[0]=newline[3]; + gstring[1]=newline[4]; + gstring[2]=newline[5]; + gstring[3]=newline[6]; + gstring[4]=0; + add=strtoul(gstring,NULL,16); + add|=addhigh; + + + if(add>0x80000) + { + printf("address too big 0x%04X\n",add); + return(1); + } + if(len&1) + { + printf("length odd\n"); + return(1); + } + + + + gstring[0]=newline[7]; + gstring[1]=newline[8]; + gstring[2]=0; + t=(unsigned char)strtoul(gstring,NULL,16); + + //;llaaaattdddddd + //01234567890 + + switch(t) + { + default: + printf("UNKOWN type %02X <%u>\n",t,line); + break; + case 0x00: + len>>=1; + for(ra=0;ramaxadd) maxadd=add; + + gstring[0]=newline[(ra<<2)+9+2]; + gstring[1]=newline[(ra<<2)+9+3]; + gstring[2]=newline[(ra<<2)+9+0]; + gstring[3]=newline[(ra<<2)+9+1]; + gstring[4]=0; + + rom[add>>1]=(unsigned short)strtoul(gstring,NULL,16); + fprintf(fpout," 0x%04X, //%08X\n",rom[add>>1],add>>1); + add+=2; + } + break; + case 0x01: + printf("End of data\n"); + break; + case 0x02: + gstring[0]=newline[9]; + gstring[1]=newline[10]; + gstring[2]=newline[11]; + gstring[3]=newline[12]; + gstring[4]=0; + addhigh=strtoul(gstring,NULL,16); + addhigh<<=16; + printf("addhigh %08X\n",addhigh); + break; + + } + } + + //printf("%u lines processed\n",line); + //printf("%08X\n",maxadd); + + //if(maxadd&0x7F) + //{ + //maxadd+=0x80; + //maxadd&=0xFFFFFF80; + //printf("%08X\n",maxadd); + //} + + //for(ra=0;ra>1]); + //} + + return(0); + + +} + + +//------------------------------------------------------------------- +int main ( int argc, char *argv[] ) +{ + FILE *fp; +//unsigned int ra; + + if(argc<2) + { + printf("hex file not specified\n"); + return(1); + } + fp=fopen(argv[1],"rt"); + if(fp==NULL) + { + printf("error opening file [%s]\n",argv[1]); + return(1); + } + fpout=fopen("blinker.h","wt"); + if(fpout==NULL) return(1); + fprintf(fpout,"\nconst unsigned short rom[0x80]=\n{\n"); + if(readhex(fp)) return(1); + fprintf(fpout,"};\n\n"); + fclose(fpout); + + + + return(0); +} +//------------------------------------------------------------------- +//------------------------------------------------------------------- + diff --git a/spi01/spi01.c b/spi01/spi01.c index d2a41fa..06f0c8c 100644 --- a/spi01/spi01.c +++ b/spi01/spi01.c @@ -2,6 +2,8 @@ //------------------------------------------------------------------------- //------------------------------------------------------------------------- +#include "blinker.h" + extern void PUT32 ( unsigned int, unsigned int ); extern unsigned int GET32 ( unsigned int ); extern void dummy ( unsigned int ); @@ -105,26 +107,16 @@ void hexstring ( unsigned int d ) uart_putc(0x0D); uart_putc(0x0A); } -//spix_clk = (system_clock_freq)/(2*(speed_field+1)) -//spix_clk = 250000000/(2*(sf+1)) -//spix_clk = 125000000/(sf+1) -//spix_clk = 125000000/(0xFFF+1) = 30.52khz. //GPIO7 SPI0_CE1_N P1-26 //GPIO8 SPI0_CE0_N P1-24 //GPIO9 SPI0_MISO P1-21 //GPIO10 SPI0_MOSI P1-19 //GPIO11 SPI0_SCLK P1-23 -//alt function 0 for all... - +//alt function 0 for all of the above //P1 1 +3V3 -//P1 6 GND -//P1 9 GND -//P1 14 GND -//P1 20 GND //P1 25 GND -//p1 22 GPIO_GEN6 //p1 26 GPIO_CE1 @@ -155,14 +147,160 @@ void spi_init ( void ) ra&=~(7<<0); //gpio10/ ra|=4<<0; //alt0 ra&=~(7<<3); //gpio11/ - ra|=4<<0; //alt0 + ra|=4<<3; //alt0 PUT32(GPFSEL1,ra); PUT32(AUX_SPI0_CS,0x0000030); - PUT32(AUX_SPI0_CLK,0xFFFF); + PUT32(AUX_SPI0_CLK,0x0000); //slowest possible, could probably go faster here +} +//------------------------------------------------------------------------ +unsigned int pdi_command ( unsigned int cmd ) +{ + unsigned int data; + + PUT32(AUX_SPI0_CS,0x004000B0); //TA=1 cs asserted + while(1) + { + if(GET32(AUX_SPI0_CS)&(1<<18)) break; //TXD + } + PUT32(AUX_SPI0_FIFO,(cmd>>24)&0xFF); + PUT32(AUX_SPI0_FIFO,(cmd>>16)&0xFF); + PUT32(AUX_SPI0_FIFO,(cmd>> 8)&0xFF); + PUT32(AUX_SPI0_FIFO,(cmd>> 0)&0xFF); + while(1) if(GET32(AUX_SPI0_CS)&(1<<16)) break; + while(1) if(GET32(AUX_SPI0_CS)&(1<<17)) break; + data=GET32(AUX_SPI0_FIFO)&0xFF; + while(1) if(GET32(AUX_SPI0_CS)&(1<<17)) break; + data<<=8; + data|=GET32(AUX_SPI0_FIFO)&0xFF; + while(1) if(GET32(AUX_SPI0_CS)&(1<<17)) break; + data<<=8; + data|=GET32(AUX_SPI0_FIFO)&0xFF; + while(1) if(GET32(AUX_SPI0_CS)&(1<<17)) break; + data<<=8; + data|=GET32(AUX_SPI0_FIFO)&0xFF; + PUT32(AUX_SPI0_CS,0x00400000); //cs0 comes back up + return(data); +} +//------------------------------------------------------------------------ +int prog_avr ( void ) +{ + unsigned int ra; + unsigned int rb; + unsigned int rc; + + unsigned int pages; + unsigned int psize; + unsigned int poff; + + + + + ra=pdi_command(0xAC530000); + if((ra&0x0000FF00)!=0x00005300) + { + hexstring(0xBAD); + return(1); + } + rb=0; + ra=pdi_command(0x30000000); + rb<<=8; rb|=ra&0xFF; + ra=pdi_command(0x30000100); + rb<<=8; rb|=ra&0xFF; + ra=pdi_command(0x30000200); + rb<<=8; rb|=ra&0xFF; + hexstring(rb); + if(rb!=0x001E9587) + { + //not really an error, this code is written for the atmega32u4 + //should be easy to adapt to another part. + hexstring(0xBAD); + return(1); + } + for(ra=0;ra<10;ra++) + { + rb=pdi_command(0x28000000|(ra<<8)); + rc=pdi_command(0x20000000|(ra<<8)); + hexstring((ra<<16)|((rb&0xFF)<<8)|(rc&0xFF)); + } + + pdi_command(0xAC800000); //chip erase + PUT32(AUX_SPI0_CS,0x00000000); //deassert reset +for(ra=0;ra<0x100000;ra++) dummy(ra); + PUT32(AUX_SPI0_CS,0x00400000); //assert reset +for(ra=0;ra<0x10000;ra++) dummy(ra); + + ra=pdi_command(0xAC530000); + hexstring(ra); + if((ra&0x0000FF00)!=0x00005300) + { + hexstring(0xBAD); + return(1); + } + rb=0; + ra=pdi_command(0x30000000); + rb<<=8; rb|=ra&0xFF; + ra=pdi_command(0x30000100); + rb<<=8; rb|=ra&0xFF; + ra=pdi_command(0x30000200); + rb<<=8; rb|=ra&0xFF; + hexstring(rb); + if(rb!=0x001E9587) + { + //not really an error, this code is written for the atmega32u4 + //should be easy to adapt to another part. + hexstring(0xBAD); + return(1); + } + for(ra=0;ra<10;ra++) + { + rb=pdi_command(0x28000000|(ra<<8)); + rc=pdi_command(0x20000000|(ra<<8)); + hexstring((ra<<16)|((rb&0xFF)<<8)|(rc&0xFF)); + } + + psize=sizeof(rom); + psize>>=1; + pages=psize>>6; + + hexstring(psize); + hexstring(pages); + + poff=0; + //for(np=0;np=psize) break; + pdi_command(0x40000000|(ra<<8)|((rom[poff]>>0)&0xFF)); //low first + pdi_command(0x48000000|(ra<<8)|((rom[poff]>>8)&0xFF)); //then high + poff++; + } + //for(;ra<64;ra++) + //{ + //pdi_command(0x400000FF|(ra<<8)); //low first + //pdi_command(0x480000FF|(ra<<8)); //then high + ////poff++; + //} + pdi_command(0x4D000000); + pdi_command(0x4C000000);//|(np<<14)); +for(ra=0;ra<0x10000;ra++) dummy(ra); + } + for(ra=0;ra<10;ra++) + { + rb=pdi_command(0x28000000|(ra<<8)); + rc=pdi_command(0x20000000|(ra<<8)); + hexstring((ra<<16)|((rb&0xFF)<<8)|(rc&0xFF)); + } + + ra=pdi_command(0x50000000); hexstring(ra); + ra=pdi_command(0x58080000); hexstring(ra); + ra=pdi_command(0x50080000); hexstring(ra); + + return(0); } //------------------------------------------------------------------------ int notmain ( void ) @@ -178,35 +316,11 @@ int notmain ( void ) spi_init(); PUT32(AUX_SPI0_CS,0x00400000); //cs1 low, reset for(ra=0;ra<0x10000;ra++) dummy(ra); - PUT32(AUX_SPI0_CS,0x004000B0); //TA=1 cs asserted - while(1) - { - if(GET32(AUX_SPI0_CS)&(1<<18)) break; //TXD - } - PUT32(AUX_SPI0_FIFO,0xAC); - PUT32(AUX_SPI0_FIFO,0x53); - PUT32(AUX_SPI0_FIFO,0x00); - PUT32(AUX_SPI0_FIFO,0x00); - while(1) - { - ra=GET32(AUX_SPI0_CS); - hexstring(ra); - if(ra&(1<<16)) break; - } - hexstring(GET32(AUX_SPI0_CS)); - hexstring(GET32(AUX_SPI0_FIFO)); - hexstring(GET32(AUX_SPI0_CS)); - hexstring(GET32(AUX_SPI0_FIFO)); - hexstring(GET32(AUX_SPI0_CS)); - hexstring(GET32(AUX_SPI0_FIFO)); - hexstring(GET32(AUX_SPI0_CS)); - hexstring(GET32(AUX_SPI0_FIFO)); - hexstring(GET32(AUX_SPI0_CS)); - PUT32(AUX_SPI0_CS,0x00400000); //cs comes back up - + prog_avr(); + PUT32(AUX_SPI0_CS,0x00000000); //cs1 comes back up + hexstring(0x12345678); return(0); -} -//------------------------------------------------------------------------- +}//------------------------------------------------------------------------- //-------------------------------------------------------------------------