adding spi01 example.

This commit is contained in:
dwelch67
2014-04-08 09:56:31 -04:00
parent 378efabd89
commit 90c69e37c1
7 changed files with 542 additions and 43 deletions

View File

@@ -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

View File

@@ -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

27
spi01/blinker.h Normal file
View File

@@ -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
};

34
spi01/blinker01.s Normal file
View File

@@ -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

53
spi01/blinker02.s Normal file
View File

@@ -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

193
spi01/dumphex.c Normal file
View File

@@ -0,0 +1,193 @@
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//-------------------------------------------------------------------
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;ra<len;ra++)
{
if(add>maxadd) 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<maxadd;ra+=2)
//{
//printf("0x%04X: 0x%04X\n",ra,rom[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);
}
//-------------------------------------------------------------------
//-------------------------------------------------------------------

View File

@@ -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<pages;np++)
{
for(ra=0;ra<64;ra++)
{
// if(poff>=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);
}
//-------------------------------------------------------------------------
}//-------------------------------------------------------------------------
//-------------------------------------------------------------------------