Browse code

Add modified LPM3_EXIT_ISR to work around FLL IRQ wake-up problem

Nils Faerber authored on 06/07/2013 21:19:55
Showing 4 changed files
... ...
@@ -58,15 +58,17 @@ __interrupt void UCA1_ISR (void)
58 58
 			if (UCA1STAT & UCRXERR) {
59 59
 				debug_uart_tx("BT UART RXERR: ");
60 60
 				if (UCA1STAT & UCOE)
61
-					debug_uart_tx("overrun\n");
61
+					debug_uart_tx("overrun ");
62 62
 				if (UCA1STAT & UCPE)
63
-					debug_uart_tx("parity err\n");
63
+					debug_uart_tx("parity err ");
64 64
 				if (UCA1STAT & UCFE)
65
-					debug_uart_tx("frm-err\n");
65
+					debug_uart_tx("frm-err ");
66
+				debug_uart_tx("\n");
66 67
 			}
67 68
 			bt_rx_buf[bt_rx_buf_wpos++] = UCA1RXBUF;
68 69
 			bt_rx_buf_wpos %= BT_RX_MAX_SIZE;
69
-			LPM3_EXIT;
70
+			// LPM3_EXIT;
71
+			LPM3_EXIT_ISR();
70 72
 			_event_src |= BT_UART_RCV_EVENT;
71 73
 			break;
72 74
 		case 4: // TXIFG
... ...
@@ -96,9 +98,10 @@ void mw_init_bt_uart(const bt_uart_baud_t baud)
96 98
 	//UCA1CTL0 |= UCRXEIE;
97 99
 
98 100
 	UCA1CTL1 &= ~UCSWRST;
101
+
99 102
 	/* clear interrup flags */
100
-	UCA1IE = UCRXIE;
101 103
 	UCA1IFG = 0;
104
+	UCA1IE = UCRXIE;
102 105
 }
103 106
 
104 107
 #if 0 // Does never finish, presumably trigger does not trigger, unknown :(
... ...
@@ -121,17 +124,23 @@ void mw_bt_uart_tx(const void *buf, const unsigned int len)
121 124
 		nop();
122 125
 }
123 126
 #else
124
-void mw_bt_uart_tx(const void *buf, const unsigned int len)
127
+int mw_bt_uart_tx(const void *buf, const unsigned int len)
125 128
 {
126
-	unsigned int pos;
129
+	unsigned int pos, i;
127 130
 	// char txstr[8];
128 131
 
129 132
 	pos = 0;
130 133
 	// debug_uart_tx("BT tx: ");
131 134
 	while (pos < len) {
132
-		// wait for CTS to go low
133
-		while ((BT_IO_PIN & BT_IO_CTS))
134
-			nop();
135
+		// watch for CTS to be low
136
+		i = 0;
137
+		while ((BT_IO_PIN & BT_IO_CTS) && (i < 1000)) {
138
+			__delay_cycles(16000);
139
+			i++;
140
+			if (i >= 1000)
141
+				return -1;
142
+			// nop();
143
+		}
135 144
 
136 145
 		// do not start a transfer if UART is busy, e.g. rx-ing
137 146
 		while (UCA1STAT & UCBUSY)
... ...
@@ -147,25 +156,31 @@ void mw_bt_uart_tx(const void *buf, const unsigned int len)
147 156
 	}
148 157
 	while (UCA1STAT & UCBUSY)
149 158
 		nop();
159
+
160
+	return len;
150 161
 }
151 162
 #endif
152 163
 
153
-static void load_cc256x_init_script(void)
164
+static int load_cc256x_init_script(void)
154 165
 {
155 166
 	uint32_t pos;
156 167
 	unsigned char *tptr;
168
+	int tlen;
157 169
 
158 170
 	pos = 0;
159 171
 	while (pos < cc256x_init_script_size) {
160 172
 		if (_event_src != 0)
161 173
 			handle_event();
162 174
 		tptr = (unsigned char *)(cc256x_init_script + pos);
163
-		mw_bt_uart_tx(tptr, 4 + tptr[3]);
164
-		pos += 4 + tptr[3];
175
+		tlen = mw_bt_uart_tx(tptr, 4 + tptr[3]);
176
+		if (tlen < 0)
177
+			return -1;
178
+		pos += tlen /*4 + tptr[3]*/;
165 179
 		// each init script part is one HCI command so wait for reply
166 180
 		if (_event_src != 0)
167 181
 			handle_event();
168 182
 	}
183
+	return 0;
169 184
 }
