Whitespace stuff.
[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         
61         //DAC should be at full voltage if it exists.
62 #ifdef DAC12IR
63         //glitchvoltages(0xfff,0xfff);
64         ADC12CTL0 = REF2_5V + REFON; // Internal 2.5V ref on
65         //for(i=0;i!=0xFFFF;i++) asm("nop"); //DO NOT UNCOMMENT, break GCC4.
66         DAC12_0CTL = DAC12IR + DAC12AMP_5 + DAC12ENC; // Int ref gain 1
67         DAC12_0DAT = 0xFFF; //Max voltage 0xfff
68         DAC12_1CTL = DAC12IR + DAC12AMP_5 + DAC12ENC; // Int ref gain 1
69         DAC12_1DAT = 0x000; //Min voltage 0x000
70 #endif
71
72         /** FIXME
73           
74           This part is really ugly.  GSEL (P5.7) must be high to select
75           normal voltage, but a lot of applications like to swing it low
76           to be a nuissance.  To get around this, we assume that anyone
77           with a glitching FET will also have a DAC, then we set that DAC
78           to a high voltage.
79           
80           At some point, each target must be sanitized to show that it
81           doesn't clear P5OUT or P5DIR.
82         */
83         P5DIR|=BIT7; P5OUT=BIT7; //Normal Supply
84         //P5DIR&=~BIT7; //Glitch Supply
85
86         //Enable Interrupts.
87         //eint();
88         
89         
90         
91         #ifdef INITPLATFORM
92         INITPLATFORM;
93         #endif
94 }
95
96
97 //! Handle a command.
98 void handle(uint8_t const app,
99             uint8_t const verb,
100             uint32_t const len){
101   int i;
102
103   //debugstr("GoodFET");
104   PLEDOUT&=~PLEDPIN;
105
106   // find the app and call the handle fn
107   for(i = 0; i < num_apps; i++){
108     if(apps[i]->app == app){
109       // call the app's handle fn
110       (*(apps[i]->handle))(app, verb, len);
111       
112       // exit early
113       return;
114     }
115   }
116
117   // if we get here, then the desired app is not copiled in 
118   // this firmware
119   debugstr("App missing.");
120   debughex(app);
121   txdata(app, NOK, 0);
122 }
123
124
125 //! Main loop.
126 int main(void){
127   volatile unsigned int i;
128   unsigned char app, verb;
129   unsigned long len;
130   // MSP reboot count for reset input & reboot function located at 0xFFFE
131   volatile unsigned int reset_count = 0;
132   void (*reboot_function)(void) = (void *) 0xFFFE;
133   
134   init();
135   
136   txstring(MONITOR,OK,"http://goodfet.sf.net/");
137   
138   //Command loop.  There's no end!
139   while(1){
140     //Magic 3
141     app = serial_rx();
142     
143     // If the app is the reset byte (0x80) increment and loop
144     if (app == RESET){
145       reset_count++;
146       
147       if (reset_count > 4){
148         // We could trigger the WDT with either:
149         // WDTCTL = 0;
150         // or
151         // WDTCTL = WDTPW + WDTCNTCL + WDTSSEL + 0x00;
152         // but instead we'll jump to our reboot function pointer
153         (*reboot_function)();
154       }
155       
156       continue;
157     }else{
158       reset_count = 0;
159     }
160
161     verb = serial_rx();
162     //len=serial_rx();
163     len = rxword();
164     
165     //Read data, looking for buffer overflow.y
166     if(len <= CMDDATALEN){
167       for(i = 0; i < len; i++){
168         cmddata[i] = serial_rx();
169       }
170
171       handle(app,verb,len);
172     }else{
173       //Listen to the blaberring.
174       for(i = 0; i < len; i++)
175         serial_rx();
176       
177       //Reply with an error.
178       debugstr("Buffer length exceeded.");
179       txdata(MONITOR,NOK,0);
180     }
181   }
182 }
183