mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-24 13:43:38 +00:00
add in alpha Bluetooth code
This commit is contained in:
parent
69deacbacd
commit
d901374d9a
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
217
platforms/stm32-f103rb-nucleo/gap_inquiry.c
Normal file
217
platforms/stm32-f103rb-nucleo/gap_inquiry.c
Normal 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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user