]> git.karo-electronics.de Git - oswald.git/blobdiff - metawatch/mw_bt.c
Add modified LPM3_EXIT_ISR to work around FLL IRQ wake-up problem
[oswald.git] / metawatch / mw_bt.c
index d5c7d26bbd29821fa7ebff3adc7b6b3de8077699..ace18e9a5e0dff740734fe31248e1c68613f0cbb 100644 (file)
@@ -58,15 +58,17 @@ __interrupt void UCA1_ISR (void)
                        if (UCA1STAT & UCRXERR) {
                                debug_uart_tx("BT UART RXERR: ");
                                if (UCA1STAT & UCOE)
-                                       debug_uart_tx("overrun\n");
+                                       debug_uart_tx("overrun ");
                                if (UCA1STAT & UCPE)
-                                       debug_uart_tx("parity err\n");
+                                       debug_uart_tx("parity err ");
                                if (UCA1STAT & UCFE)
-                                       debug_uart_tx("frm-err\n");
+                                       debug_uart_tx("frm-err ");
+                               debug_uart_tx("\n");
                        }
                        bt_rx_buf[bt_rx_buf_wpos++] = UCA1RXBUF;
                        bt_rx_buf_wpos %= BT_RX_MAX_SIZE;
-                       LPM3_EXIT;
+                       // LPM3_EXIT;
+                       LPM3_EXIT_ISR();
                        _event_src |= BT_UART_RCV_EVENT;
                        break;
                case 4: // TXIFG
@@ -96,9 +98,10 @@ void mw_init_bt_uart(const bt_uart_baud_t baud)
        //UCA1CTL0 |= UCRXEIE;
 
        UCA1CTL1 &= ~UCSWRST;
+
        /* clear interrup flags */
-       UCA1IE = UCRXIE;
        UCA1IFG = 0;
+       UCA1IE = UCRXIE;
 }
 
 #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)
                nop();
 }
 #else
-void mw_bt_uart_tx(const void *buf, const unsigned int len)
+int mw_bt_uart_tx(const void *buf, const unsigned int len)
 {
-       unsigned int pos;
+       unsigned int pos, i;
        // char txstr[8];
 
        pos = 0;
        // debug_uart_tx("BT tx: ");
        while (pos < len) {
-               // wait for CTS to go low
-               while ((BT_IO_PIN & BT_IO_CTS))
-                       nop();
+               // watch for CTS to be low
+               i = 0;
+               while ((BT_IO_PIN & BT_IO_CTS) && (i < 1000)) {
+                       __delay_cycles(16000);
+                       i++;
+                       if (i >= 1000)
+                               return -1;
+                       // nop();
+               }
 
                // do not start a transfer if UART is busy, e.g. rx-ing
                while (UCA1STAT & UCBUSY)
@@ -147,25 +156,31 @@ void mw_bt_uart_tx(const void *buf, const unsigned int len)
        }
        while (UCA1STAT & UCBUSY)
                nop();
+
+       return len;
 }
 #endif
 
-static void load_cc256x_init_script(void)
+static int load_cc256x_init_script(void)
 {
        uint32_t pos;
        unsigned char *tptr;
+       int tlen;
 
        pos = 0;
        while (pos < cc256x_init_script_size) {
                if (_event_src != 0)
                        handle_event();
                tptr = (unsigned char *)(cc256x_init_script + pos);
-               mw_bt_uart_tx(tptr, 4 + tptr[3]);
-               pos += 4 + tptr[3];
+               tlen = mw_bt_uart_tx(tptr, 4 + tptr[3]);
+               if (tlen < 0)
+                       return -1;
+               pos += tlen /*4 + tptr[3]*/;
                // each init script part is one HCI command so wait for reply
                if (_event_src != 0)
                        handle_event();
        }
+       return 0;
 }
 
 void mw_enable_bt(void)
@@ -174,6 +189,7 @@ void mw_enable_bt(void)
 
        /* make sure it resets */
        BT_SHUTDOWN();
+       __delay_cycles(16000);
 
        /* enable 32kHz ACLK output to BT module */
        P11DIR |= BIT0;
@@ -182,11 +198,19 @@ void mw_enable_bt(void)
        // wait for clock to stabilize
        __delay_cycles(16000);
 
+       // disable the IRQ on CTS, later used to get a wakeup IRQ from eHCILL
+       // will be enabled when going to sleep
+       P1IE &= ~BT_IO_CTS;
+       P1IES &= ~BT_IO_CTS;
+
        BT_IO_PDIR &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
        BT_IO_PDIR |= BT_IO_RTS;
+
        BT_IO_POUT &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
        BT_IO_POUT &= ~BT_IO_RTS; // low == ready, high == !ready
 
+       BT_IO_REN |= BT_IO_CTS; // enable pull-down on CTS, POUT-CTS is 0 already
+
        /* setup UART pins */
        BT_UART_PSEL |= BT_UART_TX_PIN | BT_UART_RX_PIN;
        // P5OUT |= BT_UART_TX_PIN | BT_UART_RX_PIN;
@@ -207,28 +231,45 @@ void mw_enable_bt(void)
        }
        if (i>=1000) {
                debug_uart_tx("Timeout waiting for CC256x to lower CTS\n");
+               mw_bt_enabled = 0;
        } else {
                debug_uart_tx("CC256x CTS low - uploading init\n");
-               for (i=0; i<100; i++) {
-                       __delay_cycles(16000); // give it some more before anyone sends data
+
+               // the init script consists of HCI cmds so HCI must be setup before
+               bt_hci_init();
+
+               // give it some more time before anyone sends data
+               for (i=0; i<10; i++) {
+                       __delay_cycles(16000);
+               }
+               if (load_cc256x_init_script() < 0) {
+                       debug_uart_tx("init upload failed!\n");
+                       return;
                }
-               load_cc256x_init_script();
+
+               __delay_cycles(32000);
+
                debug_uart_tx("init uploaded\n");
-       }
 
-       P1IE &= ~BT_IO_CTS;
-       P1IES &= ~BT_IO_CTS;
+               init_l2cap();
 
-       bt_hci_init();
-       init_l2cap();
+               if (_event_src != 0)
+                       handle_event();
 
-       mw_bt_enabled = 1;
+               mw_bt_enabled = 1;
+       }
 }
 
 void mw_disable_bt(void)
 {
        mw_bt_enabled = 0;
 
+       // disable the IRQ on CTS
+       P1IE &= ~BT_IO_CTS;
+       P1IES &= ~BT_IO_CTS;
+       // BT_IO_REN &= ~BT_IO_CTS; // disable pull-down on CTS
+       P1IFG &= ~BT_IO_CTS;
+
        /* disable UART RX interrupt */
        UCA1IE &= ~UCRXIE;