SPIFlash size warning.
[goodfet] / firmware / goodfet.c
1 /*! \file goodfet.c
2   \author Travis Goodspeed
3   \brief Main module.
4   
5   This is the main module of the GoodFET, which calls the initialization
6   routines and delegates commands to the various applications.
7 */
8
9
10 #include "platform.h"
11 #include "command.h"
12 #include "apps.h"
13 #include "glitch.h"
14
15 #define RESET 0x80      // not a real app -- causes firmware to reset
16 #define DEBUGAPP 0xFF
17
18 //! Initialize registers and all that jazz.
19 void init()
20 {
21 #ifdef DAC12IR
22         int i;
23 #endif
24
25         WDTCTL = WDTPW + WDTHOLD;                                       // Stop watchdog timer
26
27         //LED out and on.
28         PLEDDIR |= PLEDPIN;
29         PLEDOUT &= ~PLEDPIN;
30
31
32         /* P5.0 out and low; this is chosen for the PIC app (in which P5.0
33          is !MCLR) to ensure that an attached PIC chip, if present, is
34          immediately driven to reset state. A brief explanation of why this
35          is important follows.
36
37         At least dsPIC33F and PIC24H --and very likely other 16-bit PIC
38         families-- draw a large amount of current when running, especially
39         when using a fast clock: from 60 mA up to approx. 90 mA.  If the
40         PIC target begins to run before the client can request a new ICSP
41         session, which requires much less current (e.g., less than 2 mA),
42         then the MSP430 chip on the GoodFET will fail to start and the FTDI
43         may have trouble communicating with the client. The latter likely
44         relates to the FTDI on-chip 3V3 regulator being specified up to
45         only 50 mA. */
46
47
48         //P5REN &= ~BIT0; //DO NOT UNCOMMENT.  Breaks GF1x support.
49
50         //This will have to be cut soon.        Use pulling resistors instead.
51         /*
52         P5DIR |= BIT0;
53         P5OUT &= ~BIT0;
54         */
55
56         //Setup clocks, unique to each '430.
57         msp430_init_dco();
58         msp430_init_uart();
59
60         //DAC should be at full voltage if it exists.
61 #ifdef DAC12IR
62         //glitchvoltages(0xfff,0xfff);
63         ADC12CTL0 = REF2_5V + REFON;                                    // Internal 2.5V ref on
64         for(i=0;i!=0xFFFF;i++) asm("nop");
65         DAC12_0CTL = DAC12IR + DAC12AMP_5 + DAC12ENC; // Int ref gain 1
66         DAC12_0DAT = 0xFFF; //Max voltage 0xfff
67         DAC12_1CTL = DAC12IR + DAC12AMP_5 + DAC12ENC; // Int ref gain 1
68         DAC12_1DAT = 0x000; //Min voltage 0x000
69 #endif
70
71         /** FIXME
72           
73           This part is really ugly.  GSEL (P5.7) must be high to select
74           normal voltage, but a lot of applications light to swing it low
75           to be a nuissance.  To get around this, we assume that anyone
76           with a glitching FET will also have a DAC, then we set that DAC
77           to a high voltage.
78           
79           At some point, each target must be sanitized to show that it
80           doesn't clear P5OUT or P5DIR.
81         */
82         P5DIR|=BIT7; P5OUT=BIT7; //Normal Supply
83         //P5DIR&=~BIT7; //Glitch Supply
84
85         //Enable Interrupts.
86         //eint();
87         
88         #ifdef INITPLATFORM
89         INITPLATFORM;
90         #endif
91 }
92
93
94 //! Handle a command.
95 void handle(uint8_t const app,
96             uint8_t const verb,
97             uint32_t const len){
98   int i;
99
100   //debugstr("GoodFET");
101   PLEDOUT&=~PLEDPIN;
102
103   // find the app and call the handle fn
104   for(i = 0; i < num_apps; i++){
105     if(apps[i]->app == app){
106       // call the app's handle fn
107       (*(apps[i]->handle))(app, verb, len);
108       
109       // exit early
110       return;
111     }
112   }
113
114   // if we get here, then the desired app is not copiled in 
115   // this firmware
116   debugstr("App missing.");
117   debughex(app);
118   txdata(app, NOK, 0);
119 }
120
121
122 //! Main loop.
123 int main(void)
124 {
125         volatile unsigned int i;
126         unsigned char app, verb;
127         unsigned long len;
128         // MSP reboot count for reset input & reboot function located at 0xFFFE
129         volatile unsigned int reset_count = 0;
130         void (*reboot_function)(void) = (void *) 0xFFFE;
131
132         init();
133   
134         txstring(MONITOR,OK,"http://goodfet.sf.net/");
135   
136         //Command loop.  There's no end!
137         while(1)
138         {
139                 //Magic 3
140                 app = serial_rx();
141
142                 // If the app is the reset byte (0x80) increment and loop
143                 if (app == RESET)
144                 {
145                         reset_count++;
146
147                         if (reset_count > 4) 
148                         {
149                                 // We could trigger the WDT with either:
150                                 // WDTCTL = 0;
151                                 // or
152                                 // WDTCTL = WDTPW + WDTCNTCL + WDTSSEL + 0x00;
153                                 // but instead we'll jump to our reboot function pointer
154                                 (*reboot_function)();
155                         }
156
157                         continue;
158                 } 
159                 else 
160                 {
161                         reset_count = 0;
162                 }
163
164                 verb = serial_rx();
165                 //len=serial_rx();
166                 len = rxword();
167
168                 //Read data, looking for buffer overflow.y
169                 if(len <= CMDDATALEN)
170                 {
171                         for(i = 0; i < len; i++)
172                         {
173                                 cmddata[i] = serial_rx();
174                         }
175
176                         handle(app,verb,len);
177                 }
178                 else
179                 {
180                         //Listen to the blaberring.
181                         for(i = 0; i < len; i++)
182                                 serial_rx();
183
184                         //Reply with an error.
185                         debugstr("Buffer length exceeded.");
186                         txdata(MONITOR,NOK,0);
187                 }
188         }
189 }
190