Hal.c
9.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
/*
* ============ Hardware Abstraction Layer for MSP-EXP430G2 LaunchPad ============
*/
#include "Hal.h"
#include "Em_Message.h"
#include <msp430.h>
/* -------- INTERNAL FEATURES -------- */
#define LED_CONFIG() (P1DIR |= BIT6)
#define LED_ON() (P1OUT |= BIT6)
#define LED_OFF() (P1OUT &= ~BIT6)
#define LED_READ() (P1OUT & BIT6)
#define LED_TOGGLE() (P1OUT ^= BIT6)
#define CONNECTED_LED_CONFIG() (P1DIR |= BIT0)
#define CONNECTED_LED_ON() (P1OUT |= BIT0)
#define CONNECTED_LED_OFF() (P1OUT &= ~BIT0)
#define BUTTON_CONFIG() (P1DIR &= ~BIT3, P1REN |= BIT3, P1OUT |= BIT3, P1IES |= BIT3);
#define BUTTON_ENABLE() (P1IFG &= ~BIT3, P1IE |= BIT3)
#define BUTTON_PRESSED() (!(P1IN & BIT3))
#define BUTTON_DEBOUNCE_MSECS 100
#define DEBUG1_CONFIG() (P2DIR |= BIT3)
#define DEBUG1_ON() (P2OUT |= BIT3)
#define DEBUG1_OFF() (P2OUT &= ~BIT3)
#define DEBUG2_CONFIG() (P2DIR |= BIT4)
#define DEBUG2_ON() (P2OUT |= BIT4)
#define DEBUG2_OFF() (P2OUT &= ~BIT4)
#define EAP_RX_BUF UCA0RXBUF
#define EAP_TX_BUF UCA0TXBUF
#define EAP_RX_VECTOR USCIAB0RX_VECTOR
#define EAP_TX_VECTOR USCIAB0TX_VECTOR
#define EAP_TX_ACK_VECTOR PORT2_VECTOR
#define EAP_RX_ENABLE() (P1SEL |= BIT1, P1SEL2 |= BIT1)
#define EAP_RX_DISABLE() (P1SEL &= ~BIT1, P1SEL2 &= ~BIT1)
#define EAP_TX_ENABLE() (P1SEL |= BIT2, P1SEL2 |= BIT2)
#define EAP_TX_DISABLE() (P1SEL &= ~BIT2, P1SEL2 &= ~BIT2)
#define EAP_RX_ACK_CONFIG() (P2DIR |= BIT0)
#define EAP_RX_ACK_SET() (P2OUT |= BIT0)
#define EAP_RX_ACK_CLR() (P2OUT &= ~BIT0)
#define EAP_TX_ACK_CONFIG() (P2DIR &= ~BIT1, P2IES |= BIT1, P2IFG &= ~BIT1, P2IE |= BIT1)
#define EAP_TX_ACK_TST() (P2IFG & BIT1)
#define EAP_TX_ACK_CLR() (P2IFG &= ~BIT1)
#define EAP_RX_INT_CLR() (IFG2 &= ~UCA0RXIFG)
#define EAP_RX_INT_ENABLE() (IE2 |= UCA0RXIE)
#define EAP_TX_INT_CLR() (IFG2 &= ~UCA0TXIFG)
#define EAP_TX_INT_DISABLE() (IE2 &= ~UCA0TXIE)
#define EAP_TX_INT_ENABLE() (IE2 |= UCA0TXIE)
#define MCLK_TICKS_PER_MS 1000L
#define ACLK_TICKS_PER_SECOND 12000L
#define UART_WATCHDOG_PERIOD (ACLK_TICKS_PER_SECOND * 250) / 1000
#define UART_WATCH_DISABLE() (TA1CCTL1 = 0) // Turn off CCR1 Interrupt
#define UART_WATCH_ENABLE() (TA1CCR1 = TA1R + UART_WATCHDOG_PERIOD, TA1CCTL1 = CCIE) // Set CCR1, and Enable CCR1 Interrupt
#ifdef __GNUC__
#define DINT() (__disable_interrupt())
#define EINT() (__enable_interrupt())
#define INTERRUPT
#define SLEEP() (_BIS_SR(LPM3_bits + GIE))
#define WAKEUP() (_BIC_SR_IRQ(LPM3_bits))
#endif
#ifdef __TI_COMPILER_VERSION__
#define DINT() (_disable_interrupt())
#define EINT() (_enable_interrupt())
#define INTERRUPT interrupt
#define SLEEP() (__bis_SR_register(LPM3_bits + GIE))
#define WAKEUP() (__bic_SR_register_on_exit(LPM3_bits))
#endif
#define NUM_HANDLERS 3
#define BUTTON_HANDLER_ID 0
#define TICK_HANDLER_ID 1
#define DISPATCH_HANDLER_ID 2
static void buttonHandler(void);
static void postEvent(uint8_t handlerId);
static Hal_Handler appButtonHandler;
static volatile uint16_t handlerEvents = 0;
static uint16_t clockTick = 0;
static Hal_Handler handlerTab[NUM_HANDLERS];
/* -------- APP-HAL INTERFACE -------- */
void Hal_buttonEnable(Hal_Handler handler) {
handlerTab[BUTTON_HANDLER_ID] = buttonHandler;
appButtonHandler = handler;
BUTTON_CONFIG();
Hal_delay(100);
BUTTON_ENABLE();
}
void Hal_connected(void) {
CONNECTED_LED_ON();
}
void Hal_debugOn(uint8_t line) {
switch (line) {
case 1:
DEBUG1_ON();
break;
case 2:
DEBUG2_ON();
}
}
void Hal_debugOff(uint8_t line) {
switch (line) {
case 1:
DEBUG1_OFF();
break;
case 2:
DEBUG2_OFF();
}
}
void Hal_debugPulse(uint8_t line) {
switch (line) {
case 1:
DEBUG1_ON();
DEBUG1_OFF();
break;
case 2:
DEBUG2_ON();
DEBUG2_OFF();
}
}
void Hal_delay(uint16_t msecs) {
while (msecs--) {
__delay_cycles(MCLK_TICKS_PER_MS);
}
}
void Hal_disconnected(void) {
CONNECTED_LED_OFF();
}
void Hal_init(void) {
/* setup clocks */
WDTCTL = WDTPW + WDTHOLD;
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;
if (CALBC1_1MHZ != 0xFF) {
DCOCTL = 0x00;
BCSCTL1 = CALBC1_1MHZ; /* Set DCO to 1MHz */
DCOCTL = CALDCO_1MHZ;
}
BCSCTL1 |= XT2OFF + DIVA_0;
BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1;
/* setup LEDs */
LED_CONFIG();
LED_OFF();
CONNECTED_LED_CONFIG();
CONNECTED_LED_OFF();
/* setup debug pins */
DEBUG1_CONFIG(); DEBUG1_OFF();
DEBUG2_CONFIG(); DEBUG2_OFF();
DEBUG1_ON(); DEBUG1_OFF();
/* setup TimerA1 */
TA1CTL = TASSEL_1 + MC_2; // ACLK, Continuous mode
UART_WATCH_ENABLE();
/* setup UART */
UCA0CTL1 |= UCSWRST;
EAP_RX_ENABLE();
EAP_TX_ENABLE();
EAP_RX_ACK_CONFIG();
EAP_RX_ACK_SET();
EAP_TX_ACK_CONFIG();
// suspend the MCM
EAP_RX_ACK_CLR();
UCA0CTL1 = UCSSEL_2 + UCSWRST;
UCA0MCTL = UCBRF_0 + UCBRS_6;
UCA0BR0 = 8;
UCA0CTL1 &= ~UCSWRST;
handlerTab[DISPATCH_HANDLER_ID] = Em_Message_dispatch;
}
void Hal_idleLoop(void) {
EINT();
for (;;) {
// atomically read/clear all handlerEvents
DINT();
uint16_t events = handlerEvents;
handlerEvents = 0;
if (events) { // dispatch all current events
EINT();
uint16_t mask;
uint8_t id;
for (id = 0, mask = 0x1; id < NUM_HANDLERS; id++, mask <<= 1) {
if ((events & mask) && handlerTab[id]) {
handlerTab[id]();
}
}
}
else { // await more events
SLEEP();
}
}
}
void Hal_ledOn(void) {
LED_ON();
}
void Hal_ledOff(void) {
LED_OFF();
}
bool Hal_ledRead(void) {
return LED_READ();
}
void Hal_ledToggle(void) {
LED_TOGGLE();
}
void Hal_tickStart(uint16_t msecs, Hal_Handler handler) {
handlerTab[TICK_HANDLER_ID] = handler;
clockTick = (ACLK_TICKS_PER_SECOND * msecs) / 1000;
TA1CCR0 = TA1R + clockTick; // Set the CCR0 interrupt for msecs from now.
TA1CCTL0 = CCIE; // Enable the CCR0 interrupt
}
/* -------- SRT-HAL INTERFACE -------- */
uint8_t Em_Hal_lock(void) {
#ifdef __GNUC__
uint8_t key = READ_SR & 0x8;
__disable_interrupt();
return key;
#endif
#ifdef __TI_COMPILER_VERSION__
uint8_t key = _get_interrupt_state();
_disable_interrupt();
return key;
#endif
}
void Em_Hal_reset(void) {
uint8_t key = Em_Hal_lock();
EAP_RX_ACK_CLR(); // suspend the MCM
Hal_delay(100);
EAP_RX_ACK_SET(); // reset the MCM
Hal_delay(500);
EAP_RX_INT_CLR();
EAP_TX_INT_CLR();
EAP_TX_ACK_CLR();
EAP_RX_INT_ENABLE();
Em_Hal_unlock(key);
}
void Em_Hal_startSend() {
EAP_TX_BUF = Em_Message_startTx();
}
void Em_Hal_unlock(uint8_t key) {
#ifdef __GNUC__
__asm__("bis %0,r2" : : "ir" ((uint16_t) key));
#endif
#ifdef __TI_COMPILER_VERSION__
_set_interrupt_state(key);
#endif
}
void Em_Hal_watchOff(void) {
UART_WATCH_DISABLE();
}
void Em_Hal_watchOn(void) {
UART_WATCH_ENABLE();
}
/* -------- INTERNAL FUNCTIONS -------- */
static void buttonHandler(void) {
Hal_delay(100);
if (BUTTON_PRESSED() && appButtonHandler) {
appButtonHandler();
}
}
static void postEvent(uint8_t handlerId) {
uint8_t key = Em_Hal_lock();
handlerEvents |= 1 << handlerId;
Em_Hal_unlock(key);
}
/* -------- INTERRUPT SERVICE ROUTINES -------- */
#ifdef __GNUC__
__attribute__((interrupt(PORT1_VECTOR)))
#endif
#ifdef __TI_COMPILER_VERSION__
#pragma vector=PORT1_VECTOR
#endif
INTERRUPT void buttonIsr(void) {
postEvent(BUTTON_HANDLER_ID);
BUTTON_ENABLE();
WAKEUP();
}
#ifdef __GNUC__
__attribute__((interrupt(EAP_RX_VECTOR)))
#endif
#ifdef __TI_COMPILER_VERSION__
#pragma vector=EAP_RX_VECTOR
#endif
INTERRUPT void rxIsr(void) {
uint8_t b = EAP_RX_BUF;
Em_Message_startRx();
EAP_RX_ACK_CLR();
EAP_RX_ACK_SET();
if (Em_Message_addByte(b)) {
postEvent(DISPATCH_HANDLER_ID);
}
WAKEUP();
}
#ifdef __GNUC__
__attribute__((interrupt(TIMER1_A0_VECTOR)))
#endif
#ifdef __TI_COMPILER_VERSION__
#pragma vector=TIMER1_A0_VECTOR
#endif
INTERRUPT void timerIsr(void) {
TA1CCR0 += clockTick;
postEvent(TICK_HANDLER_ID);
WAKEUP();
}
#ifdef __GNUC__
__attribute__((interrupt(EAP_TX_ACK_VECTOR)))
#endif
#ifdef __TI_COMPILER_VERSION__
#pragma vector=EAP_TX_ACK_VECTOR
#endif
INTERRUPT void txAckIsr(void) {
if (EAP_TX_ACK_TST()) {
uint8_t b;
if (Em_Message_getByte(&b)) {
EAP_TX_BUF = b;
}
EAP_TX_ACK_CLR();
}
WAKEUP();
}
#ifdef __GNUC__
__attribute__((interrupt(TIMER1_A1_VECTOR)))
#endif
#ifdef __TI_COMPILER_VERSION__
#pragma vector=TIMER1_A1_VECTOR
#endif
INTERRUPT void uartWatchdogIsr(void) {
switch (TA1IV) {
case 2: // CCR1
UART_WATCH_DISABLE();
Em_Message_restart();
WAKEUP();
break;
}
}