-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhal_uart_dma.c
More file actions
326 lines (252 loc) · 8.23 KB
/
Copy pathhal_uart_dma.c
File metadata and controls
326 lines (252 loc) · 8.23 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
/**
* @file hal_bt.c
***************************************************************************/
#include <stdint.h>
#include <msp430x54x.h>
#include "hal_compat.h"
#include <btstack/hal_uart_dma.h>
extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled);
// debugging only
// #include <stdio.h>
#define BT_PORT_OUT P9OUT
#define BT_PORT_SEL P9SEL
#define BT_PORT_DIR P9DIR
#define BT_PORT_REN P9REN
#define BT_PIN_TXD BIT4
#define BT_PIN_RXD BIT5
// RXD P9.5
// TXD P9.4
// RTS P1.4
// CTS P1.3
void dummy_handler(void){};
// rx state
static uint16_t bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = 0;
// tx state
static uint16_t bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = 0;
// handlers
static void (*rx_done_handler)(void) = dummy_handler;
static void (*tx_done_handler)(void) = dummy_handler;
static void (*cts_irq_handler)(void) = dummy_handler;
/**
* @brief Initializes the serial communications peripheral and GPIO ports
* to communicate with the PAN BT .. assuming 16 Mhz CPU
*
* @param none
*
* @return none
*/
void hal_uart_dma_init(void)
{
BT_PORT_SEL |= BT_PIN_RXD + BT_PIN_TXD;
BT_PORT_DIR |= BT_PIN_TXD;
BT_PORT_DIR &= ~BT_PIN_RXD;
// set BT RTS (P1.4)
P1SEL &= ~BIT4; // = 0 - I/O
P1DIR |= BIT4; // = 1 - Output
P1OUT |= BIT4; // = 1 - RTS high -> stop
// set BT CTS
P1SEL &= ~BIT3; // = 0 - I/O
P1DIR &= ~BIT3; // = 0 - Input P1DIR |= BIT4; // RTS
// set BT SHUTDOWN (P8.2) to 1 (active low)
P8SEL &= ~BIT2; // = 0 - I/O
P8DIR |= BIT2; // = 1 - Output
P8OUT |= BIT2; // = 1 - Active low -> ok
// Enable ACLK to provide 32 kHz clock to Bluetooth module
P11SEL |= BIT0;
P11DIR |= BIT0;
// wait for Bluetooth to power up properly after providing 32khz clock
waitAboutOneSecond();
UCA2CTL1 |= UCSWRST; //Reset State
UCA2CTL0 = UCMODE_0;
UCA2CTL0 &= ~UC7BIT; // 8bit char
UCA2CTL1 |= UCSSEL_2;
UCA2CTL1 &= ~UCSWRST; // continue
hal_uart_dma_set_baud(115200);
}
/**
UART used in low-frequency mode
In this mode, the maximum USCI baud rate is one-third the UART source clock frequency BRCLK.
16000000 / 576000 = 277.77
16000000 / 115200 = 138.88
16000000 / 921600 = 17.36
16000000 / 1000000 = 16.00
16000000 / 2000000 = 8.00
16000000 / 2400000 = 6.66
16000000 / 3000000 = 3.33
16000000 / 4000000 = 2.00
*/
int hal_uart_dma_set_baud(uint32_t baud){
int result = 0;
UCA2CTL1 |= UCSWRST; //Reset State
switch (baud){
case 4000000:
UCA2BR0 = 2;
UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000
break;
case 3000000:
UCA2BR0 = 3;
UCA2BR1 = 0;
UCA2MCTL= 3 << 1; // + 0.375
break;
case 2400000:
UCA2BR0 = 6;
UCA2BR1 = 0;
UCA2MCTL= 5 << 1; // + 0.625
break;
case 2000000:
UCA2BR0 = 8;
UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000
break;
case 1000000:
UCA2BR0 = 16;
UCA2BR1 = 0;
UCA2MCTL= 0 << 1; // + 0.000
break;
case 921600:
UCA2BR0 = 17;
UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // 3 << 1; // + 0.375
break;
case 115200:
UCA2BR0 = 138; // from family user guide
UCA2BR1 = 0;
UCA2MCTL= 7 << 1; // + 0.875
break;
case 57600:
UCA2BR0 = 21;
UCA2BR1 = 1;
UCA2MCTL= 7 << 1; // + 0.875
break;
default:
result = -1;
break;
}
UCA2CTL1 &= ~UCSWRST; // continue
return result;
}
void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
rx_done_handler = the_block_handler;
}
void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
tx_done_handler = the_block_handler;
}
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
if (the_irq_handler){
P1IFG = 0; // no IRQ pending
P1IV = 0; // no IRQ pending
P1IES &= ~BIT3; // IRQ on 0->1 transition
P1IE |= BIT3; // enable IRQ for P1.3
cts_irq_handler = the_irq_handler;
return;
}
P1IE &= ~BIT3;
cts_irq_handler = dummy_handler;
}
/**********************************************************************/
/**
* @brief Disables the serial communications peripheral and clears the GPIO
* settings used to communicate with the BT.
*
* @param none
*
* @return none
**************************************************************************/
void hal_uart_dma_shutdown(void) {
UCA2IE &= ~(UCRXIE | UCTXIE);
UCA2CTL1 = UCSWRST; //Reset State
BT_PORT_SEL &= ~( BT_PIN_RXD + BT_PIN_TXD );
BT_PORT_DIR |= BT_PIN_TXD;
BT_PORT_DIR |= BT_PIN_RXD;
BT_PORT_OUT &= ~(BT_PIN_TXD + BT_PIN_RXD);
}
void hal_uart_dma_send_block(const uint8_t * data, uint16_t len){
// printf("hal_uart_dma_send_block, size %u\n\r", len);
UCA2IE &= ~UCTXIE ; // disable TX interrupts
tx_buffer_ptr = (uint8_t *) data;
bytes_to_write = len;
UCA2IE |= UCTXIE; // enable TX interrupts
}
static inline void hal_uart_dma_enable_rx(void){
P1OUT &= ~BIT4; // = 0 - RTS low -> ok
}
static inline void hal_uart_dma_disable_rx(void){
P1OUT |= BIT4; // = 1 - RTS high -> stop
}
// int used to indicate a request for more new data
void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
UCA2IE &= ~UCRXIE ; // disable RX interrupts
rx_buffer_ptr = buffer;
bytes_to_read = len;
UCA2IE |= UCRXIE; // enable RX interrupts
hal_uart_dma_enable_rx(); // enable receive
}
void hal_uart_dma_set_sleep(uint8_t sleep){
hal_cpu_set_uart_needed_during_sleep(!sleep);
}
// block-wise "DMA" RX/TX UART driver
#ifdef __GNUC__
__attribute__((interrupt(USCI_A2_VECTOR)))
#endif
#ifdef __IAR_SYSTEMS_ICC__
#pragma vector=USCI_A2_VECTOR
__interrupt
#endif
void usbRxTxISR(void){
// find reason
switch (UCA2IV){
case 2: // RXIFG
if (bytes_to_read == 0) {
hal_uart_dma_disable_rx();
UCA2IE &= ~UCRXIE ; // disable RX interrupts
return;
}
*rx_buffer_ptr = UCA2RXBUF;
++rx_buffer_ptr;
--bytes_to_read;
if (bytes_to_read > 0) {
return;
}
P1OUT |= BIT4; // = 1 - RTS high -> stop
UCA2IE &= ~UCRXIE ; // disable RX interrupts
(*rx_done_handler)();
// force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break;
case 4: // TXIFG
if (bytes_to_write == 0){
UCA2IE &= ~UCTXIE ; // disable TX interrupts
return;
}
UCA2TXBUF = *tx_buffer_ptr;
++tx_buffer_ptr;
--bytes_to_write;
if (bytes_to_write > 0) {
return;
}
UCA2IE &= ~UCTXIE ; // disable TX interrupts
(*tx_done_handler)();
// force exit low power mode
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break;
default:
break;
}
}
// CTS ISR
extern void ehcill_handle(uint8_t action);
#define EHCILL_CTS_SIGNAL 0x034
#ifdef __GNUC__
__attribute__((interrupt(PORT1_VECTOR)))
#endif
#ifdef __IAR_SYSTEMS_ICC__
#pragma vector=PORT1_VECTOR
__interrupt
#endif
void ctsISR(void){
P1IV = 0;
(*cts_irq_handler)();
}