started work on msp430f5529 + cc256x port

This commit is contained in:
matthias.ringwald@gmail.com 2014-11-15 23:07:12 +00:00
parent 8247341c6a
commit c8049d01b4
11 changed files with 1332 additions and 0 deletions

View File

@ -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 $^"

View File

@ -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

View File

@ -0,0 +1,66 @@
// *****************************************************************************
//
// led_counter demo - uses the BTstack run loop to blink an LED
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430.h>
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include "btstack_memory.h"
#include <btstack/run_loop.h>
#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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1,98 @@
/**
* @file hal_usb.c
*
* Copyright 2008 Texas Instruments, Inc.
***************************************************************************/
#include <msp430.h>
#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;
}

View File

@ -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

View File

@ -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 <btstack/hal_cpu.h>
#include "hal_board.h"
#include "hal_compat.h"
#include <msp430.h>
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;
}

View File

@ -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 <msp430.h>
#include <stdlib.h>
#include "hal_compat.h"
#include <btstack/hal_tick.h>
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
}

View File

@ -0,0 +1,344 @@
/**
* @file hal_bt.c
***************************************************************************/
#include <stdint.h>
#include <msp430.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>
// 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

View File

@ -0,0 +1,85 @@
// *****************************************************************************
//
// main.c for msp430f5529-cc256x
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <msp430.h>
#include "bt_control_cc256x.h"
#include "hal_board.h"
#include "hal_compat.h"
#include "hal_usb.h"
#include <btstack/run_loop.h>
#include <btstack/hal_tick.h>
#include <btstack/hal_cpu.h>
#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;
}