170 185
 
171 186
 void mw_enable_bt(void)
... ...
@@ -174,6 +189,7 @@ void mw_enable_bt(void)
174 189
 
175 190
 	/* make sure it resets */
176 191
 	BT_SHUTDOWN();
192
+	__delay_cycles(16000);
177 193
 
178 194
 	/* enable 32kHz ACLK output to BT module */
179 195
 	P11DIR |= BIT0;
... ...
@@ -182,11 +198,19 @@ void mw_enable_bt(void)
182 198
 	// wait for clock to stabilize
183 199
 	__delay_cycles(16000);
184 200
 
201
+	// disable the IRQ on CTS, later used to get a wakeup IRQ from eHCILL
202
+	// will be enabled when going to sleep
203
+	P1IE &= ~BT_IO_CTS;
204
+	P1IES &= ~BT_IO_CTS;
205
+
185 206
 	BT_IO_PDIR &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
186 207
 	BT_IO_PDIR |= BT_IO_RTS;
208
+
187 209
 	BT_IO_POUT &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
188 210
 	BT_IO_POUT &= ~BT_IO_RTS; // low == ready, high == !ready
189 211
 
212
+	BT_IO_REN |= BT_IO_CTS; // enable pull-down on CTS, POUT-CTS is 0 already
213
+
190 214
 	/* setup UART pins */
191 215
 	BT_UART_PSEL |= BT_UART_TX_PIN | BT_UART_RX_PIN;
192 216
 	// P5OUT |= BT_UART_TX_PIN | BT_UART_RX_PIN;
... ...
@@ -207,28 +231,45 @@ void mw_enable_bt(void)
207 231
 	}
208 232
 	if (i>=1000) {
209 233
 		debug_uart_tx("Timeout waiting for CC256x to lower CTS\n");
234
+		mw_bt_enabled = 0;
210 235
 	} else {
211 236
 		debug_uart_tx("CC256x CTS low - uploading init\n");
212
-		for (i=0; i<100; i++) {
213
-			__delay_cycles(16000); // give it some more before anyone sends data
237
+
238
+		// the init script consists of HCI cmds so HCI must be setup before
239
+		bt_hci_init();
240
+
241
+		// give it some more time before anyone sends data
242
+ 		for (i=0; i<10; i++) {
243
+			__delay_cycles(16000);
244
+		}
245
+		if (load_cc256x_init_script() < 0) {
246
+			debug_uart_tx("init upload failed!\n");
247
+			return;
214 248
 		}
215
-		load_cc256x_init_script();
249
+
250
+		__delay_cycles(32000);
251
+
216 252
 		debug_uart_tx("init uploaded\n");
217
-	}
218 253
 
219
-	P1IE &= ~BT_IO_CTS;
220
-	P1IES &= ~BT_IO_CTS;
254
+		init_l2cap();
221 255
 
222
-	bt_hci_init();
223
-	init_l2cap();
256
+		if (_event_src != 0)
257
+			handle_event();
224 258
 
225
-	mw_bt_enabled = 1;
259
+		mw_bt_enabled = 1;
260
+	}
226 261
 }
227 262
 
228 263
 void mw_disable_bt(void)
