Removed P5REN element from goodfet.c
[goodfet] / firmware / apps / spi / spi.c
1 /*! \file spi.c
2   \author Travis Goodspeed
3   \brief SPI Master
4 */
5
6 //Higher level left to client application.
7
8 #include "platform.h"
9 #include "command.h"
10
11 #include <signal.h>
12 #include <io.h>
13 #include <iomacros.h>
14
15 #include "spi.h"
16
17 //This could be more accurate.
18 //Does it ever need to be?
19 #define SPISPEED 0
20 #define SPIDELAY(x)
21 //delay(x)
22
23
24 //! Set up the pins for SPI mode.
25 void spisetup(){
26   SETSS;
27   P5DIR|=MOSI+SCK+BIT0; //BIT0 might be SS
28   P5DIR&=~MISO;
29   DIRSS;
30   
31   //Begin a new transaction.
32   CLRSS; 
33   SETSS;
34 }
35
36
37 //! Read and write an SPI byte.
38 unsigned char spitrans8(unsigned char byte){
39   register unsigned int bit;
40   //This function came from the SPI Wikipedia article.
41   //Minor alterations.
42   
43   for (bit = 0; bit < 8; bit++) {
44     /* write MOSI on trailing edge of previous clock */
45     if (byte & 0x80)
46       SETMOSI;
47     else
48       CLRMOSI;
49     byte <<= 1;
50  
51     SETCLK;
52   
53     /* read MISO on trailing edge */
54     byte |= READMISO;
55     CLRCLK;
56   }
57   
58   return byte;
59 }
60
61
62 //! Enable SPI writing
63 void spiflash_wrten(){
64   SETSS;
65   /*
66   CLRSS; //Drop !SS to begin transaction.
67   spitrans8(0x04);//Write Disable
68   SETSS;  //Raise !SS to end transaction.
69   */
70   CLRSS; //Drop !SS to begin transaction.
71   spitrans8(0x06);//Write Enable
72   SETSS;  //Raise !SS to end transaction.
73 }
74
75
76 //! Grab the SPI flash status byte.
77 unsigned char spiflash_status(){
78   unsigned char c;
79   SETSS;  //Raise !SS to end transaction.
80   CLRSS; //Drop !SS to begin transaction.
81   spitrans8(0x05);//GET STATUS
82   c=spitrans8(0xFF);
83   SETSS;  //Raise !SS to end transaction.
84   return c;
85 }
86
87
88 //! Grab the SPI flash status byte.
89 void spiflash_setstatus(unsigned char c){
90   SETSS;
91   CLRSS; //Drop !SS to begin transaction.
92   spitrans8(0x01);//SET STATUS
93   spitrans8(c);
94   SETSS;  //Raise !SS to end transaction.
95   //return c;
96 }
97
98
99 //! Read a block to a buffer.
100 void spiflash_peekblock(unsigned long adr,
101                         unsigned char *buf,
102                         unsigned int len){
103   unsigned char i;
104   
105   SETSS;
106   CLRSS; //Drop !SS to begin transaction.
107   spitrans8(0x03);//Flash Read Command
108   
109   //Send address
110   spitrans8((adr&0xFF0000)>>16);
111   spitrans8((adr&0xFF00)>>8);
112   spitrans8(adr&0xFF);
113   
114   for(i=0;i<len;i++)
115     buf[i]=spitrans8(0);
116   SETSS;  //Raise !SS to end transaction.
117 }
118
119 //! Read a block to a buffer.
120 void spiflash_pokeblock(unsigned long adr,
121                         unsigned char *buf,
122                         unsigned int len){
123   unsigned int i;
124   
125   SETSS;
126   
127   //if(len!=0x100)
128   //  debugstr("Non-standard block size.");
129   
130   while(spiflash_status()&0x01);//minor performance impact
131   
132   spiflash_setstatus(0x02);
133   spiflash_wrten();
134   
135   //Are these necessary?
136   //spiflash_setstatus(0x02);
137   //spiflash_wrten();
138   
139   CLRSS; //Drop !SS to begin transaction.
140   spitrans8(0x02); //Poke command.
141   
142   //Send address
143   spitrans8((adr&0xFF0000)>>16);
144   spitrans8((adr&0xFF00)>>8);
145   spitrans8(adr&0xFF);
146
147   for(i=0;i<len;i++)
148     spitrans8(buf[i]);
149   SETSS;  //Raise !SS to end transaction.
150   
151   while(spiflash_status()&0x01);//minor performance impact
152   return;
153 }
154
155
156 //! Write many blocks to the SPI Flash.
157 void spiflash_pokeblocks(unsigned long adr,
158                          unsigned char *buf,
159                          unsigned int len){
160   long off=0;//offset of this block
161   int blen;//length of this block
162   SETSS;
163   
164   while(off<len){
165     //calculate block length
166     blen=(len-off>0x100?0x100:len-off);
167     //write the block
168     spiflash_pokeblock(adr+off,
169                        buf+off,
170                        blen);
171     //add offset
172     off+=blen;
173   }
174 }
175
176
177
178 //! Peek some blocks.
179 void spiflash_peek(unsigned char app,
180                    unsigned char verb,
181                    unsigned long len){
182   unsigned int i;
183   CLRSS; //Drop !SS to begin transaction.
184   spitrans8(0x03);//Flash Read Command
185   len=3;//write 3 byte pointer
186   for(i=0;i<len;i++)
187     spitrans8(cmddata[i]);
188   
189   //Send reply header
190   len=0x1000;
191   txhead(app,verb,len);
192   
193   while(len--)
194     serial_tx(spitrans8(0));
195   
196   SETSS;  //Raise !SS to end transaction.
197 }
198
199
200 //! Erase a sector.
201 void spiflash_erasesector(unsigned long adr){
202   //debugstr("Erasing a 4kB sector.");
203
204   //Write enable.
205   spiflash_wrten();
206
207   //Begin
208   CLRSS;
209
210   //Second command.
211   spitrans8(0x20);
212   //Send address
213   spitrans8((adr&0xFF0000)>>16);
214   spitrans8((adr&0xFF00)>>8);
215   spitrans8(adr&0xFF);
216
217   SETSS;
218   while(spiflash_status()&0x01);//while busy
219   //debugstr("Erased.");
220 }
221
222
223 //! Handles a monitor command.
224 void spihandle(unsigned char app,
225                unsigned char verb,
226                unsigned long len){
227   unsigned long i;
228   
229   //Raise !SS to end transaction, just in case we forgot.
230   SETSS;
231   spisetup();
232   
233   switch(verb){
234     //PEEK and POKE might come later.
235   case READ:
236   case WRITE:
237     CLRSS; //Drop !SS to begin transaction.
238     for(i=0;i<len;i++)
239       cmddata[i]=spitrans8(cmddata[i]);
240     SETSS;  //Raise !SS to end transaction.
241     txdata(app,verb,len);
242     break;
243
244
245   case SPI_JEDEC://Grab 3-byte JEDEC ID.
246     CLRSS; //Drop !SS to begin transaction.
247     spitrans8(0x9f);
248     len=3;  //Length is variable in some chips, 3 minimum.
249     for(i=0;i<len;i++)
250       cmddata[i]=spitrans8(cmddata[i]);
251     txdata(app,verb,len);
252     SETSS;  //Raise !SS to end transaction.
253     break;
254
255
256   case PEEK://Grab 128 bytes from an SPI Flash ROM
257     spiflash_peek(app,verb,len);
258     break;
259
260
261   case POKE://Poke up bytes from an SPI Flash ROM.
262     spiflash_pokeblocks(cmddatalong[0],//adr
263                         cmddata+4,//buf
264                         len-4);//len    
265     
266     txdata(app,verb,0);
267     break;
268
269
270   case SPI_ERASE://Erase the SPI Flash ROM.
271     spiflash_wrten();
272     CLRSS; //Drop !SS to begin transaction.
273     spitrans8(0xC7);//Chip Erase
274     SETSS;  //Raise !SS to end transaction.
275     
276     
277     while(spiflash_status()&0x01)//while busy
278       PLEDOUT^=PLEDPIN;
279     PLEDOUT&=~PLEDPIN;
280     
281     txdata(app,verb,0);
282     break;
283
284   case SETUP:
285     spisetup();
286     txdata(app,verb,0);
287     break;
288   }
289   
290 }