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