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