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