0cc4c0da79842727fd70833ad4dba75b8321400d
[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
21 //! Initialized an attached AVR.
22 void avrconnect(){
23   //set I/O pins
24   avrsetup(); //Cut this?
25   
26   SETSS;
27   //delay(50);
28   
29   //Pulse !RST (SS) at least twice while CLK is low.
30   CLRCLK;
31   CLRSS;
32   //delay(5);
33
34   SETSS;
35   CLRCLK;
36   //delay(5);
37   CLRSS;
38   //delay(5);
39   
40   //Enable programming
41   avr_prgen();
42 }
43
44 //! Read and write an SPI byte with delays.
45 u8 avrtrans8(u8 byte){
46   register u16 bit;
47   //This function came from the SPI Wikipedia article.
48   //Minor alterations.
49   
50   for (bit = 0; bit < 8; bit++) {
51     /* write MOSI on trailing edge of previous clock */
52     if (byte & 0x80)
53       SETMOSI;
54     else
55       CLRMOSI;
56     byte <<= 1;
57     
58     delay(2);
59     SETCLK;
60   
61     /* read MISO on trailing edge */
62     byte |= READMISO;
63     delay(2);
64     CLRCLK;
65   }
66   
67   return byte;
68 }
69
70 //! Perform a 4-byte exchange.
71 u8 avrexchange(u8 a, u8 b, u8 c, u8 d){
72   avrtrans8(a);
73   avrtrans8(b);
74   if(avrtrans8(c)!=b){
75     //debugstr("AVR sync error, b not returned as c.");
76     //Reconnect here?
77   }
78   return avrtrans8(d);
79 }
80
81 //! Enable AVR programming mode.
82 void avr_prgen(){
83   avrexchange(0xAC, 0x53, 0, 0);
84 }
85
86 //! Is the AVR ready or busy?
87 u8 avr_isready(){
88   return avrexchange(0xF0, 0, 0, 0);
89 }
90
91 //! Read AVR device code.
92 u8 avr_sig(u8 i){
93   return avrexchange(0x30, //Read signature byte
94               0x00,
95               i&0x03,      //sig adr
96               0x00         //don't care.
97               );
98 }
99
100 //! Erase an AVR device
101 void avr_erase(){
102   avrexchange(0xAC, 0x80, 0, 0);
103 }
104
105 //! Read lock bits.
106 u8 avr_lockbits(){
107   return avrexchange(0x58, 0, 0, 0);
108 }
109 //! Write lock bits.
110 void avr_setlock(u8 bits){
111   avrexchange(0xAC,0xE0,0x00,
112               bits);
113 }
114
115 //! Read a byte of EEPROM.
116 u8 avr_peekeeprom(u16 adr){
117   return avrexchange(0xA0, adr>>8, adr&0xFF, 0);
118 }
119 //! Read a byte of EEPROM.
120 u8 avr_pokeeeprom(u16 adr, u8 val){
121   return avrexchange(0xC0, adr>>8, adr&0xFF, val);
122 }
123
124 //! Read a byte of Flash
125 u8 avr_peekflash(u16 adr){
126   u16 a=adr>>1;
127   if(adr&1) //high byte
128     return avrexchange(0x28,a>>8,a&0xff,0);
129   else      //low byte
130     return avrexchange(0x20,a>>8,a&0xff,0);
131 }
132
133 void avr_bulk_load(u16 start, u16 len, u8 *data) {
134   u16 adr;
135   for (adr = 0; adr < len; adr++) {
136     u16 a = adr + start;
137     avrexchange((adr & 1) ? 0x48 : 0x40,
138                 a >> 9,
139                 (a >> 1) & 0xff,
140                 data[adr]);
141   }
142 }
143
144 //! Handles an AVR command.
145 void avrhandle(unsigned char app,
146                unsigned char verb,
147                unsigned long len){
148   unsigned long i;
149   unsigned int at;
150   
151   /*
152   if(!avr_isready() && connected)
153     debugstr("AVR is not yet ready.");
154   */
155   
156   switch(verb){
157   case READ:
158   case WRITE:
159     for(i=0;i<len;i++)
160       cmddata[i]=avrtrans8(cmddata[i]);
161     txdata(app,verb,len);
162     break;
163   case SETUP:
164     avrsetup();
165     txdata(app,verb,0);
166     break;
167   case START:
168     avrconnect();
169     txdata(app,verb,0);
170     break;//Used to fall through here.
171   case STOP:
172     SETSS;
173     txdata(app, verb, 0);
174   case AVR_PEEKSIG:
175     for(i=0;i<4;i++)
176       cmddata[i]=avr_sig(i);
177     txdata(app,verb,4);
178     break;
179   case AVR_ERASE:
180     avr_erase();
181     txdata(app,verb,0);
182     break;
183   case AVR_PEEKLOCK:
184     cmddata[0]=avr_lockbits();
185     txdata(app,verb,1);
186     break;
187   case AVR_POKELOCK:
188     avr_setlock(cmddata[0]);
189     txdata(app,verb,0);
190     break;
191   case AVR_POKEEEPROM:
192     avr_pokeeeprom(cmddataword[0], cmddata[2]);
193     //no break here.
194   case AVR_PEEKEEPROM:
195     cmddata[0]=avr_peekeeprom(cmddataword[0]);
196     txdata(app,verb,1);
197     break;
198   case AVR_BULKLOAD:
199     if (len < 3) {
200       debugstr("Length too short");
201       txdata(app, NOK, 0);
202     } else {
203       at = cmddataword[0];
204       avr_bulk_load(at, len - 2, cmddata + 2);
205       txdata(app, verb, 0);
206     }
207     break;
208   case PEEK:
209     //cmddata[0]=avr_peekflash(cmddataword[0]);
210     //txdata(app,verb,1);
211     at=cmddataword[0];
212     
213     //Fetch large blocks for bulk fetches,
214     //small blocks for individual peeks.
215     if(len>2){
216       len=(cmddataword[1]);//always even.
217     }else{
218       len=1;
219     }
220     txhead(app,verb,len);
221     for(i=0;i<len;i++){
222       serial_tx(avr_peekflash(at++));
223     }
224     break;
225   case POKE:
226   default:
227     debugstr("Verb unimplemented in AVR application.");
228     txdata(app,NOK,0);
229     break;
230   }
231 }
232