229 264
 {
230 265
 	mw_bt_enabled = 0;
231 266
 
267
+	// disable the IRQ on CTS
268
+	P1IE &= ~BT_IO_CTS;
269
+	P1IES &= ~BT_IO_CTS;
270
+	// BT_IO_REN &= ~BT_IO_CTS; // disable pull-down on CTS
271
+	P1IFG &= ~BT_IO_CTS;
272
+
232 273
 	/* disable UART RX interrupt */
233 274
 	UCA1IE &= ~UCRXIE;
234 275
 
... ...
@@ -12,17 +12,18 @@
12 12
 #define BT_IO_POUT		P1OUT
13 13
 #define BT_IO_PIN		P1IN
14 14
 #define BT_IO_PDIR		P1DIR
15
+#define BT_IO_REN		P1REN
15 16
 
16 17
 #define BT_IO_PIN1		BIT5
17 18
 #define BT_IO_PIN2		BIT6
18
-#define BT_IO_CLKREQ		BIT4
19
+#define BT_IO_CLKREQ	BIT4
19 20
 
20 21
 #define BT_SHUTDOWN()		{ BT_RST_POUT &= ~BT_RST_PIN; }
21
-#define BT_ENABLE()		{ BT_RST_POUT |= BT_RST_PIN; }
22
+#define BT_ENABLE()			{ BT_RST_POUT |= BT_RST_PIN; }
22 23
 
23 24
 #define BT_UART_PSEL		P5SEL
24 25
 #define BT_UART_PDIR		P5DIR
25
-#define BT_UART_REN		P5REN
26
+#define BT_UART_REN			P5REN
26 27
 #define BT_UART_POUT		P5OUT
27 28
 #define BT_UART_TX_PIN		BIT6
28 29
 #define BT_UART_RX_PIN		BIT7
... ...
@@ -56,7 +57,7 @@ typedef enum {
56 57
 
57 58
 void mw_init_bt_uart(const bt_uart_baud_t baud);
58 59
 
59
-void mw_bt_uart_tx(const void *buf, const unsigned int len);
60
+int mw_bt_uart_tx(const void *buf, const unsigned int len);
60 61
 // extern char BT_UART_RX_CHAR;
61 62
 
62 63
 int mw_bt_get_rxbuf_len(void);
... ...
@@ -20,24 +20,26 @@
20 20
 #include "oswald_main.h"
21 21
 #include "oswald_hal.h"
22 22
 
23
+#include "bluetooth_init_cc256x.h"
23 24
 
24 25
 uint16_t _event_src = 0;
25 26
 
26 27
 #define HARDWARE_REVISION_ADDRESS (0x1a07)
27 28
 
28
-unsigned char GetMsp430HardwareRevision(void)
29
+uint8_t GetMsp430HardwareRevision(void)
29 30
 {
30
-	unsigned char *pDeviceType = (unsigned char *)(unsigned char *)HARDWARE_REVISION_ADDRESS;
31
+	uint8_t *pDeviceType = (uint8_t *)(uint8_t *)HARDWARE_REVISION_ADDRESS;
31 32
   
32 33
 	return pDeviceType[0]+'1';                         
33 34
 }
34 35
 
35 36
 uint8_t DetermineErrata(void)
36 37
 {
37
-	unsigned char Revision = GetMsp430HardwareRevision();
38
+	uint8_t Revision = GetMsp430HardwareRevision();
38 39
   
39 40
 	switch (Revision) {
40 41
 		case 'F':
42
+		case 'G':
41 43
 		case 'H':
42 44
 			return 0;
43 45
 			break;
... ...
@@ -67,6 +69,31 @@ static void set16mhz(void)
67 69
 	}
68 70
 }
69 71
 
72
+static unsigned char PMM15Check(void)
73
+{
74
+  // First check if SVSL/SVML is configured for fast wake-up
75
+  if ((!(SVSMLCTL & SVSLE)) || ((SVSMLCTL & SVSLE) && (SVSMLCTL & SVSLFP)) ||
76
+      (!(SVSMLCTL & SVMLE)) || ((SVSMLCTL & SVMLE) && (SVSMLCTL & SVMLFP)))
77
+  { 
78
+    // Next Check SVSH/SVMH settings to see if settings are affected by PMM15
79
+    if ((SVSMHCTL & SVSHE) && (!(SVSMHCTL & SVSHFP)))
80
+    {
81
+      if ( (!(SVSMHCTL & SVSHMD)) ||
82
+           ((SVSMHCTL & SVSHMD) && (SVSMHCTL & SVSMHACE)) )
83
+        return 1; // SVSH affected configurations
84
+    }
85
+
86
+    if ((SVSMHCTL & SVMHE) && (!(SVSMHCTL & SVMHFP)) && (SVSMHCTL & SVSMHACE))
87
+      return 1; // SVMH affected configurations
88
+  }
89
+
90
+  return 0; // SVS/M settings not affected by PMM15
91
+}
92
+
93
+#define configCPU_CLOCK_HZ ((unsigned long) 16777216) /* 512*32768 */
94
+#define configTICK_RATE_HZ ((unsigned int)1024)
95
+#define ACLK_MULTIPLIER    ((unsigned int)512)
96
+
70 97
 static void setup_clocks(void)
71 98
 {
72 99
 	unsigned long i;
... ...
@@ -75,6 +102,8 @@ static void setup_clocks(void)
75 102
 
76 103
 	/* use external oscillator */
77 104
 	P7SEL |= BIT0 + BIT1;
105
+
106
+#if 1
78 107
 	if ((UCSCTL6 & XT1DRIVE_3) != XT1DRIVE_3) {
79 108
 		UCSCTL6_L |= XT1DRIVE1_L + XT1DRIVE0_L;
80 109
 	}
... ...
@@ -88,7 +117,21 @@ static void setup_clocks(void)
88 117
 	set16mhz();
89 118
 
90 119
 	UCSCTL8 |= SMCLKREQEN;
120
+#else
121
+	// Startup LFXT1 32 kHz crystal
122
+	while (LFXT_Start_Timeout(XT1DRIVE_0, 50000) == UCS_STATUS_ERROR)
123
+		nop();
124
+
125
+	// select the sources for the FLL reference and ACLK
126
+	SELECT_ACLK(SELA__XT1CLK);
127
+	SELECT_FLLREF(SELREF__XT1CLK);
91 128
 
129
+	// 512 * 32768 = 16777216 / 1024
130
+	Init_FLL_Settle(configCPU_CLOCK_HZ/configTICK_RATE_HZ, ACLK_MULTIPLIER);
131
+  
132
+	// Disable FLL loop control
133
+//	__bis_SR_register(SCG0);
134
+#endif
92 135
 	// setup for quick wake up from interrupt and
93 136
 	// minimal power consumption in sleep mode
94 137
 	DISABLE_SVSL();				// SVS Low side is turned off
... ...
@@ -105,12 +148,15 @@ static void setup_clocks(void)
105 148
 
106 149
 	SVSH_ENABLED_IN_LPM_FULL_PERF();	// SVS high side Full perf mode,
107 150
 						// stays on in LPM3,enhanced protect
151
+	SVSL_ENABLED_IN_LPM_FAST_WAKE();
108 152
 
109 153
 	// Wait until high side, low side settled
110 154
 	while ((PMMIFG & SVSMLDLYIFG) == 0 && (PMMIFG & SVSMHDLYIFG) == 0)
111 155
 		nop();
112 156
 	CLEAR_PMM_IFGS();
113 157
 
158
+	while (PMM15Check());
159
+
114 160
 	// Errata PMM17
115 161
 	if (DetermineErrata()) {
116 162
 		*(unsigned int*)(0x0110) = 0x9602;
... ...
@@ -176,9 +222,12 @@ static void setup_pins(void)
176 222
 	APPLE_POWER_DISABLE();
177 223
 
178 224
 	CONFIG_BT_PINS();
179
-	BT_CLK_REQ_CONFIG_AS_OUTPUT_LOW();
180
-	BT_IO1_CONFIG_AS_OUTPUT_LOW();
181
-	BT_IO2_CONFIG_AS_OUTPUT_LOW();
225
+//	BT_CLK_REQ_CONFIG_AS_OUTPUT_LOW();
226
+//	BT_IO1_CONFIG_AS_OUTPUT_LOW();
227
+//	BT_IO2_CONFIG_AS_OUTPUT_LOW();
228
+	BT_CLK_REQ_CONFIG_AS_INPUT();
229
+	BT_IO1_CONFIG_AS_INPUT();
230
+	BT_IO2_CONFIG_AS_INPUT();
182 231
 	mw_disable_bt();
183 232
 
184 233
 	LIGHT_SENSE_INIT();
... ...
@@ -198,6 +247,20 @@ static void setup_pins(void)
198 247
 #ifndef MW_DEVBOARD_V2 // but only on real watch
199 248
 	SFRRPCR &= ~SYSRSTRE;
200 249
 	SFRRPCR |= SYSNMI;
250
+#endif
251
+	/* allow debug UART */
252
+/*
253
+	P10SEL &= ~(BIT6 | BIT7);
254
+	P10DIR |= BIT6 | BIT7;
255
+	P10OUT &= ~(BIT6 | BIT7);
256
+*/
257
+#ifndef MW_DEVBOARD_V2
258
+	ENABLE_MUX_OUTPUT_CONTROL();
259
+#ifdef MW_DEBUG_UART
260
+	MUX_OUTPUT_SELECTS_SERIAL();
261
+#else
262
+	MUX_OUTPUT_OFF();
263
+#endif
201 264
 #endif
202 265
 }
203 266
 
... ...
@@ -250,8 +313,8 @@ __interrupt void RTC_ISR (void)
250 313
 		case RTCIV_RT1PSIFG:
251 314
 			RTCPS1CTL &= ~RT1PSIFG;
252 315
 			_event_src |= RTC_1HZ_EVENT;
253
-			LPM3_EXIT;
254
-			nop();
316
+			// LPM3_EXIT;
317
+			LPM3_EXIT_ISR();
255 318
 #if defined MW_DEVBOARD_V2
256 319
 			LED7_TOGGLE();
257 320
 #endif
... ...
@@ -301,7 +364,7 @@ void setup_rtc(void)
301 364
 	nop();
302 365
 }
303 366
 
304
-#if defined MW_DEVBOARD_V2
367
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
305 368
 static void dbg_out_rtc(void)
306 369
 {
307 370
 	char clk_str[16];
... ...
@@ -377,7 +440,7 @@ static void handle_bt_uart_rx_event(void)
377 440
 	*rp = (*rp + len) % BT_RX_MAX_SIZE;
378 441
 }
379 442
 
380
-#if defined MW_DEVBOARD_V2
443
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
381 444
 static void handle_uart_rx_event(void)
382 445
 {
383 446
 	char c;
... ...
@@ -462,6 +525,20 @@ static void handle_uart_rx_event(void)
462 525
 			debug_uart_tx("HCI reset\n");
463 526
 			bt_hci_cmd(HCI_HC_BB_OGF, HCI_RESET_OCF, 0, NULL);
464 527
 			bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_COD_OCF, 3, dclass);
528
+		} else if (c == 'i') {
529
+			debug_uart_tx("Information:\n");
530
+			debug_uart_tx("Oswald ");
531
+			debug_uart_tx(MW_MAIN_VERSION);
532
+			debug_uart_tx("\n");
533
+			debug_uart_tx("Build #");
534
+			debug_uart_tx(BUILDNO);
535
+			debug_uart_tx("\n");
536
+			debug_uart_tx("BT V ");
537
+			debug_uart_tx(cc256x_version);
538
+			debug_uart_tx("\n");
539
+			debug_uart_tx("MCU Rev ");
540
+			debug_uart_tx_char(GetMsp430HardwareRevision());
541
+			debug_uart_tx("\n");
465 542
 		} else if (c == 'S') {
466 543
 			debug_uart_tx("Scan enable\n");
467 544
 			tstr[0] = HCI_BB_SCAN_INQUIRY | HCI_BB_SCAN_PAGE;
... ...
@@ -516,12 +593,13 @@ __interrupt void TIMER0_A0_ISR (void)
516 593
 	LED6_TOGGLE();
517 594
 #endif
518 595
 	_event_src |= TIMER_500MS_EVENT | TIMER_100MS_EVENT;
519
-	LPM3_EXIT;
596
+	// LPM3_EXIT;
597
+	LPM3_EXIT_ISR();
520 598
 }
521 599
 
522 600
 uint8_t handle_event(void)
523 601
 {
524
-#if defined MW_DEVBOARD_V2
602
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
525 603
 	char tstr[64];
526 604
 #endif
527 605
 	if (_event_src == 0)
... ...
@@ -535,7 +613,7 @@ uint8_t handle_event(void)
535 613
 			_event_src &= ~RTC_1HZ_EVENT;
536 614
 			check_pwr_state();
537 615
 			oswald_one_second_tick();
538
-#if defined MW_DEVBOARD_V2
616
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
539 617
 			dbg_out_rtc();
540 618
 #endif
541 619
 		} else if (_event_src & BT_UART_RCV_EVENT) {
... ...
@@ -546,7 +624,7 @@ uint8_t handle_event(void)
546 624
 			bt_hci_ehcill_wake();
547 625
 		} else if (_event_src & DBG_UART_RCV_EVENT) {
548 626
 			_event_src &= ~DBG_UART_RCV_EVENT;
549
-#if defined MW_DEVBOARD_V2
627
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
550 628
 			handle_uart_rx_event();
551 629
 #endif
552 630
 		} else if (_event_src & BUTTON_EVENT) {
... ...
@@ -562,7 +640,7 @@ uint8_t handle_event(void)
562 640
 			_event_src &= ~ACCEL_EVENT;
563 641
 			mw_acc_handle_irq();
564 642
 		} else {
565
-#if defined MW_DEVBOARD_V2
643
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
566 644
 			snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src);
567 645
 			debug_uart_tx(tstr);
568 646
 #endif
... ...
@@ -574,7 +652,8 @@ uint8_t handle_event(void)
574 652
 #pragma vector=BUTTON_PORT_VECTOR
575 653
 __interrupt void BUTTON_ISR (void)
576 654
 {
577
-	LPM3_EXIT;
655
+	// LPM3_EXIT;
656
+	LPM3_EXIT_ISR();
578 657
 	BUTTON_PORT_IFG &= ~ALL_BUTTONS;
579 658
 	// BUTTON_PORT_IE  &= ~INT_EDGE_SEL_BUTTONS;
580 659
 	_event_src |= BUTTON_EVENT;
... ...
@@ -585,14 +664,16 @@ __interrupt void BUTTON_ISR (void)
585 664
 __interrupt void PORT1_GPIO_ISR (void)
586 665
 {
587 666
 	if (P1IFG & BT_IO_CTS) {
588
-		LPM3_EXIT;
667
+		//LPM3_EXIT;
668
+		LPM3_EXIT_ISR();
589 669
 		P1IE &= ~BT_IO_CTS;
590 670
 		P1IFG &= ~BT_IO_CTS;
591 671
 		debug_uart_tx("BT CTS irq\n");
592 672
 		_event_src |= BT_UART_WAKEUP_EVENT;
593 673
 		// bt_hci_ehcill_wake();
594 674
 	} else if (P1IFG & ACCELEROMETER_INT_PIN) {
595
-		LPM3_EXIT;
675
+		//LPM3_EXIT;
676
+		LPM3_EXIT_ISR();
596 677
 		P1IFG &= ~ACCELEROMETER_INT_PIN;
597 678
 		// debug_uart_tx("ACC irq\n");
598 679
 		_event_src |= ACCEL_EVENT;
... ...
@@ -619,7 +700,7 @@ int main(void)
619 700
 	/* enable interrupts, we will need them! */
620 701
 	__enable_interrupt();
621 702
 
622
-#if defined MW_DEVBOARD_V2
703
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
623 704
 	init_debug_uart();
624 705
 	debug_uart_tx("\nOswald on MetaWatch\n");
625 706
 #endif
... ...
@@ -12,6 +12,7 @@
12 12
 #endif
13 13
 #include "hal_io_macros.h"
14 14
 
15
+#define LPM3_EXIT_ISR() { _BIC_SR_IRQ(SCG1+OSCOFF+CPUOFF); nop(); }
15 16
 
16 17
 #define WATCHDOG_EVENT		1 << 0
17 18
 #define RTC_1HZ_EVENT		1 << 1