Added initial support for board=apimote2
[goodfet] / firmware / lib / tilaunchpad.c
1 //! tilaunchpad clock and I/O definitions
2
3 // serial io stuff moved to msp430_serial.c
4 // serial is common for the different versions of msp430 so it makes sense
5
6 #include "platform.h"
7 #include <signal.h>
8 #include <msp430.h>
9 #include <iomacros.h>
10
11 #define MSP430_CPU_SPEED 6000000UL
12 #include <setjmp.h>
13 #include "msp430_serial.h"
14 extern jmp_buf warmstart;
15 void coldstart();
16 #define USE_NMI_RESET_IRQ
17
18 static void delay_1us()
19 {
20         // 6 Mhz, 6000000 cycles/sec, 6000 cycles/msec, 6 cycles/usec
21         // 6 cycles = 1 usec
22         // asummung loop wil be 3 cycles
23         //asm("  nop");         // 1 cycle
24         asm("  nop");           // 1 cycle
25         asm("  nop");           // 1 cycle
26         asm("  nop");           // 1 cycle
27 }
28
29 void delay_us(unsigned int us)
30 {
31         while (us) {
32                 delay_1us();
33                 us--;
34         }
35 }
36
37 void delay_ms(unsigned int ms)
38 {
39         while (ms) {
40                 ms--;
41                 delay_us(1000);
42         }
43 }
44
45 void delay_sec(unsigned int s)
46 {
47         while (s) {
48                 s--;
49                 delay_ms(1000);
50         }
51 }
52
53 static char led_pin = 0;        // since we are short on pins we might have LED on different pin 
54 static char led_last;
55 // led_pin=0 is disabled
56 // BIT2 and BIT3 is on port 5   SBWDIO SBWTCK
57 // BIT6 and BIT7 os on port 3   BRDRX BRDTX
58 void led_init(char pin)
59 {
60         ddputs("led=");
61         if (pin & BIT2) {
62                 ddputs("P5.2");
63                 led_pin = BIT2;
64                 P5DIR |= led_pin;
65         } else if (pin & BIT3) {
66                 ddputs("P5.3");
67                 led_pin = BIT3;
68                 P5DIR |= BIT3;
69         } else if (pin & BIT6) {
70                 ddputs("P3.6");
71                 led_pin = BIT6;
72                 P3SEL &= ~BIT6; // do not use as uart1
73                 P3DIR |= BIT6;
74         } else if (pin & BIT7) {
75                 ddputs("P3.7");
76                 led_pin = BIT7;
77                 P3SEL &= ~BIT7; // do not use as uart1
78                 P3DIR |= BIT7;
79         } else {
80                 led_pin = 0;
81                 ddputs("disabled");
82         }
83 }
84
85 void led_on()                   // 0 will disable, but it is up to the application to setup new use
86 {
87 //      dddputs("led_on=");
88 //      dddputb(led_pin);
89         if (led_pin & BIT2) {
90                 P5OUT |= BIT2;
91         } else if (led_pin & BIT3) {
92                 P5OUT |= BIT3;
93         } else if (led_pin & BIT6) {
94                 P3OUT |= BIT6;
95         } else if (led_pin & BIT7) {
96                 P3OUT |= BIT7;
97         }
98         led_last = 1;
99 }
100
101 void led_off()
102 {
103         //dddputs("led_off=");
104         //dddputb(led_pin);
105         if (led_pin & BIT2) {
106                 P5OUT &= ~BIT2;
107         } else if (led_pin & BIT3) {
108                 P5OUT &= ~BIT3;
109         } else if (led_pin & BIT6) {
110                 P3OUT &= ~BIT6;
111         } else if (led_pin & BIT7) {
112                 P3OUT &= ~BIT7;
113         }
114         led_last = 0;
115 }
116
117 void led_toggle()
118 {
119         if (led_last) {
120                 led_off();
121         } else {
122                 led_on();
123         }
124 }
125
126 void led_blink(int n)           // long - n shorts
127 {
128         int i;
129         return;
130         led_off();
131         delay_ms(200);
132         led_on();
133         delay_ms(500);
134         for (i = 0; i < n; i++) {
135                 led_off();
136                 delay_ms(100);
137                 led_on();
138                 delay_ms(150);
139         }
140         led_off();
141 }
142
143 void check_usb2serial()
144 {
145         //ddputs("usb2serial ");
146         led_init(SBWTCK);       // we will use TCK for LED
147         P5DIR &= ~SBWDIO;       // input
148
149         led_on();               // we will use TCK for LED
150         if ((P5IN & SBWDIO) == 0) {     // TCK != DIO
151                 led_init(0);    // no led
152                 dputs("low no usb2serial");
153                 return;
154         }
155         led_off();              // we will use TCK for LED
156         if (P5IN & SBWDIO) {    // TCK != DIO
157                 led_init(0);    // no led
158                 dputs("high no usb2serial");
159                 return;
160         }
161         // TCK is jumpered to DIO, lets start working as USB-serial converter.
162         serflush(txfp0);
163         serflush(txfp1);
164         delay_ms(100);
165         dputs("Serial pass through\n");
166         serputs("Serial pass through\n", txfp0);
167         while (1) {
168                 char c;
169                 if (seravailable(rxfp0) > 0) {
170                         c=sergetc(rxfp0);
171                         serputc( c, txfp1);
172                 }
173                 if (seravailable(rxfp1) > 0) {
174                         c=sergetc(rxfp1);
175                         serputc( c, txfp0);
176                 }
177                 // FIXME we should sleep
178         }
179 }
180
181 char rts_change = 1;            // we cannot return 0 in longjmp so we take 1
182
183 interrupt(PORT1_VECTOR) POSRT1_ISR(void)
184 {
185         if (P1IFG & RTS) {
186                 if ((P1IN & DTR) == 0) {
187                         rts_change++;
188                         if (rts_change > 10) {  // just there is no wrap-around
189                                 rts_change = 10;
190                         }
191                 } else {
192                         rts_change = 1;
193                 }
194                 P1IFG &= ~RTS;  // clear irq
195         }
196         if (P1IFG & DTR) {
197                 int i;
198                 P1IFG &= ~DTR;  // clear irq
199                 
200                 for (i=0; (P1IN & DTR) == 0;i++) {      // wait for DTR high
201                         if (i>10000) {
202                                 i=10000;
203                         }
204                 }
205                 if (i>5000) { //avoid spikes
206                         longjmp(warmstart, rts_change);
207                 }
208         }
209 }
210
211 #ifdef USE_NMI_RESET_IRQ
212 // A reset is warmstart, ie. do not reset TUSB3410
213 // to use this wire a reset switch or connect TUSB3410 DTR to RST/NMI
214 // for development it is conveenient ot implement a reset function
215 interrupt(NMI_VECTOR) NMI_ISR(void)
216 {
217         IFG1 &= ~NMIIFG;
218         led_toggle();
219         dputs("NMI(RESET)\n");
220         dflush();
221         longjmp(warmstart, rts_change);
222 }
223 #endif
224 // TI lauchpad has 12 Mhz X-tal on XT2 which also is the base clock for the TUSB34010 
225 // For Launchpad and probably EZ430/FETUIF 
226 // EZ430/FETUIF may need BCSCTL2 = SELM1 | DIVM1 | SELS;
227 void coldstart()
228 {
229         _DINT();
230 #ifdef USE_NMI_RESET_IRQ
231         WDTCTL = WDTPW + WDTHOLD + WDTNMI;      // Stop WDT, deactivate RESET
232         //IE1 |= NMIIE;         // msp430f1612.pdf page 13
233 #else
234         WDTCTL = WDTPW + WDTHOLD;       // Stop WDT
235 #endif
236         //led_init(SBWTCK);
237         led_init(0);
238         led_off();
239 // reset for TUSB3410
240         P4OUT &= ~BIT6;         // reset TUSB3410
241         P4DIR |= BIT6;
242 // 12 Mhz on XT2
243         BCSCTL1 &= ~0x80;       // turn on XT2 oscillator
244         do {                    // delay for X-tal to settle
245                 IFG1 &= ~OFIFG;
246                 delay_us(100);  // wait at least 50 usec
247         } while (IFG1 & OFIFG);
248         //BCSCTL2 = SELM_2 | DIVM_1 | SELS | DIVS_0;    // 6Mhz MCLK=XT2/2 SMCLK=XT2
249         BCSCTL2 = SELM_2 | DIVM_2 | SELS | DIVS_0;      // 3Mhz MCLK=XT2/4 SMCLK=XT2
250 // Disable eeprom P3.1 SDA P3.3 SCL
251         P3OUT &= ~(BIT1 | BIT3);        // pull dcl and sda down
252         P3DIR |= BIT1 | BIT3;
253 // generate 12 Mhz clock for TUSB3410
254         P5SEL |= BIT5;          // P5.5 is SMCLK to TUSG3410
255         P5DIR |= BIT5;          // P5.5 is output
256 // release reset for TUSB3410
257         delay_ms(100);
258         P4OUT &= ~BIT6;         // release reset to TUSB3410
259         P4DIR &= ~BIT6;         // and release port TUSB3410
260 // P1.3 RTS input, P1.4 DTR input can generate IRQ
261         P1DIR &= ~(RTS | DTR);  // input
262         P1SEL &= ~(RTS | DTR);  // no  special funtions
263         P1IES &= ~RTS;  // low to high
264         P1IES |=  DTR;  // high to low
265         P1IFG &= ~(RTS | DTR);  // clear irqs if any, to avoid instant irq
266         P1IE |= RTS | DTR;      // enable IRQ on pin 3,4
267         IE1 |= NMIIE;           // msp430f1612.pdf page 13
268         ser0_init(0, &fiforx0, &fifotx0);
269         //ser1_init(0, &fiforx1, &fifotx1);
270         ser1_init(0, NULL, NULL);
271         _EINT();                // now we can print
272         dputs("->coldstart<-\n");
273         led_blink(4);
274         led_on();               // led comes on after the very basic setup is done
275 }
276
277 void msp430_init()
278 {
279 #ifdef USE_NMI_RESET_IRQ
280         WDTCTL = WDTPW + WDTHOLD + WDTNMI;      // Stop WDT, deactivate RESET
281         //IFG1 &= ~NMIIFG;
282         IE1 |= NMIIE;           // msp430f1612.pdf page 13
283 #else
284         WDTCTL = WDTPW + WDTHOLD;       // Stop WDT
285 #endif
286         serclear(rxfp0);
287         ddputs("msp430_init\n");
288         led_blink(10);
289
290         check_usb2serial();     // configure as USB-serial if jumper RST-TEST
291         led_blink(2);
292         led_on();
293 }
294
295 //! Initialization is correct.
296 void msp430_init_dco_done()
297 {
298 }