f1fe5b78eaa1b63c761b8c37bf7485a335edd620
[goodfet] / firmware / apps / avr / avr.c
1 /*! \file avr.c
2   \author Travis Goodspeed
3   \brief AVR SPI Programmer
4 */
5
6 #include "platform.h"
7 #include "command.h"
8
9 #include <signal.h>
10 #include <io.h>
11 #include <iomacros.h>
12
13 #include "avr.h"
14 #include "glitch.h"
15
16 //! Setup the AVR pins.
17 void avrsetup(){
18   spisetup();
19   
20   glitchsetup();
21 }
22
23 //! Initialized an attached AVR.
24 void avrconnect(){
25   //set I/O pins
26   avrsetup();
27   
28   //Pulse !RST (SS) at least twice while CLK is low.
29   CLRCLK;
30   CLRSS;
31
32   SETSS;
33   CLRCLK;
34   delay(500);
35   CLRSS;
36   delay(500);
37   
38   //Enable programming
39   avr_prgen();
40 }
41
42 //! Read and write an SPI byte with delays.
43 unsigned char avrtrans8(unsigned char byte){
44   register unsigned int bit;
45   //This function came from the SPI Wikipedia article.
46   //Minor alterations.
47   
48   for (bit = 0; bit < 8; bit++) {
49     /* write MOSI on trailing edge of previous clock */
50     if (byte & 0x80)
51       SETMOSI;
52     else
53       CLRMOSI;
54     byte <<= 1;
55     
56     delay(2);
57     SETCLK;
58   
59     /* read MISO on trailing edge */
60     byte |= READMISO;
61     delay(2);
62     CLRCLK;
63   }
64   
65   return byte;
66 }
67
68 //! Perform a 4-byte exchange.
69 u8 avrexchange(u8 a, u8 b, u8 c, u8 d){
70   avrtrans8(a);
71   avrtrans8(b);
72   if(avrtrans8(c)!=b){
73     debugstr("AVR sync error, b not returned as c.");
74     //Reconnect here?
75   }
76   return avrtrans8(d);
77 }
78
79 //! Enable AVR programming mode.
80 void avr_prgen(){
81   avrexchange(0xAC, 0x53, 0, 0);
82 }
83
84 //! Is the AVR ready or busy?
85 u8 avr_isready(){
86   return avrexchange(0xF0, 0, 0, 0);
87 }
88
89 //! Read AVR device code.
90 u8 avr_sig(u8 i){
91   return avrexchange(0x30, //Read signature byte
92               0x00,
93               i&0x03,      //sig adr
94               0x00         //don't care.
95               );
96 }
97
98 //! Erase an AVR device
99 void avr_erase(){
100   avrexchange(0xAC, 0x80, 0, 0);
101 }
102
103 //! Read lock bits.
104 u8 avr_lockbits(){
105   return avrexchange(0x58, 0, 0, 0);
106 }
107
108 //! Read a byte of EEPROM.
109 u8 avr_peekeeprom(u16 adr){
110   return avrexchange(0xA0, adr>>8, adr&0xFF, 0);
111 }
112 //! Read a byte of EEPROM.
113 u8 avr_pokeeeprom(u16 adr, u8 val){
114   return avrexchange(0xC0, adr>>8, adr&0xFF, val);
115 }
116
117 //! Read a byte of Flash
118 u8 avr_peekflash(u16 adr){
119   u16 a=adr>>1;
120   if(adr&1) //high byte
121     return avrexchange(0x28,a>>8,a&0xff,0);
122   else      //low byte
123     return avrexchange(0x20,a>>8,a&0xff,0);
124 }
125
126
127 //! Handles an AVR command.
128 void avrhandle(unsigned char app,
129                unsigned char verb,
130                unsigned long len){
131   unsigned long i;
132   unsigned int at;
133   static u8 connected=0;
134   
135   if(!avr_isready() && connected)
136     debugstr("AVR is not yet ready.");
137   
138   switch(verb){
139   case READ:
140   case WRITE:
141     for(i=0;i<len;i++)
142       cmddata[i]=avrtrans8(cmddata[i]);
143     txdata(app,verb,len);
144     break;
145   case SETUP:
146     avrsetup();
147     txdata(app,verb,0);
148     break;
149   case START://returns device code
150     avrconnect();
151     //no break here
152   case AVR_PEEKSIG:
153     for(i=0;i<4;i++)
154       cmddata[i]=avr_sig(i);
155     txdata(app,verb,4);
156     break;
157   case AVR_ERASE:
158     avr_erase();
159     txdata(app,verb,0);
160     break;
161   case AVR_PEEKLOCK:
162     cmddata[0]=avr_lockbits();
163     txdata(app,verb,1);
164     break;
165
166   case AVR_POKEEEPROM:
167     avr_pokeeeprom(cmddataword[0], cmddata[2]);
168     //no break here.
169   case AVR_PEEKEEPROM:
170     cmddata[0]=avr_peekeeprom(cmddataword[0]);
171     txdata(app,verb,1);
172     break;
173   case PEEK:
174     //cmddata[0]=avr_peekflash(cmddataword[0]);
175     //txdata(app,verb,1);
176     at=cmddataword[0];
177     
178     //Fetch large blocks for bulk fetches,
179     //small blocks for individual peeks.
180     if(len>2){
181       len=(cmddataword[1]);//always even.
182     }else{
183       len=1;
184     }
185     txhead(app,verb,len);
186     for(i=0;i<len;i++){
187       serial_tx(avr_peekflash(at++));
188     }
189     break;
190   case POKE:
191   default:
192     debugstr("Verb unimplemented in AVR application.");
193     txdata(app,NOK,0);
194     break;
195   }
196 }
197