diff --git a/platforms/msp430f229lp-cc2564b/Makefile b/platforms/msp430f229lp-cc2564b/Makefile new file mode 100644 index 000000000..19ce6b392 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/Makefile @@ -0,0 +1,156 @@ +# Makefile for MSP-EXP430F5438 board with CC2560B/CC2564B/CC2567 modules +# +# Please check instructions at https://code.google.com/p/btstack/wiki/CC256x on downloading +# and converting the init scripts for use with BTstack +# +# mspgcc is used: http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=MSPGCC_Wiki +# + +# init scripts +CC2560B = bluetooth_init_cc2560B_1.0_BT_Spec_4.1.o +CC2564B = bluetooth_init_cc2564B_1.0_BT_Spec_4.1.o +CC2567 = CC256x_BT_Service_Pack_2.8_ANT_1.16.o + +BTSTACK_ROOT = ../.. +VPATH += example +VPATH += firmware +VPATH += src +VPATH += ${BTSTACK_ROOT}/platforms/msp430 +VPATH += $(BTSTACK_ROOT)/ble +VPATH += $(BTSTACK_ROOT)/chipset-cc256x +VPATH += $(BTSTACK_ROOT)/example/embedded +VPATH += $(BTSTACK_ROOT)/src + +MCU = msp430f5529 + +CC = msp430-gcc +CFLAGS = -mmcu=${MCU} -Os -Wall -fno-toplevel-reorder +CFLAGS += \ + -I. \ + -I src \ + -I firmware \ + -I$(BTSTACK_ROOT)/include \ + -I$(BTSTACK_ROOT)/src \ + -I$(BTSTACK_ROOT)/ble \ + -I$(BTSTACK_ROOT)/chipset-cc256x \ + -I${BTSTACK_ROOT}/platforms/msp430 \ + +LDFLAGS = -mmcu=${MCU} + +CORE = \ + hci_dump.c \ + btstack_memory.c \ + linked_list.c \ + memory_pool.c \ + utils.c \ + main.c \ + hal_board.c \ + hal_usb.c \ + hal_tick.c \ + run_loop.c \ + run_loop_embedded.c \ + hal_cpu.c \ + hal_compat.c \ + +COMMON = \ + hal_uart_dma.c \ + bt_control_cc256x.c \ + hci.c \ + hci_cmds.c \ + hci_transport_h4_ehcill_dma.c \ + remote_device_db_memory.c \ + +SPP = \ + l2cap.c \ + l2cap_signaling.c \ + rfcomm.c \ + sdp_util.c \ + +SDP_CLIENT += \ + sdp_client.o \ + sdp_parser.o \ + sdp_query_util.o \ + sdp_query_rfcomm.o \ + +BLE = \ + att.c \ + att_server.c \ + central_device_db_memory.c \ + sm.c \ + att_dispatch.c \ + l2cap_le.c \ + ${CC2564B} \ +# gatt_client.c \ + +LCD = hal_lcd.c hal_lcd_fonts.c + + +CORE_OBJ = $(CORE:.c=.o) +COMMON_OBJ = $(COMMON:.c=.o) +SPP_OBJ = $(SPP:.c=.o) +BLE_OBJ = $(BLE:.c=.o) +LCD_OBJ = $(LCD:.c=.o) + +# create .hex file from .out +%.hex: %.out + msp430-objcopy -O ihex $< $@ + +# create firmware image from common objects and example source file + +all: led_counter.hex spp_counter.hex gap_inquiry.hex spp_flowcontrol.hex \ + sdp_rfcomm_query.hex sdp_general_query.hex + +# compiling requires a 20-bit mspgcc version +# spp_and_le_counter.hex + +# compiling ant-test requires special ant init script +# ant-test.hex + +# compile GATT database +%.h: %.gatt + python ${BTSTACK_ROOT}/ble/compile-gatt.py $< $@ + + +led_counter.out: ${CORE_OBJ} ${COMMON_OBJ} ${CC2560B} led_counter.o + ${CC} $^ ${LDFLAGS} -o $@ + +ant-test.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} profile.h sdp.o ant_cmds.o ${CC2567} ant-test.o + ${CC} $^ ${LDFLAGS} -o $@ + +ble_server.out: ${CORE_OBJ} ${COMMON_OBJ} ${BLE_OBJ} ${LCD_OBJ} profile.h ble_server.o + ${CC} $^ ${LDFLAGS} -o $@ + +hid_demo.out: ${CORE_OBJ} ${COMMON_OBJ} ${LCD_OBJ} ${SPP_OBJ} ${CC2560B} hid_demo.o + ${CC} $^ ${LDFLAGS} -o $@ + +spp_accel.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} spp_accel.o sdp.o hal_adc.o + ${CC} $^ ${LDFLAGS} -o $@ + +spp_and_le_counter.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${BLE_OBJ} spp_and_le_counter.h spp_and_le_counter.o sdp.o hal_adc.o + ${CC} $^ ${LDFLAGS} -o $@ + +spp_counter.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} spp_counter.o sdp.o + ${CC} $^ ${LDFLAGS} -o $@ + +spp_flowcontrol.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} spp_flowcontrol.o sdp.o + ${CC} $^ ${LDFLAGS} -o $@ + +gap_inquiry.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${CC2560B} gap_inquiry.o + ${CC} $^ ${LDFLAGS} -o $@ + +sdp_rfcomm_query.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${SDP_CLIENT} ${CC2560B} sdp_rfcomm_query.o + ${CC} $^ ${LDFLAGS} -o $@ + +sdp_general_query.out: ${CORE_OBJ} ${COMMON_OBJ} ${SPP_OBJ} ${SDP_CLIENT} ${CC2560B} sdp_general_query.o + ${CC} $^ ${LDFLAGS} -o $@ + +clean: + rm -f $ *.o *.out *.hex profile.h spp_and_le_counter.h ../driver/*.o ../../src/*.o ../src/*.o ../firmware/*.o ${BTSTACK_ROOT}/chipset-cc256x/*.o ${BTSTACK_ROOT}/src/*.o + +size: all + msp430-size *.o + msp430-size *.out + +%.flash: %.hex + mspdebug tilib --force-reset "prog $^" + diff --git a/platforms/msp430f229lp-cc2564b/btstack-config.h b/platforms/msp430f229lp-cc2564b/btstack-config.h new file mode 100644 index 000000000..dedd58403 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/btstack-config.h @@ -0,0 +1,39 @@ + +#ifndef __BTSTACK_CONFIG +#define __BTSTACK_CONFIG + +#define EMBEDDED + +#define HAVE_BLE + +#define HAVE_INIT_SCRIPT +#define HAVE_BZERO +#define HAVE_TICK + +#define HAVE_EHCILL + +#define HAVE_HCI_DUMP +// #define ENABLE_LOG_ERROR +// #define ENABLE_LOG_INFO + +#define HCI_ACL_PAYLOAD_SIZE 52 + +// +#define MAX_SPP_CONNECTIONS 1 + +#define MAX_NO_HCI_CONNECTIONS MAX_SPP_CONNECTIONS +#define MAX_NO_GATT_CLIENTS 0 +#define MAX_NO_GATT_SUBCLIENTS 0 +#define MAX_NO_L2CAP_SERVICES 2 +#define MAX_NO_L2CAP_CHANNELS (1+MAX_SPP_CONNECTIONS) +#define MAX_NO_RFCOMM_MULTIPLEXERS MAX_SPP_CONNECTIONS +#define MAX_NO_RFCOMM_SERVICES 1 +#define MAX_NO_RFCOMM_CHANNELS MAX_SPP_CONNECTIONS +#define MAX_NO_BNEP_SERVICES 1 +#define MAX_NO_BNEP_CHANNELS MAX_SPP_CONNECTIONS +#define MAX_NO_DB_MEM_DEVICE_LINK_KEYS 2 +#define MAX_NO_DB_MEM_DEVICE_NAMES 0 +#define MAX_NO_DB_MEM_SERVICES 1 + +#endif + diff --git a/platforms/msp430f229lp-cc2564b/example/led_counter.c b/platforms/msp430f229lp-cc2564b/example/led_counter.c new file mode 100644 index 000000000..11c3a41b7 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/example/led_counter.c @@ -0,0 +1,66 @@ +// ***************************************************************************** +// +// led_counter demo - uses the BTstack run loop to blink an LED +// +// ***************************************************************************** + +#include +#include +#include +#include + +#include + +#include "hal_board.h" +#include "hal_compat.h" +#include "hal_usb.h" + +#include "btstack_memory.h" + +#include +#include "btstack-config.h" + +#define HEARTBEAT_PERIOD_MS 1000 + +static int counter = 0; +static timer_source_t heartbeat; + +static void run_loop_register_timer(timer_source_t *timer, uint16_t period){ + run_loop_set_timer(timer, period); + run_loop_add_timer(timer); +} + +static void heartbeat_handler(timer_source_t *ts){ + // increment counter + char lineBuffer[30]; + sprintf(lineBuffer, "BTstack counter %04u\n\r", ++counter); + printf(lineBuffer); + + // toggle LED + LED2_OUT = LED2_OUT ^ LED2_PIN; + + // re-register timer + run_loop_register_timer(ts, HEARTBEAT_PERIOD_MS); +} + +static void timer_setup(){ + // set one-shot timer + heartbeat.process = &heartbeat_handler; + run_loop_register_timer(&heartbeat, HEARTBEAT_PERIOD_MS); +} + +int btstack_main(int argc, const char * argv[]); +int btstack_main(int argc, const char * argv[]){ + + printf("Run...\n\r"); + + timer_setup(); + + + // go! + run_loop_execute(); + + // happy compiler! + return 0; +} + diff --git a/platforms/msp430f229lp-cc2564b/firmware/hal_board.c b/platforms/msp430f229lp-cc2564b/firmware/hal_board.c new file mode 100755 index 000000000..f8412709f --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/firmware/hal_board.c @@ -0,0 +1,255 @@ +/** + * @file hal_board.c + * + * Copyright 2008 Texas Instruments, Inc. +******************************************************************************/ +#include "hal_board.h" + +#include "msp430.h" + +#include "hal_compat.h" +// #include "hal_adc.h" +// #include "hal_usb.h" + +static void halBoardSetVCoreUp(unsigned char level); +static void halBoardSetVCoreDown(unsigned char level); +static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed, + unsigned char *setDcoRange, + unsigned char *setVCore, + unsigned int *setMultiplier); + +/************************************************************************ + * @brief Increments the VCore setting. + * + * @param level The target VCore setting + * + * @return none + *************************************************************************/ +static void halBoardSetVCoreUp (unsigned char level) +{ + // Open PMM module registers for write access + PMMCTL0_H = 0xA5; + + // Set SVS/M high side to new level + SVSMHCTL = (SVSMHCTL & ~(SVSHRVL0*3 + SVSMHRRL0)) | \ + (SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level); + + // Set SVM new Level + SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level; + // Set SVS/M low side to new level + SVSMLCTL = (SVSMLCTL & ~(SVSMLRRL_3)) | (SVMLE + SVSMLRRL0 * level); + + while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay) + PMMCTL0_L = PMMCOREV0 * level; // Set VCore to x + PMMIFG &= ~(SVMLVLRIFG + SVMLIFG); // Clear already set flags + + if ((PMMIFG & SVMLIFG)) + while ((PMMIFG & SVMLVLRIFG) == 0); // Wait till level is reached + + // Set SVS/M Low side to new level + SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \ + (SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level); + + // Lock PMM module registers from write access + PMMCTL0_H = 0x00; +} + +/************************************************************************ + * @brief Decrements the VCore setting. + * + * @param level The target VCore. + * + * @return none + *************************************************************************/ +static void halBoardSetVCoreDown(unsigned char level) +{ + // Open PMM module registers for write access + PMMCTL0_H = 0xA5; + + // Set SVS/M low side to new level + SVSMLCTL = (SVSMLCTL & ~(SVSLRVL0*3 + SVSMLRRL_3)) | \ + (SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level); + + while ((PMMIFG & SVSMLDLYIFG) == 0); // Wait till SVM is settled (Delay) + PMMCTL0_L = (level * PMMCOREV0); // Set VCore to new level + // Lock PMM module registers for write access + + PMMCTL0_H = 0x00; +} + +/************************************************************************ + * @brief Get function for the DCORSEL, VCORE, and DCO multiplier settings + * that map to a given clock speed. + * + * @param systemClockSpeed Target DCO frequency - SYSCLK_xxMHZ. + * + * @param setDcoRange Pointer to the DCO range select bits. + * + * @param setVCore Pointer to the VCore level bits. + * + * @param setMultiplier Pointer to the DCO multiplier bits. + * + * @return none + ************************************************************************/ +static void halBoardGetSystemClockSettings(unsigned char systemClockSpeed, + unsigned char *setDcoRange, + unsigned char *setVCore, + unsigned int *setMultiplier) +{ + switch (systemClockSpeed) + { + case SYSCLK_1MHZ: + *setDcoRange = DCORSEL_1MHZ; + *setVCore = VCORE_1MHZ; + *setMultiplier = DCO_MULT_1MHZ; + break; + case SYSCLK_4MHZ: + *setDcoRange = DCORSEL_4MHZ; + *setVCore = VCORE_4MHZ; + *setMultiplier = DCO_MULT_4MHZ; + break; + case SYSCLK_8MHZ: + *setDcoRange = DCORSEL_8MHZ; + *setVCore = VCORE_8MHZ; + *setMultiplier = DCO_MULT_8MHZ; + break; + case SYSCLK_12MHZ: + *setDcoRange = DCORSEL_12MHZ; + *setVCore = VCORE_12MHZ; + *setMultiplier = DCO_MULT_12MHZ; + break; + case SYSCLK_16MHZ: + *setDcoRange = DCORSEL_16MHZ; + *setVCore = VCORE_16MHZ; + *setMultiplier = DCO_MULT_16MHZ; + break; + } +} + +/************************************************************************ + * @brief Set function for the PMM core voltage (PMMCOREV) setting + * + * @param level Target VCore setting + * + * @return none + *************************************************************************/ +void halBoardSetVCore(unsigned char level) +{ + unsigned int currentVCore; + + currentVCore = PMMCTL0 & PMMCOREV_3; // Get actual VCore + // Change VCore step by step + while (level != currentVCore) + { + if (level > currentVCore) + halBoardSetVCoreUp(++currentVCore); + else + halBoardSetVCoreDown(--currentVCore); + } +} + +/************************************************************************ + * @brief Initialization routine for XT1. + * + * Sets the necessary internal capacitor values and loops until all + * ocillator fault flags remain cleared. + * + * @param none + * + * @return none + *************************************************************************/ +void halBoardStartXT1(void) +{ + /* LFXT can take up to 1000ms to start. + * Go to the loop below 4 times for a total of 2 sec timout. + * If a timeout happens due to no XTAL present or a faulty XTAL + * the clock system will fall back to REFOCLK (~32kHz) */ + P5SEL |= BIT4 + BIT5; + /* Set XTAL2 pins to output to reduce power consumption */ + P5DIR |= BIT2 + BIT3; + /* Turn XT1 ON */ + UCSCTL6 &= ~(XT1OFF); + /* Set XTAL CAPS to 12 pF */ + UCSCTL6 |= XCAP_3; + + do { + /* Clear Oscillator fault flags */ + UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); + /* Clear the Oscillator fault interrupt flag */ + SFRIFG1 &= ~OFIFG; + /* Test the fault flag */ + __delay_cycles(56250); + } while (SFRIFG1 & OFIFG); + /* Reduse drive strength to reduce power consumption */ + UCSCTL6 &= ~(XT1DRIVE_3); +} + +/************************************************************************ + * @brief Set function for MCLK frequency. + * + * @param systemClockSpeed Intended frequency of operation - SYSCLK_xxMHZ. + * + * @return none + *************************************************************************/ +void halBoardSetSystemClock(unsigned char systemClockSpeed) +{ + unsigned char setDcoRange = 0; + unsigned char setVCore = 0; + unsigned int setMultiplier = 0; + + halBoardGetSystemClockSettings( systemClockSpeed, &setDcoRange, \ + &setVCore, &setMultiplier); + + if (setVCore > (PMMCTL0 & PMMCOREV_3)) // Only change VCore if necessary + halBoardSetVCore( setVCore ); + + UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx + UCSCTL1 = setDcoRange; // Select suitable range + + UCSCTL2 = setMultiplier + FLLD_1; // Set DCO Multiplier + UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV ; + + // Worst-case settling time for the DCO when the DCO range bits have been + // changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG + // for optimization. + // 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle + // t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle + + // __delay_cycles(562500); + int i; + for (i=0;i<10;i++){ + __delay_cycles(56250); + } +} + +/************************************************************************ + * @brief Initializes all GPIO configurations. + * TI example did set all ports to OUTPUT, we don't. + * @param none + * + * @return none + *************************************************************************/ +void halBoardInit(void) +{ + //Tie unused ports + PAOUT = 0; + PADIR = 0; + PASEL = 0; + PBOUT = 0; + PBDIR = 0; + PBSEL = 0; + PCOUT = 0; + PCDIR = 0; + PCSEL = 0; + PDOUT = 0; + PDDIR = 0; + PDSEL = 0; + PJOUT = 0; + PJDIR = 0; + + // AUDIO_PORT_OUT = AUDIO_OUT_PWR_PIN ; + // USB_PORT_DIR &= ~USB_PIN_RXD; // USB RX Pin, Input with + // // ...pulled down Resistor + // USB_PORT_OUT &= ~USB_PIN_RXD; + // USB_PORT_REN |= USB_PIN_RXD; +} diff --git a/platforms/msp430f229lp-cc2564b/firmware/hal_board.h b/platforms/msp430f229lp-cc2564b/firmware/hal_board.h new file mode 100755 index 000000000..f98bee6ce --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/firmware/hal_board.h @@ -0,0 +1,91 @@ +/************************************************************************ + Filename: hal_board.h + + Copyright 2008 Texas Instruments, Inc. +***************************************************************************/ +#ifndef HAL_BOARD_H +#define HAL_BOARD_H + +// LED 1 = P1.0 +#define LED1_DIR P1DIR +#define LED1_OUT P1OUT +#define LED1_PIN BIT0 + +// LED 2 = P4.7 +#define LED2_DIR P4DIR +#define LED2_OUT P4OUT +#define LED2_PIN BIT7 + +#define CLK_PORT_DIR P11DIR +#define CLK_PORT_OUT P11OUT +#define CLK_PORT_SEL P11SEL + +#define ACLK_PIN BIT0 +#define MCLK_PIN BIT1 +#define SMCLK_PIN BIT2 + +#define XT1_XTAL_DIR P7DIR +#define XT1_XTAL_SEL P7SEL +#define XT1_XTAL_OUT P7OUT + +#define SYSCLK_1MHZ 0 +#define SYSCLK_4MHZ 1 +#define SYSCLK_8MHZ 2 +#define SYSCLK_12MHZ 3 +#define SYSCLK_16MHZ 4 +#define SYSCLK_20MHZ 5 +#define SYSCLK_25MHZ 6 + +#define DCO_MULT_1MHZ 30 +#define DCO_MULT_4MHZ 122 +#define DCO_MULT_8MHZ 244 +#define DCO_MULT_12MHZ 366 +#define DCO_MULT_16MHZ 488 +#define DCO_MULT_20MHZ 610 +#define DCO_MULT_25MHZ 763 + +#define DCORSEL_1MHZ DCORSEL_2 +#define DCORSEL_4MHZ DCORSEL_4 +#define DCORSEL_8MHZ DCORSEL_4 +#define DCORSEL_12MHZ DCORSEL_5 +#define DCORSEL_16MHZ DCORSEL_5 +#define DCORSEL_20MHZ DCORSEL_6 +#define DCORSEL_25MHZ DCORSEL_7 + +// Due to erratum FLASH28 the expected VCORE settings, as follows, +// cannot be achieved. The Vcore setting should not be changed. +//#define VCORE_1MHZ PMMCOREV_0 +//#define VCORE_4MHZ PMMCOREV_0 +//#define VCORE_8MHZ PMMCOREV_0 +//#define VCORE_12MHZ PMMCOREV_0 +//#define VCORE_16MHZ PMMCOREV_1 +//#define VCORE_20MHZ PMMCOREV_2 +//#define VCORE_25MHZ PMMCOREV_3 +#define VCORE_1MHZ PMMCOREV_2 +#define VCORE_4MHZ PMMCOREV_2 +#define VCORE_8MHZ PMMCOREV_2 +#define VCORE_12MHZ PMMCOREV_2 +#define VCORE_16MHZ PMMCOREV_2 + +// Due to erratum FLASH28 the expected VCORE settings, as follows, +// cannot be achieved. The Vcore setting should not be changed. +//#define VCORE_1_35V PMMCOREV_0 +//#define VCORE_1_55V PMMCOREV_1 +#define VCORE_1_75V PMMCOREV_2 +//#define VCORE_1_85V PMMCOREV_3 + +/*---------------------------------------------------------------- + * Function Prototypes + *---------------------------------------------------------------- + */ + +void halBoardSetVCore(unsigned char level); +void halBoardDisableSVS(void); +void halBoardEnableSVS(void); +void halBoardStartXT1(void); +void halBoardSetSystemClock(unsigned char systemClockSpeed); +void halBoardOutputSystemClock(void); +void halBoardStopOutputSystemClock(void); +void halBoardInit(void); + +#endif diff --git a/platforms/msp430f229lp-cc2564b/firmware/hal_usb.c b/platforms/msp430f229lp-cc2564b/firmware/hal_usb.c new file mode 100755 index 000000000..938deef49 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/firmware/hal_usb.c @@ -0,0 +1,98 @@ +/** + * @file hal_usb.c + * + * Copyright 2008 Texas Instruments, Inc. +***************************************************************************/ +#include +#include "hal_usb.h" + +/************************************************************************ + * @brief Initializes the serial communications peripheral and GPIO ports + * to communicate with the TUSB3410. + * + * @param none + * + * @return none + **************************************************************************/ +void halUsbInit(void) +{ + + USB_PORT_SEL |= USB_PIN_RXD + USB_PIN_TXD; + USB_PORT_DIR |= USB_PIN_TXD; + USB_PORT_DIR &= ~USB_PIN_RXD; + + UCA1CTL1 |= UCSWRST; //Reset State + UCA1CTL0 = UCMODE_0; + + UCA1CTL0 &= ~UC7BIT; // 8bit char + UCA1CTL1 |= UCSSEL_2; +#if 0 + // 57600 @ 16 Mhz + UCA1BR0 = 16; + UCA1BR1 = 1; +#else + // 115200 @ 16 Mhz + UCA1BR0 = 138; + UCA1BR1 = 0; +#endif + UCA1MCTL = 0xE; + UCA1CTL1 &= ~UCSWRST; +} + +/************************************************************************ + * @brief Disables the serial communications peripheral and clears the GPIO + * settings used to communicate with the TUSB3410. + * + * @param none + * + * @return none + **************************************************************************/ +void halUsbShutDown(void) +{ + UCA1IE &= ~UCRXIE; + UCA1CTL1 = UCSWRST; //Reset State + USB_PORT_SEL &= ~( USB_PIN_RXD + USB_PIN_TXD ); + USB_PORT_DIR |= USB_PIN_TXD; + USB_PORT_DIR |= USB_PIN_RXD; + USB_PORT_OUT &= ~(USB_PIN_TXD + USB_PIN_RXD); +} + +/************************************************************************ + * @brief Sends a character over UART to the TUSB3410. + * + * @param character The character to be sent. + * + * @return none + **************************************************************************/ +void halUsbSendChar(char character) +{ + while (!(UCA1IFG & UCTXIFG)); + UCA1TXBUF = character; +} + +char halUsbRecvChar(){ + while (!(UCA1IFG & UCRXIFG)); + return UCA1RXBUF; +} + +/************************************************************************ + * @brief Sends a string of characters to the TUSB3410 + * + * @param string[] The array of characters to be transmit to the TUSB3410. + * + * @param length The length of the string. + * + * @return none + **************************************************************************/ +void halUsbSendString(char string[], unsigned char length) +{ + volatile unsigned char i; + for (i=0; i < length; i++) + halUsbSendChar(string[i]); +} + +// provide putchar used by printf +int putchar(int c){ + halUsbSendChar(c); + return 1; +} \ No newline at end of file diff --git a/platforms/msp430f229lp-cc2564b/firmware/hal_usb.h b/platforms/msp430f229lp-cc2564b/firmware/hal_usb.h new file mode 100755 index 000000000..f2cca4ee1 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/firmware/hal_usb.h @@ -0,0 +1,26 @@ +/******************************************************************************* + @file hal_usb.h + + Copyright 2008 Texas Instruments, Inc. +***************************************************************************/ +#ifndef HAL_USB_H +#define HAL_USB_H + + +#define USB_PORT_OUT P4OUT +#define USB_PORT_SEL P4SEL +#define USB_PORT_DIR P4DIR +#define USB_PORT_REN P4REN +#define USB_PIN_TXD BIT4 +#define USB_PIN_RXD BIT5 + +/*------------------------------------------------------------- + * Function Prototypes + * ------------------------------------------------------------*/ +void halUsbInit(void); +void halUsbShutDown(void); +void halUsbSendChar(char character); +void halUsbSendString(char string[], unsigned char length); +char halUsbRecvChar(); + +#endif diff --git a/platforms/msp430f229lp-cc2564b/src/hal_cpu.c b/platforms/msp430f229lp-cc2564b/src/hal_cpu.c new file mode 100644 index 000000000..1112a278f --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/src/hal_cpu.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * hal_cpu.c + * + * Implementation for MSP430 Experimenter board using low power mode 0/3 + * + */ + +#include + +#include "hal_board.h" +#include "hal_compat.h" + +#include + +static uint8_t low_power_mode_for_sleep = LPM0_bits; + +void hal_cpu_disable_irqs(){ + + // LED off + LED1_OUT &= ~LED1_PIN; + + // disable irq + __bic_SR_register(GIE); +} + +void hal_cpu_enable_irqs(){ + + // enable irq + __bis_SR_register(GIE); + + // LED on + LED1_OUT |= LED1_PIN; +} + +void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled){ + if (enabled){ + LED2_OUT |= LED2_PIN; + low_power_mode_for_sleep = LPM0_bits; + return; + } + LED2_OUT &= ~LED2_PIN; + low_power_mode_for_sleep = LPM3_bits; +} + +void hal_cpu_enable_irqs_and_sleep(){ + + // enable irq and enter lpm0 + __bis_SR_register(low_power_mode_for_sleep + GIE); + + // LED on + P1OUT |= 1; + +} + + diff --git a/platforms/msp430f229lp-cc2564b/src/hal_tick.c b/platforms/msp430f229lp-cc2564b/src/hal_tick.c new file mode 100644 index 000000000..a40d7dcc8 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/src/hal_tick.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * hal_tick.c + * + * Implementation for MSP430 Experimenter board using 250 ms ticks provided by Timer A1 + * + */ + +#include +#include +#include "hal_compat.h" + +#include + +static void dummy_handler(void){}; + +static void (*tick_handler)(void) = &dummy_handler; + +// Auxillary Clock (ACLK) = 32768 hz +// 8192 ticks = 1/4 second + +#define TIMER_COUNTDOWN 8192 + +void hal_tick_init(void){ + TA1CCTL0 = CCIE; // CCR0 interrupt enabled + TA1CTL = TASSEL_1 | MC_2 | TACLR; // use ACLK (32768), contmode, clear TAR + TA1CCR0 = TIMER_COUNTDOWN; // -> 1/4 s +} + +void hal_tick_set_handler(void (*handler)(void)){ + if (handler == NULL){ + tick_handler = &dummy_handler; + return; + } + tick_handler = handler; +} + +int hal_tick_get_tick_period_in_ms(void){ + return 250; +} + +// Timer A1 interrupt service routine +#ifdef __GNUC__ +__attribute__((interrupt(TIMER1_A0_VECTOR))) +#endif +#ifdef __IAR_SYSTEMS_ICC__ +#pragma vector=TIMER1_A0_VECTOR +__interrupt +#endif +void timerA0ISR(void){ + TA1CCR0 += TIMER_COUNTDOWN; + (*tick_handler)(); + + // force exit low power mode + __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU +} diff --git a/platforms/msp430f229lp-cc2564b/src/hal_uart_dma.c b/platforms/msp430f229lp-cc2564b/src/hal_uart_dma.c new file mode 100755 index 000000000..2e41ee818 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/src/hal_uart_dma.c @@ -0,0 +1,344 @@ +/** + * @file hal_bt.c + ***************************************************************************/ +#include + +#include +#include "hal_compat.h" + +#include + +extern void hal_cpu_set_uart_needed_during_sleep(uint8_t enabled); + +// debugging only +// #include + + +// RXD 3.4 +// TXD 3.3 +#define BT_PORT_OUT P3OUT +#define BT_PORT_SEL P3SEL +#define BT_PORT_DIR P3DIR +#define BT_PORT_REN P3REN +#define BT_PIN_TXD BIT3 +#define BT_PIN_RXD BIT4 + +// RTS P2.3 +#define RTS_SEL P2SEL +#define RTS_OUT P2OUT +#define RTS_DIR P2DIR +#define RTS_PIN BIT3 + +// CTS P8.1 +#define CTS_SEL P8SEL +#define CTS_OUT P8OUT +#define CTS_DIR P8DIR +#define CTS_PIN BIT1 + +// N_SHUTDOWN P4.1 +#define N_SHUTDOWN_SEL P4SEL +#define N_SHUTDOWN_OUT P4OUT +#define N_SHUTDOWN_DIR P4DIR +#define N_SHUTDOWN_PIN BIT1 + +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 + RTS_SEL &= ~RTS_PIN; // = 0 - I/O + RTS_DIR |= RTS_PIN; // = 1 - Output + RTS_OUT |= RTS_PIN; // = 1 - RTS high -> stop + + // set BT CTS + CTS_SEL &= ~CTS_PIN; // = 0 - I/O + CTS_DIR &= ~CTS_PIN; // = 0 - Input P1DIR |= BIT4; // RTS + + // set BT SHUTDOWN to 1 (active low) + N_SHUTDOWN_SEL &= ~N_SHUTDOWN_PIN; // = 0 - I/O + N_SHUTDOWN_DIR |= N_SHUTDOWN_PIN; // = 1 - Output + N_SHUTDOWN_OUT |= N_SHUTDOWN_PIN; // = 1 - Active low -> ok + + // wait for Bluetooth to power up properly after providing 32khz clock + waitAboutOneSecond(); + + UCA0CTL1 |= UCSWRST; //Reset State + UCA0CTL0 = UCMODE_0; + + UCA0CTL0 &= ~UC7BIT; // 8bit char + UCA0CTL1 |= UCSSEL_2; + + UCA0CTL1 &= ~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; + + UCA0CTL1 |= UCSWRST; //Reset State + + switch (baud){ + + case 4000000: + UCA0BR0 = 2; + UCA0BR1 = 0; + UCA0MCTL= 0 << 1; // + 0.000 + break; + + case 3000000: + UCA0BR0 = 3; + UCA0BR1 = 0; + UCA0MCTL= 3 << 1; // + 0.375 + break; + + case 2400000: + UCA0BR0 = 6; + UCA0BR1 = 0; + UCA0MCTL= 5 << 1; // + 0.625 + break; + + case 2000000: + UCA0BR0 = 8; + UCA0BR1 = 0; + UCA0MCTL= 0 << 1; // + 0.000 + break; + + case 1000000: + UCA0BR0 = 16; + UCA0BR1 = 0; + UCA0MCTL= 0 << 1; // + 0.000 + break; + + case 921600: + UCA0BR0 = 17; + UCA0BR1 = 0; + UCA0MCTL= 7 << 1; // 3 << 1; // + 0.375 + break; + + case 115200: + UCA0BR0 = 138; // from family user guide + UCA0BR1 = 0; + UCA0MCTL= 7 << 1; // + 0.875 + break; + + case 57600: + UCA0BR0 = 21; + UCA0BR1 = 1; + UCA0MCTL= 7 << 1; // + 0.875 + break; + + default: + result = -1; + break; + } + + UCA0CTL1 &= ~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)){ +#ifdef HAVE_CTS_IRQ + if (the_irq_handler){ + P8IFG = 0; // no IRQ pending + P8IV = 0; // no IRQ pending + P8IES &= ~BIT1; // IRQ on 0->1 transition + P8IE |= BIT1; // enable IRQ for P8.1 + cts_irq_handler = the_irq_handler; + return; + } + + P8IE &= ~BIT1; + cts_irq_handler = dummy_handler; +#endif +} + +/**********************************************************************/ +/** + * @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) { + + UCA0IE &= ~(UCRXIE | UCTXIE); + UCA0CTL1 = 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); + + UCA0IE &= ~UCTXIE ; // disable TX interrupts + + tx_buffer_ptr = (uint8_t *) data; + bytes_to_write = len; + + UCA0IE |= UCTXIE; // enable TX interrupts +} + +static inline void hal_uart_dma_enable_rx(void){ + RTS_OUT &= ~ RTS_PIN; // = 0 - RTS low -> ok +} + +static inline void hal_uart_dma_disable_rx(void){ + RTS_OUT |= RTS_PIN; // = 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){ + + UCA0IE &= ~UCRXIE ; // disable RX interrupts + + rx_buffer_ptr = buffer; + bytes_to_read = len; + + UCA0IE |= 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_A0_VECTOR))) +#endif +#ifdef __IAR_SYSTEMS_ICC__ +#pragma vector=USCI_A0_VECTOR +__interrupt +#endif +void usbRxTxISR(void){ + + // find reason + switch (UCA0IV){ + + case 2: // RXIFG + if (bytes_to_read == 0) { + hal_uart_dma_disable_rx(); + UCA0IE &= ~UCRXIE ; // disable RX interrupts + return; + } + *rx_buffer_ptr = UCA0RXBUF; + ++rx_buffer_ptr; + --bytes_to_read; + if (bytes_to_read > 0) { + return; + } + P1OUT |= BIT4; // = 1 - RTS high -> stop + UCA0IE &= ~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){ + UCA0IE &= ~UCTXIE ; // disable TX interrupts + return; + } + UCA0TXBUF = *tx_buffer_ptr; + ++tx_buffer_ptr; + --bytes_to_write; + + if (bytes_to_write > 0) { + return; + } + + UCA0IE &= ~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 +#ifdef HAVE_CTS_IRQ +// TODO: there's no PORT8_VECTOR, but configuration seems possible + +extern void ehcill_handle(uint8_t action); +#define EHCILL_CTS_SIGNAL 0x034 + +#ifdef __GNUC__ +__attribute__((interrupt(POERT1_VECTOR))) +#endif +#ifdef __IAR_SYSTEMS_ICC__ +#pragma vector=PORT1_VECTOR +__interrupt +#endif +void ctsISR(void){ + P1IV = 0; + (*cts_irq_handler)(); +} +#endif + diff --git a/platforms/msp430f229lp-cc2564b/src/main.c b/platforms/msp430f229lp-cc2564b/src/main.c new file mode 100644 index 000000000..af6c34b36 --- /dev/null +++ b/platforms/msp430f229lp-cc2564b/src/main.c @@ -0,0 +1,85 @@ +// ***************************************************************************** +// +// main.c for msp430f5529-cc256x +// +// ***************************************************************************** + +#include +#include +#include +#include + +#include + +#include "bt_control_cc256x.h" +#include "hal_board.h" +#include "hal_compat.h" +#include "hal_usb.h" + +#include +#include +#include + +#include "hci.h" +#include "hci_dump.h" +#include "btstack_memory.h" +#include "remote_device_db.h" +#include "btstack-config.h" + +static void hw_setup(){ + + // stop watchdog timer + WDTCTL = WDTPW + WDTHOLD; + + //Initialize clock and peripherals + halBoardInit(); + halBoardStartXT1(); + halBoardSetSystemClock(SYSCLK_16MHZ); + + // // init debug UART + halUsbInit(); + + hal_tick_init(); + + /// init LEDs + LED1_DIR |= LED1_PIN; + LED2_DIR |= LED2_PIN; + + // ready - enable irq used in h4 task + __enable_interrupt(); +} + +static void btstack_setup(){ + + hci_dump_open(NULL, HCI_DUMP_STDOUT); + + /// GET STARTED with BTstack /// + btstack_memory_init(); + run_loop_init(RUN_LOOP_EMBEDDED); + + // init HCI + hci_transport_t * transport = hci_transport_h4_dma_instance(); + bt_control_t * control = bt_control_cc256x_instance(); + hci_uart_config_t * config = hci_uart_config_cc256x_instance(); + remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory; + hci_init(transport, config, control, remote_db); + + // use eHCILL + // bt_control_cc256x_enable_ehcill(1); +} + +int btstack_main(int argc, const char * argv[]); + +// main +int main(void){ + + hw_setup(); + + printf("Hardware setup done\n"); + + btstack_setup(); + btstack_main(0, NULL); + // happy compiler! + return 0; +} +