594e04fdabbf016583bccb90ef4525e45c23578d
[goodfet] / firmware / apps / spi / spi.c
1 //GoodFET SPI Application
2 //Handles basic I/O
3
4 //Higher level left to client application.
5
6 #include "platform.h"
7 #include "command.h"
8
9 #include <signal.h>
10 #include <io.h>
11 #include <iomacros.h>
12
13
14 //Pins and I/O
15 #define SS   BIT0
16 #define MOSI BIT1
17 #define MISO BIT2
18 #define SCK  BIT3
19
20
21 //This could be more accurate.
22 //Does it ever need to be?
23 #define SPISPEED 0
24 #define SPIDELAY(x) delay(x)
25
26 #define SETMOSI P5OUT|=MOSI
27 #define CLRMOSI P5OUT&=~MOSI
28 #define SETCLK P5OUT|=SCK
29 #define CLRCLK P5OUT&=~SCK
30 #define READMISO (P5IN&MISO?1:0)
31
32
33
34 //! Set up the pins for SPI mode.
35 void spisetup(){
36   P5OUT|=SS;
37   P5DIR|=MOSI+SCK+SS;
38   P5DIR&=~MISO;
39   
40   //Begin a new transaction.
41   P5OUT&=~SS; 
42   P5OUT|=SS;
43 }
44
45
46 //! Read and write an SPI byte.
47 unsigned char spitrans8(unsigned char byte){
48   unsigned int bit;
49   //This function came from the SPI Wikipedia article.
50   //Minor alterations.
51   
52   for (bit = 0; bit < 8; bit++) {
53     /* write MOSI on trailing edge of previous clock */
54     if (byte & 0x80)
55       SETMOSI;
56     else
57       CLRMOSI;
58     byte <<= 1;
59  
60     /* half a clock cycle before leading/rising edge */
61     SPIDELAY(SPISPEED/2);
62     SETCLK;
63  
64     /* half a clock cycle before trailing/falling edge */
65     SPIDELAY(SPISPEED/2);
66  
67     /* read MISO on trailing edge */
68     byte |= READMISO;
69     CLRCLK;
70   }
71   
72   return byte;
73 }
74
75
76 //! Enable SPI writing
77 void spiflash_wrten(){
78   P5OUT&=~SS; //Drop !SS to begin transaction.
79   spitrans8(0x04);//Write Disable
80   P5OUT|=SS;  //Raise !SS to end transaction.
81   P5OUT&=~SS; //Drop !SS to begin transaction.
82   spitrans8(0x06);//Write Enable
83   P5OUT|=SS;  //Raise !SS to end transaction.
84 }
85
86
87 //! Grab the SPI flash status byte.
88 unsigned char spiflash_status(){
89   unsigned char c;
90   P5OUT|=SS;  //Raise !SS to end transaction.
91   P5OUT&=~SS; //Drop !SS to begin transaction.
92   spitrans8(0x05);//GET STATUS
93   c=spitrans8(0xFF);
94   P5OUT|=SS;  //Raise !SS to end transaction.
95   return c;
96 }
97
98
99 //! Grab the SPI flash status byte.
100 void spiflash_setstatus(unsigned char c){
101   P5OUT&=~SS; //Drop !SS to begin transaction.
102   spitrans8(0x01);//SET STATUS
103   spitrans8(c);
104   P5OUT|=SS;  //Raise !SS to end transaction.
105   //return c;
106 }
107
108 //! Peek some blocks.
109 void spiflash_peek(unsigned char app,
110                    unsigned char verb,
111                    unsigned char len){
112   register char blocks=(len>3?cmddata[3]:1);
113   unsigned char i,j;
114   
115   P5OUT&=~SS; //Drop !SS to begin transaction.
116   spitrans8(0x03);//Flash Read Command
117   len=3;//write 3 byte pointer
118   for(i=0;i<len;i++)
119     spitrans8(cmddata[i]);
120   
121   //Send reply header
122   len=0x80;//128 byte chunk, repeated for each block
123   serial_tx(app);
124   serial_tx(verb);
125   serial_tx(len); //multiplied by block count.
126   
127   while(blocks--){
128     for(i=0;i<len;i++)
129       serial_tx(spitrans8(0));
130     
131     /* old fashioned
132     for(i=0;i<len;i++)
133       cmddata[i]=spitrans8(0);
134     txdata(app,verb,len);
135     */
136   }
137   P5OUT|=SS;  //Raise !SS to end transaction.
138 }
139
140 //! Handles a monitor command.
141 void spihandle(unsigned char app,
142                unsigned char verb,
143                unsigned char len){
144   unsigned char i;
145   
146   
147   //Raise !SS to end transaction, just in case we forgot.
148   P5OUT|=SS;  
149   
150   switch(verb){
151     //PEEK and POKE might come later.
152   case READ:
153   case WRITE:
154     P5OUT&=~SS; //Drop !SS to begin transaction.
155     for(i=0;i<len;i++)
156       cmddata[i]=spitrans8(cmddata[i]);
157     P5OUT|=SS;  //Raise !SS to end transaction.
158     txdata(app,verb,len);
159     break;
160
161
162   case SPI_JEDEC://Grab 3-byte JEDEC ID.
163     P5OUT&=~SS; //Drop !SS to begin transaction.
164     spitrans8(0x9f);
165     len=3;
166     for(i=0;i<len;i++)
167       cmddata[i]=spitrans8(cmddata[i]);
168     txdata(app,verb,len);
169     P5OUT|=SS;  //Raise !SS to end transaction.
170     break;
171
172
173   case PEEK://Grab 128 bytes from an SPI Flash ROM
174     spiflash_peek(app,verb,len);
175     break;
176
177
178   case POKE://Poke up bytes from an SPI Flash ROM.
179     spiflash_setstatus(0x02);
180     spiflash_wrten();
181     
182     P5OUT&=~SS; //Drop !SS to begin transaction.
183     spitrans8(0x02); //Poke command.
184     
185     //First three bytes are address, then data.
186     for(i=0;i<len;i++)
187       spitrans8(cmddata[i]);
188     P5OUT|=SS;  //Raise !SS to end transaction.
189     
190     
191     while(spiflash_status()&0x01)//while busy
192       P1OUT^=1;
193     P1OUT&=~1;
194     
195     txdata(app,verb,len);
196     break;
197
198
199   case SPI_ERASE://Erase the SPI Flash ROM.
200     spiflash_wrten();
201     P5OUT&=~SS; //Drop !SS to begin transaction.
202     spitrans8(0xC7);//Chip Erase
203     P5OUT|=SS;  //Raise !SS to end transaction.
204     
205         
206     while(spiflash_status()&0x01)//while busy
207       P1OUT^=1;
208     P1OUT&=~1;
209     
210     txdata(app,verb,0);
211     break;
212
213   case SETUP:
214     spisetup();
215     txdata(app,verb,0);
216     break;
217   }
218   
219 }