/* ******************************************************************************/ /* DriverLib Includes */ #include "driverlib.h" /* Standard Includes */ #include #include #include #include #include "btstack_config.h" #include "bluetooth_company_id.h" #include "btstack_chipset_cc256x.h" #include "btstack_defines.h" #include "btstack_event.h" #include "btstack_debug.h" #include "btstack_memory.h" #include "btstack_tlv.h" #include "btstack_run_loop.h" #include "btstack_run_loop_embedded.h" #include "hci_dump.h" #include "btstack_tlv_flash_bank.h" #include "hal_flash_bank_msp432.h" #include "classic/btstack_link_key_db_tlv.h" #include "ble/le_device_db_tlv.h" static void delay_ms(uint32_t ms); static hci_transport_config_uart_t config = { HCI_TRANSPORT_CONFIG_UART, 115200, 3000000, // main baudrate 1, // flow control NULL, }; static hal_flash_bank_msp432_t hal_flash_bank_context; static btstack_tlv_flash_bank_t btstack_tlv_flash_bank_context; #ifndef ENABLE_SEGGER_RTT /** * Use USART_CONSOLE as a console. * This is a syscall for newlib * @param file * @param ptr * @param len * @return */ #include #include #include int _write(int file, char *ptr, int len); int _write(int file, char *ptr, int len){ uint8_t cr = '\r'; int i; if (file == STDOUT_FILENO || file == STDERR_FILENO) { for (i = 0; i < len; i++) { if (ptr[i] == '\n') { HAL_UART_Transmit( &huart2, &cr, 1, HAL_MAX_DELAY ); } HAL_UART_Transmit( &huart2, (uint8_t *) &ptr[i], 1, HAL_MAX_DELAY ); } return i; } errno = EIO; return -1; } #endif int _read(int file, char * ptr, int len){ UNUSED(file); UNUSED(ptr); UNUSED(len); return -1; } int _close(int file){ UNUSED(file); return -1; } int _isatty(int file){ UNUSED(file); return -1; } int _lseek(int file){ UNUSED(file); return -1; } int _fstat(int file){ UNUSED(file); return -1; } // end of bss, start of heap extern int _end; void * _sbrk(int incr){ static unsigned char *heap = NULL; unsigned char *prev_heap; if (heap == NULL) { heap = (unsigned char *)&_end; } prev_heap = heap; heap += incr; return prev_heap; } void abort(void){ btstack_assert(false); while (1); } #ifdef ENABLE_SEGGER_RTT #include "SEGGER_RTT.h" int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); // gcc/clang map printf to puts or putchar for printf("...\n"), or printf("%c", c) respectively int puts(const char * s){ SEGGER_RTT_WriteString(0, s); SEGGER_RTT_PutChar(0, '\n'); } int putchar(int c){ SEGGER_RTT_PutChar(0, c); } int printf(const char * format, ...){ va_list argptr; va_start(argptr, format); SEGGER_RTT_vprintf(0, format, &argptr); va_end(argptr); } int vprintf(const char * format, va_list argptr){ SEGGER_RTT_vprintf(0, format, &argptr); } #endif // HAL CPU #include "hal_cpu.h" void hal_cpu_disable_irqs(void){ __disable_irq(); } void hal_cpu_enable_irqs(void){ __enable_irq(); } void hal_cpu_enable_irqs_and_sleep(void){ __enable_irq(); __asm__("wfe"); // go to sleep if event flag isn't set. if set, just clear it. IRQs set event flag } // HAL LED #include "hal_led.h" void hal_led_toggle(void){ static bool on = false; if (on){ on = false; GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0); } else { on = true; GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN0); } } // HAL UART DMA #include "hal_uart_dma.h" // DMA Control Table // 8 channels are implemented => 16 channel control data structures (a 16 bytes) are needed // GCC __attribute__ ((aligned (256))) static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[16]; // RX Ping Pong Buffer - similar to circular buffer on other MCUs #define HAL_DMA_RX_BUFFER_SIZE 64 static uint8_t hal_dma_rx_ping_pong_buffer[2 * HAL_DMA_RX_BUFFER_SIZE]; // active buffer and position to read from static uint8_t hal_dma_rx_active_buffer = 0; static uint16_t hal_dma_rx_offset; // 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); static void (*tx_done_handler)(void); // #define BLUETOOTH_DEBUG_PORT GPIO_PORT_P5 // #define BLUETOOTH_DEBUG_PIN GPIO_PIN0 #define BLUETOOTH_TX_PORT GPIO_PORT_P3 #define BLUETOOTH_TX_PIN GPIO_PIN2 #define BLUETOOTH_RX_PORT GPIO_PORT_P3 #define BLUETOOTH_RX_PIN GPIO_PIN3 #if 0 // BOOST-CC2564MODA (CC2564B BoosterPack) #define BLUETOOTH_RTS_PORT GPIO_PORT_P6 #define BLUETOOTH_RTS_PIN GPIO_PIN6 #define BLUETOOTH_CTS_PORT GPIO_PORT_P5 #define BLUETOOTH_CTS_PIN GPIO_PIN6 #define BLUETOOTH_nSHUTDOWN_PORT GPIO_PORT_P2 #define BLUETOOTH_nSHUTDOWN_PIN GPIO_PIN5 #else // EM Wireless BoosterPack with CC256x module #define BLUETOOTH_RTS_PORT GPIO_PORT_P3 #define BLUETOOTH_RTS_PIN GPIO_PIN6 #define BLUETOOTH_CTS_PORT GPIO_PORT_P5 #define BLUETOOTH_CTS_PIN GPIO_PIN2 #define BLUETOOTH_nSHUTDOWN_PORT GPIO_PORT_P6 #define BLUETOOTH_nSHUTDOWN_PIN GPIO_PIN4 #endif /* UART Configuration Parameter. These are the configuration parameters to * make the eUSCI A UART module to operate with a 115200 baud rate. These * values were calculated using the online calculator that TI provides * at: * http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html */ static eUSCI_UART_ConfigV1 uartConfig = { EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 0 , // BRDIV (template) 0, // UCxBRF (template) 0 , // UCxBRS (template) EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // MSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode: normal 0, // Oversampling (template) EUSCI_A_UART_8_BIT_LEN, // 8 bit }; // table static struct baudrate_config { uint32_t baudrate; uint8_t clock_prescalar; uint8_t first_mod_reg; uint8_t second_mod_reg; uint8_t oversampling; } baudrate_configs[] = { // Config for 48 Mhz { 57600, 52, 1, 37, 1}, { 115200, 26, 1, 111, 1}, { 230400, 13, 0, 37, 1}, { 460800, 6, 8, 32, 1}, { 921600, 3, 4, 2, 1}, { 1000000, 3, 0, 0, 1}, { 2000000, 1, 8, 0, 1}, { 3000000, 1, 0, 0, 1}, { 4000000, 12, 0, 0, 0}, }; #ifdef TEST_LOOPBACK static uint8_t test_tx[16]; static uint8_t test_rx[16]; static uint8_t test_rx_flag; static void test_tx_complete(void){ } static void test_rx_complete(void){ test_rx_flag = 1; } #endif // return true if ok static bool hal_uart_dma_config(uint32_t baud){ int index = -1; int i; for (i=0;iBRW = config->clockPrescalar; EUSCI_A_CMSIS(moduleInstance)->MCTLW = ((config->secondModReg << 8) + (config->firstModReg << 4) + config->overSampling); MAP_UART_enableModule(EUSCI_A2_BASE); return 0; } void hal_uart_dma_set_sleep(uint8_t sleep){ UNUSED(sleep); } void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){ UNUSED(the_irq_handler); } 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_send_block(const uint8_t * data, uint16_t len){ MAP_DMA_setChannelTransfer(DMA_CH4_EUSCIA2TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (uint8_t *) data, (void *) MAP_UART_getTransmitBufferAddressForDMA(EUSCI_A2_BASE), len); MAP_DMA_enableChannel(DMA_CH4_EUSCIA2TX & 0x0F); } // int used to indicate a request for more new data void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){ rx_buffer_ptr = buffer; bytes_to_read = len; hal_cpu_disable_irqs(); hal_uart_dma_harvest(); hal_cpu_enable_irqs(); } // HAL TIME MS Implementation #include "hal_time_ms.h" static volatile uint32_t systick; void SysTick_Handler(void){ systick++; // process received data #ifdef BLUETOOTH_DEBUG_PORT MAP_GPIO_setOutputHighOnPin(BLUETOOTH_DEBUG_PIN, BLUETOOTH_DEBUG_PORT); #endif hal_uart_dma_harvest(); #ifdef BLUETOOTH_DEBUG_PORT MAP_GPIO_setOutputLowOnPin(BLUETOOTH_DEBUG_PIN, BLUETOOTH_DEBUG_PORT); #endif } static void init_systick(void){ // Configuring SysTick to trigger every ms (48 Mhz / 48000 = 1 ms) MAP_SysTick_enableModule(); MAP_SysTick_setPeriod(48000); // MAP_Interrupt_enableSleepOnIsrExit(); MAP_SysTick_enableInterrupt(); } static void delay_ms(uint32_t ms){ uint32_t delay_until = systick + ms; // assumes mcu runs fast enough to check once every ms while (systick != delay_until); } uint32_t hal_time_ms(void){ return systick; } // btstack assert void btstack_assert_failed(const char * file, uint16_t line_nr){ printf("ASSERT failed in %s, line %u\n", file, line_nr); while (1); } // main.c #include "SEGGER_RTT.h" // HAL FLASH MSP432 Configuration - use two last 4kB sectors #define HAL_FLASH_BANK_SIZE 4096 #define HAL_FLASH_BANK_0_SECTOR FLASH_SECTOR30 #define HAL_FLASH_BANK_1_SECTOR FLASH_SECTOR31 #define HAL_FLASH_BANK_0_ADDR 0x3E000 #define HAL_FLASH_BANK_1_ADDR 0x3F000 int btstack_main(const int argc, const char * argvp[]); static btstack_packet_callback_registration_t hci_event_callback_registration; static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(size); UNUSED(channel); bd_addr_t local_addr; if (packet_type != HCI_EVENT_PACKET) return; switch(hci_event_packet_get_type(packet)){ case BTSTACK_EVENT_STATE: if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; gap_local_bd_addr(local_addr); printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr)); break; case HCI_EVENT_COMMAND_COMPLETE: if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){ uint16_t manufacturer = little_endian_read_16(packet, 10); uint16_t lmp_subversion = little_endian_read_16(packet, 12); // assert manufacturer is TI if (manufacturer != BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){ printf("ERROR: Expected Bluetooth Chipset from TI but got manufacturer 0x%04x\n", manufacturer); break; } // assert correct init script is used based on expected lmp_subversion if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){ printf("Error: LMP Subversion does not match initscript!\n"); printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer"); printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n"); btstack_assert(false); break; } } break; default: break; } } int main(void) { /* Halting the Watchdog */ MAP_WDT_A_holdTimer(); init_systick(); // init led MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); hal_led_toggle(); // start with BTstack init - especially configure HCI Transport btstack_memory_init(); btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); // uncomment to enable packet logger // hci_dump_open( NULL, HCI_DUMP_STDOUT ); // init HCI hci_init(hci_transport_h4_instance(btstack_uart_block_embedded_instance()), (void*) &config); hci_set_chipset(btstack_chipset_cc256x_instance()); // setup TLV Flash Sector implementation const hal_flash_bank_t * hal_flash_bank_impl = hal_flash_bank_msp432_init_instance( &hal_flash_bank_context, HAL_FLASH_BANK_SIZE, HAL_FLASH_BANK_0_SECTOR, HAL_FLASH_BANK_1_SECTOR, HAL_FLASH_BANK_0_ADDR, HAL_FLASH_BANK_1_ADDR); const btstack_tlv_t * btstack_tlv_impl = btstack_tlv_flash_bank_init_instance( &btstack_tlv_flash_bank_context, hal_flash_bank_impl, &hal_flash_bank_context); // setup global tlv btstack_tlv_set_instance(btstack_tlv_impl, &btstack_tlv_flash_bank_context); // setup Link Key DB using TLV const btstack_link_key_db_t * btstack_link_key_db = btstack_link_key_db_tlv_get_instance(btstack_tlv_impl, &btstack_tlv_flash_bank_context); hci_set_link_key_db(btstack_link_key_db); // setup LE Device DB using TLV le_device_db_tlv_configure(btstack_tlv_impl, &btstack_tlv_flash_bank_context); // inform about BTstack state hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); // hand over to btstack embedded code btstack_main(0, NULL); // go btstack_run_loop_execute(); }