add in alpha Bluetooth code

This commit is contained in:
matthias.ringwald@gmail.com 2014-09-29 21:08:37 +00:00
parent 69deacbacd
commit d901374d9a
4 changed files with 354 additions and 17 deletions

View File

@ -2,7 +2,8 @@
# Makefile for STM32-F103RB Nucleo board with CC256x Bluetooth modules
#
BINARY=led_counter
# BINARY=led_counter
BINARY=gap_inquiry
OPENCM3_DIR = libopencm3
LDSCRIPT = stm32f1-nucleo.ld
@ -16,13 +17,33 @@ CORE = \
${BTSTACK_ROOT}/src/run_loop.c \
${BTSTACK_ROOT}/src/run_loop_embedded.c
COMMON = \
${BTSTACK_ROOT}/chipset-cc256x/bt_control_cc256x.c \
${BTSTACK_ROOT}/chipset-cc256x/bluetooth_init_cc2560B_1.0_BT_Spec_4.1.c \
${BTSTACK_ROOT}/src/hci.c \
${BTSTACK_ROOT}/src/hci_cmds.c \
${BTSTACK_ROOT}/src/hci_dump.c \
${BTSTACK_ROOT}/src/hci_transport_h4_ehcill_dma.c \
${BTSTACK_ROOT}/src/l2cap.c \
${BTSTACK_ROOT}/src/l2cap_signaling.c \
${BTSTACK_ROOT}/src/remote_device_db_memory.c \
${BTSTACK_ROOT}/src/rfcomm.c \
${BTSTACK_ROOT}/src/sdp.c \
${BTSTACK_ROOT}/src/sdp_util.c \
${BTSTACK_ROOT}/src/utils.c \
${BTSTACK_ROOT}/src/sdp_parser.c \
${BTSTACK_ROOT}/src/sdp_client.c \
${BTSTACK_ROOT}/src/sdp_query_util.c \
${BTSTACK_ROOT}/src/sdp_query_rfcomm.c \
CORE_OBJ = $(CORE:.c=.o)
COMMON_OBJ = $(COMMON:.c=.o)
OBJS += $(CORE_OBJ)
OBJS += $(CORE_OBJ) $(COMMON_OBJ)
CFLAGS = -I. -I$(BTSTACK_ROOT)/include -I$(BTSTACK_ROOT)/src
CFLAGS = -I. -I$(BTSTACK_ROOT)/include -I$(BTSTACK_ROOT)/src -I$(BTSTACK_ROOT)/chipset-cc256x
examples: libopencm3/lib/libopencm3_stm32f1.a led_counter.elf
examples: libopencm3/lib/libopencm3_stm32f1.a $(BINARY).elf
include libopencm3.stm32f1.mk

View File

@ -12,9 +12,8 @@ Configuration:
- Bluetooth: USART3 with Hardware Flowcontrol. TX PB10, RX PB11, CTS PB13 (in), RTS PB14 (out), N_SHUTDOWN PB15
TODO:
- figure out how to compile multiple examples with single Makefile/folder
- implement hal_uart_dma.h
- implement hal_uart_dma.h using DMA (fallback: regular UART)
- implement hal_cpu.h
- create and implement hal_led.h
- figure out how to compile multiple examples with single Makefile/folder
- extract classic and le examples into example/embedded
- use examples from BTSTACK_ROOT/example/embedded directly

View File

