MSP430F5xx stuff; 1xx support is probably broken right now.
[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 #include <spi.h>
14
15 //This could be more accurate.
16 //Does it ever need to be?
17 #define SPISPEED 0
18 #define SPIDELAY(x) delay(x)
19
20
21 //! Set up the pins for SPI mode.
22 void spisetup(){
23   P5OUT|=SS;
24   P5DIR|=MOSI+SCK+SS;
25   P5DIR&=~MISO;
26   
27   //Begin a new transaction.
28   P5OUT&=~SS; 
29   P5OUT|=SS;
30 }
31
32
33 //! Read and write an SPI byte.
34 unsigned char spitrans8(unsigned char byte){
35   unsigned int bit;
36   //This function came from the SPI Wikipedia article.
37   //Minor alterations.
38   
39   for (bit = 0; bit < 8; bit++) {
40     /* write MOSI on trailing edge of previous clock */
41     if (byte & 0x80)
42       SETMOSI;
43     else
44       CLRMOSI;
45     byte <<= 1;
46  
47     /* half a clock cycle before leading/rising edge */
48     SPIDELAY(SPISPEED/2);
49     SETCLK;
50  
51     /* half a clock cycle before trailing/falling edge */
52     SPIDELAY(SPISPEED/2);
53  
54     /* read MISO on trailing edge */
55     byte |= READMISO;
56     CLRCLK;
57   }
58   
59   return byte;
60 }
61
62
63 //! Enable SPI writing
64 void spiflash_wrten(){
65   SETSS;
66   P5OUT&=~SS; //Drop !SS to begin transaction.
67   spitrans8(0x04);//Write Disable
68   P5OUT|=SS;  //Raise !SS to end transaction.
69   P5OUT&=~SS; //Drop !SS to begin transaction.
70   spitrans8(0x06);//Write Enable
71   P5OUT|=SS;  //Raise !SS to end transaction.
72 }
73
74
75 //! Grab the SPI flash status byte.
76 unsigned char spiflash_status(){
77   unsigned char c;
78   P5OUT|=SS;  //Raise !SS to end transaction.
79   P5OUT&=~SS; //Drop !SS to begin transaction.
80   spitrans8(0x05);//GET STATUS
81   c=spitrans8(0xFF);
82   P5OUT|=SS;  //Raise !SS to end transaction.
83   return c;
84 }
85
86
87 //! Grab the SPI flash status byte.
88 void spiflash_setstatus(unsigned char c){
89   SETSS;
90   CLRSS; //Drop !SS to begin transaction.
91   spitrans8(0x01);//SET STATUS
92   spitrans8(c);
93   SETSS;  //Raise !SS to end transaction.
94   //return c;
95 }
96
97
98 //! Read a block to a buffer.
99 void spiflash_peekblock(unsigned long adr,
100                         unsigned char *buf,
101                         unsigned int len){
102   unsigned char i;
103   
104   SETSS;
105   CLRSS; //Drop !SS to begin transaction.
106   spitrans8(0x03);//Flash Read Command
107   
108   //Send address
109   spitrans8((adr&0xFF0000)>>16);
110   spitrans8((adr&0xFF00)>>8);
111   spitrans8(adr&0xFF);
112   
113   for(i=0;i<len;i++)
114     buf[i]=spitrans8(0);
115   SETSS;  //Raise !SS to end transaction.
116 }
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 char i;
124   
125   SETSS;
126   
127   spiflash_setstatus(0x02);
128   spiflash_wrten();
129   
130   CLRSS; //Drop !SS to begin transaction.
131   spitrans8(0x02); //Poke command.
132   
133   //Send address
134   spitrans8((adr&0xFF0000)>>16);
135   spitrans8((adr&0xFF00)>>8);
136   spitrans8(adr&0xFF);
137
138   for(i=0;i<len;i++)
139     spitrans8(buf[i]);
140   SETSS;  //Raise !SS to end transaction.
141   
142   while(spiflash_status()&0x01)
143     ;
144   
145   return;
146 }
147
148
149 //! Peek some blocks.
150 void spiflash_peek(unsigned char app,
151                    unsigned char verb,
152                    unsigned char len){
153   register char blocks=(len>3?cmddata[3]:1);
154   unsigned char i;
155   
156   P5OUT&=~SS; //Drop !SS to begin transaction.
157   spitrans8(0x03);//Flash Read Command
158   len=3;//write 3 byte pointer
159   for(i=0;i<len;i++)
160     spitrans8(cmddata[i]);
161   
162   //Send reply header
163   len=0x80;//128 byte chunk, repeated for each block
164   serial_tx(app);
165   serial_tx(verb);
166   serial_tx(len); //multiplied by block count.
167   
168   while(blocks--){
169     for(i=0;i<len;i++)
170       serial_tx(spitrans8(0));
171     
172     /* old fashioned
173     for(i=0;i<len;i++)
174       cmddata[i]=spitrans8(0);
175     txdata(app,verb,len);
176     */
177   }
178   P5OUT|=SS;  //Raise !SS to end transaction.
179 }
180
181 //! Handles a monitor command.
182 void spihandle(unsigned char app,
183                unsigned char verb,
184                unsigned char len){
185   unsigned char i;
186   
187   //Raise !SS to end transaction, just in case we forgot.
188   P5OUT|=SS;  
189   
190   switch(verb){
191     //PEEK and POKE might come later.
192   case READ:
193   case WRITE:
194     P5OUT&=~SS; //Drop !SS to begin transaction.
195     for(i=0;i<len;i++)
196       cmddata[i]=spitrans8(cmddata[i]);
197     P5OUT|=SS;  //Raise !SS to end transaction.
198     txdata(app,verb,len);
199     break;
200
201
202   case SPI_JEDEC://Grab 3-byte JEDEC ID.
203     P5OUT&=~SS; //Drop !SS to begin transaction.
204     spitrans8(0x9f);
205     len=3;
206     for(i=0;i<len;i++)
207       cmddata[i]=spitrans8(cmddata[i]);
208     txdata(app,verb,len);
209     P5OUT|=SS;  //Raise !SS to end transaction.
210     break;
211
212
213   case PEEK://Grab 128 bytes from an SPI Flash ROM
214     spiflash_peek(app,verb,len);
215     break;
216
217
218   case POKE://Poke up bytes from an SPI Flash ROM.
219     spiflash_setstatus(0x02);
220     spiflash_wrten();
221     
222     P5OUT&=~SS; //Drop !SS to begin transaction.
223     spitrans8(0x02); //Poke command.
224     
225     //First three bytes are address, then data.
226     for(i=0;i<len;i++)
227       spitrans8(cmddata[i]);
228     P5OUT|=SS;  //Raise !SS to end transaction.
229     
230     
231     while(spiflash_status()&0x01)//while busy
232       P1OUT^=1;
233     P1OUT&=~1;
234     
235     txdata(app,verb,len);
236     break;
237
238
239   case SPI_ERASE://Erase the SPI Flash ROM.
240     spiflash_wrten();
241     P5OUT&=~SS; //Drop !SS to begin transaction.
242     spitrans8(0xC7);//Chip Erase
243     P5OUT|=SS;  //Raise !SS to end transaction.
244     
245         
246     while(spiflash_status()&0x01)//while busy
247       P1OUT^=1;
248     P1OUT&=~1;
249     
250     txdata(app,verb,0);
251     break;
252
253   case SETUP:
254     spisetup();
255     txdata(app,verb,0);
256     break;
257   }
258   
259 }