Support for debugging strings, closer to a clean MSP430X2 implementation.
[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)
19 //delay(x)
20
21
22 //! Set up the pins for SPI mode.
23 void spisetup(){
24   P5OUT|=SS;
25   P5DIR|=MOSI+SCK+SS;
26   P5DIR&=~MISO;
27   
28   //Begin a new transaction.
29   P5OUT&=~SS; 
30   P5OUT|=SS;
31 }
32
33
34 //! Read and write an SPI byte.
35 unsigned char spitrans8(unsigned char byte){
36   unsigned int bit;
37   //This function came from the SPI Wikipedia article.
38   //Minor alterations.
39   
40   for (bit = 0; bit < 8; bit++) {
41     /* write MOSI on trailing edge of previous clock */
42     if (byte & 0x80)
43       SETMOSI;
44     else
45       CLRMOSI;
46     byte <<= 1;
47  
48     /* half a clock cycle before leading/rising edge */
49     SPIDELAY(SPISPEED/2);
50     SETCLK;
51  
52     /* half a clock cycle before trailing/falling edge */
53     SPIDELAY(SPISPEED/2);
54  
55     /* read MISO on trailing edge */
56     byte |= READMISO;
57     CLRCLK;
58   }
59   
60   return byte;
61 }
62
63
64 //! Enable SPI writing
65 void spiflash_wrten(){
66   SETSS;
67   P5OUT&=~SS; //Drop !SS to begin transaction.
68   spitrans8(0x04);//Write Disable
69   P5OUT|=SS;  //Raise !SS to end transaction.
70   P5OUT&=~SS; //Drop !SS to begin transaction.
71   spitrans8(0x06);//Write Enable
72   P5OUT|=SS;  //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   P5OUT|=SS;  //Raise !SS to end transaction.
80   P5OUT&=~SS; //Drop !SS to begin transaction.
81   spitrans8(0x05);//GET STATUS
82   c=spitrans8(0xFF);
83   P5OUT|=SS;  //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
120 //! Read a block to a buffer.
121 void spiflash_pokeblock(unsigned long adr,
122                         unsigned char *buf,
123                         unsigned int len){
124   unsigned char i;
125   
126   SETSS;
127   
128   spiflash_setstatus(0x02);
129   spiflash_wrten();
130   
131   CLRSS; //Drop !SS to begin transaction.
132   spitrans8(0x02); //Poke command.
133   
134   //Send address
135   spitrans8((adr&0xFF0000)>>16);
136   spitrans8((adr&0xFF00)>>8);
137   spitrans8(adr&0xFF);
138
139   for(i=0;i<len;i++)
140     spitrans8(buf[i]);
141   SETSS;  //Raise !SS to end transaction.
142   
143   //while(spiflash_status()&0x01);
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   spisetup();
190   
191   switch(verb){
192     //PEEK and POKE might come later.
193   case READ:
194   case WRITE:
195     P5OUT&=~SS; //Drop !SS to begin transaction.
196     for(i=0;i<len;i++)
197       cmddata[i]=spitrans8(cmddata[i]);
198     P5OUT|=SS;  //Raise !SS to end transaction.
199     txdata(app,verb,len);
200     break;
201
202
203   case SPI_JEDEC://Grab 3-byte JEDEC ID.
204     P5OUT&=~SS; //Drop !SS to begin transaction.
205     spitrans8(0x9f);
206     len=3;
207     for(i=0;i<len;i++)
208       cmddata[i]=spitrans8(cmddata[i]);
209     txdata(app,verb,len);
210     P5OUT|=SS;  //Raise !SS to end transaction.
211     break;
212
213
214   case PEEK://Grab 128 bytes from an SPI Flash ROM
215     spiflash_peek(app,verb,len);
216     break;
217
218
219   case POKE://Poke up bytes from an SPI Flash ROM.
220     spiflash_setstatus(0x02);
221     spiflash_wrten();
222     
223     P5OUT&=~SS; //Drop !SS to begin transaction.
224     spitrans8(0x02); //Poke command.
225     
226     //First three bytes are address, then data.
227     for(i=0;i<len;i++)
228       spitrans8(cmddata[i]);
229     P5OUT|=SS;  //Raise !SS to end transaction.
230     
231     
232     while(spiflash_status()&0x01)//while busy
233       P1OUT^=1;
234     P1OUT&=~1;
235     
236     txdata(app,verb,len);
237     break;
238
239
240   case SPI_ERASE://Erase the SPI Flash ROM.
241     spiflash_wrten();
242     P5OUT&=~SS; //Drop !SS to begin transaction.
243     spitrans8(0xC7);//Chip Erase
244     P5OUT|=SS;  //Raise !SS to end transaction.
245     
246         
247     while(spiflash_status()&0x01)//while busy
248       P1OUT^=1;
249     P1OUT&=~1;
250     
251     txdata(app,verb,0);
252     break;
253
254   case SETUP:
255     spisetup();
256     txdata(app,verb,0);
257     break;
258   }
259   
260 }