@ -0,0 +1,217 @@
//*****************************************************************************
//
// minimal setup for HCI code
//
//*****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bt_control_cc256x.h"
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
#include "hci.h"
#include "btstack_memory.h"
#include "remote_device_db.h"
#include "btstack-config.h"
int btstack_main(void);
#define MAX_DEVICES 10
enum DEVICE_STATE { REMOTE_NAME_REQUEST, REMOTE_NAME_INQUIRED, REMOTE_NAME_FETCHED };
struct device {
bd_addr_t address;
uint16_t clockOffset;
uint32_t classOfDevice;
uint8_t pageScanRepetitionMode;
uint8_t rssi;
enum DEVICE_STATE state;
};
#define INQUIRY_INTERVAL 5
struct device devices[MAX_DEVICES];
int deviceCount = 0;
enum STATE {INIT, W4_INQUIRY_MODE_COMPLETE, ACTIVE} ;
enum STATE state = INIT;
int getDeviceIndexForAddress( bd_addr_t addr){
int j;
for (j=0; j< deviceCount; j++){
if (BD_ADDR_CMP(addr, devices[j].address) == 0){
return j;
}
}
return -1;
}
void start_scan(void){
printf("Starting inquiry scan..\n");
hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
}
int has_more_remote_name_requests(void){
int i;
for (i=0;i<deviceCount;i++) {
if (devices[i].state == REMOTE_NAME_REQUEST) return 1;
}
return 0;
}
void do_next_remote_name_request(void){
int i;
for (i=0;i<deviceCount;i++) {
// remote name request
if (devices[i].state == REMOTE_NAME_REQUEST){
devices[i].state = REMOTE_NAME_INQUIRED;
printf("Get remote name of %s...\n", bd_addr_to_str(devices[i].address));
hci_send_cmd(&hci_remote_name_request, devices[i].address,
devices[i].pageScanRepetitionMode, 0, devices[i].clockOffset | 0x8000);
return;
}
}
}
static void continue_remote_names(){
if (has_more_remote_name_requests()){
do_next_remote_name_request();
return;
}
start_scan();
}
static void packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
bd_addr_t addr;
int i;
int numResponses;
// printf("packet_handler: pt: 0x%02x, packet[0]: 0x%02x\n", packet_type, packet[0]);
if (packet_type != HCI_EVENT_PACKET) return;
uint8_t event = packet[0];
switch(state){
case INIT:
if (packet[2] == HCI_STATE_WORKING) {
hci_send_cmd(&hci_write_inquiry_mode, 0x01); // with RSSI
state = W4_INQUIRY_MODE_COMPLETE;
}
break;
case W4_INQUIRY_MODE_COMPLETE:
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
start_scan();
state = ACTIVE;
}
break;
case ACTIVE:
switch(event){
case HCI_EVENT_INQUIRY_RESULT:
case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:{
numResponses = packet[2];
int offset = 3;
for (i=0; i<numResponses && deviceCount < MAX_DEVICES;i++){
bt_flip_addr(addr, &packet[offset]);
offset =+ 6;
int index = getDeviceIndexForAddress(addr);
if (index >= 0) continue; // already in our list
memcpy(devices[deviceCount].address, addr, 6);
devices[deviceCount].pageScanRepetitionMode = packet[offset];
offset += 1;
if (event == HCI_EVENT_INQUIRY_RESULT){
offset += 2; // Reserved + Reserved
devices[deviceCount].classOfDevice = READ_BT_24(packet, offset);
offset += 3;
devices[deviceCount].clockOffset = READ_BT_16(packet, offset) & 0x7fff;
offset += 2;
devices[deviceCount].rssi = 0;
} else {
offset += 1; // Reserved
devices[deviceCount].classOfDevice = READ_BT_24(packet, offset);
offset += 3;
devices[deviceCount].clockOffset = READ_BT_16(packet, offset) & 0x7fff;
offset += 2;
devices[deviceCount].rssi = packet[offset];
offset += 1;
}
devices[deviceCount].state = REMOTE_NAME_REQUEST;
printf("Device found: %s with COD: 0x%06x, pageScan %d, clock offset 0x%04x, rssi 0x%02x\n", bd_addr_to_str(addr),
devices[deviceCount].classOfDevice, devices[deviceCount].pageScanRepetitionMode,
devices[deviceCount].clockOffset, devices[deviceCount].rssi);
deviceCount++;
}
break;
}
case HCI_EVENT_INQUIRY_COMPLETE:
for (i=0;i<deviceCount;i++) {
// retry remote name request
if (devices[i].state == REMOTE_NAME_INQUIRED)
devices[i].state = REMOTE_NAME_REQUEST;
}
continue_remote_names();
break;
case BTSTACK_EVENT_REMOTE_NAME_CACHED:
bt_flip_addr(addr, &packet[3]);
printf("Cached remote name for %s: '%s'\n", bd_addr_to_str(addr), &packet[9]);
break;
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
bt_flip_addr(addr, &packet[3]);
int index = getDeviceIndexForAddress(addr);
if (index >= 0) {
if (packet[2] == 0) {
printf("Name: '%s'\n", &packet[9]);
devices[index].state = REMOTE_NAME_FETCHED;
} else {
printf("Failed to get name: page timeout\n");
}
}
continue_remote_names();
break;
default:
break;
}
break;
default:
break;
}
}
// main == setup
int btstack_main(void)
{
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);
hci_register_packet_handler(packet_handler);
// turn on!
hci_power_control(HCI_POWER_ON);
// go!
run_loop_execute();
// happy compiler!
return 0;
}

View File

@ -8,6 +8,8 @@
#include <errno.h>
#include <unistd.h>
#include <btstack/run_loop.h>
// Configuration
// LED2 on PA5
// Debug: USART2, TX on PA2
@ -19,6 +21,8 @@
// btstack code starts there
void btstack_main(void);
static void bluetooth_power_cycle(void);
// hal_tick.h inmplementation
#include <btstack/hal_tick.h>
@ -72,6 +76,59 @@ void hal_led_toggle(void){
gpio_toggle(GPIOA, GPIO_LED2);
}
// hal_uart_dma.c implementation
#include <btstack/hal_uart_dma.h>
// 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;
void hal_uart_dma_init(void){
bluetooth_power_cycle();
}
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)){
// TODO: enable/disable interrupt
cts_irq_handler = the_irq_handler;
}
int hal_uart_dma_set_baud(uint32_t baud){
usart_disable(USART3);
usart_set_baudrate(USART3, baud);
usart_enable(USART3);
}
void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t length){
// TODO: use DMA for this
printf("TX: ");
while (length){
printf("%02x ", *buffer);
usart_send_blocking(USART3, *buffer);
buffer++;
length--;
}
printf("\n");
(*tx_done_handler)();
}
void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){
// TODO: use DMA for this
(void) buffer;
(void) len;
}
void hal_uart_dma_set_sleep(uint8_t sleep){
// TODO:
(void) sleep;
}
/**
* Use USART_CONSOLE as a console.
* This is a syscall for newlib
@ -81,8 +138,7 @@ void hal_led_toggle(void){
* @return
*/
int _write(int file, char *ptr, int len);
int _write(int file, char *ptr, int len)
{
int _write(int file, char *ptr, int len){
int i;
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
@ -98,8 +154,7 @@ int _write(int file, char *ptr, int len)
return -1;
}
static void clock_setup(void)
{
static void clock_setup(void){
/* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1 + USART2. */
/* needs to be done before initializing other peripherals */
rcc_periph_clock_enable(RCC_GPIOA);
@ -108,15 +163,12 @@ static void clock_setup(void)
rcc_periph_clock_enable(RCC_USART3);
}
static void gpio_setup(void)
{
static void gpio_setup(void){
/* Set GPIO5 (in GPIO port A) to 'output push-pull'. [LED] */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_LED2);
}
void usart_setup(void);
void usart_setup(void)
{
static void usart_setup(void){
/* Setup GPIO pin GPIO_USART2_TX/GPIO2 on GPIO port A for transmit. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
@ -132,12 +184,60 @@ void usart_setup(void)
usart_enable(USART2);
}
static void bluetooth_setup(void){
printf("\nBluetooth starting...\n");
// n_shutdown as output
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,GPIO_BT_N_SHUTDOWN);
// tx output
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART3_TX);
// rts output
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART3_RTS);
// rx input
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART3_RX);
// cts as input
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART3_CTS);
/* Setup UART parameters. */
usart_set_baudrate(USART3, 115200);
usart_set_databits(USART3, 8);
usart_set_stopbits(USART3, USART_STOPBITS_1);
usart_set_mode(USART3, USART_MODE_TX_RX);
usart_set_parity(USART3, USART_PARITY_NONE);
usart_set_flow_control(USART3, USART_FLOWCONTROL_RTS_CTS);
/* Finally enable the USART. */
usart_enable(USART3);
}
// reset Bluetooth using n_shutdown
static void msleep(uint32_t delay)
{
uint32_t wake = embedded_get_ticks() + delay;
while (wake > embedded_get_ticks());
}
static void bluetooth_power_cycle(void){
printf("n_shutdown low\n");
gpio_clear(GPIOA, GPIO_LED2);
gpio_clear(GPIOB, GPIO_BT_N_SHUTDOWN);
msleep(1000);
printf("n_shutdown high\n");
gpio_set(GPIOA, GPIO_LED2);
gpio_set(GPIOB, GPIO_BT_N_SHUTDOWN);
msleep(1000);
printf("n_shutdown toggling down\n");
}
int main(void)
{
clock_setup();
gpio_setup();
usart_setup();
hal_tick_init();
usart_setup();
bluetooth_setup();
// hand over to btstack embedded code
btstack_main();