atwilc3000: new port posix-h4-atwilc3000. firmware upload ipmlemented

This commit is contained in:
Matthias Ringwald 2017-07-23 18:14:12 +02:00
parent 4eb6a35329
commit ccebdf934c
7 changed files with 587 additions and 0 deletions

View File

@ -0,0 +1,203 @@
/*
* Copyright (C) 2017 BlueKitchen GmbH
*
* 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.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH 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.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
/*
* btstack_chipset_atwilc3000.c
*
* Adapter to use atwilc3000-based chipsets with BTstack
*
*/
#define __BTSTACK_FILE__ "btstack_chipset_atwilc3000.c"
#include "btstack_config.h"
#include "btstack_chipset_atwilc3000.h"
#include "btstack_debug.h"
#include <stddef.h> /* NULL */
#include <stdio.h>
#include <string.h> /* memcpy */
#include "hci.h"
#define IRAM_START 0x80000000
// HCI commands
static const uint8_t hci_reset_command[] = { 0x01, 0x03, 0x0c, 0x00 };
static const uint8_t hci_read_local_version_information_command[] = { 0x01, 0x01, 0x10, 0x00 };
static const uint8_t hci_vendor_specific_reset_command[] = { 0x01, 0x55, 0xfc, 0x00 };
// prototypes
static void atwilc3000_w4_command_complete_reset(void);
static void atwilc3000_w4_command_complete_read_local_version_information(void);
static void atwilc3000_write_memory(void);
static void atwilc3000_vendor_specific_reset(void);
static void atwilc3000_done(void);
// globals
static void (*download_complete)(int result);
static const btstack_uart_block_t * the_uart_driver;
static int download_count;
static uint8_t event_buffer[15];
static uint8_t command_buffer[260];
static const uint8_t * fw_data;
static uint32_t fw_size;
static uint32_t fw_offset;
static void atwilc3000_send_command(const uint8_t * data, uint16_t len){
hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, (uint8_t *) &data[1], len - 1);
the_uart_driver->send_block(data, len);
}
static void atwilc3000_log_event(void){
int len = event_buffer[2] + 2;
hci_dump_packet(HCI_EVENT_PACKET, 1, &event_buffer[1], len);
}
static void atwilc3000_start(void){
// send HCI Reset
the_uart_driver->set_block_received(&atwilc3000_w4_command_complete_reset);
the_uart_driver->receive_block(&event_buffer[0], 7);
atwilc3000_send_command(&hci_reset_command[0], sizeof(hci_reset_command));
log_info("atwilc3000_start: wait for command complete for HCI Reset");
}
static void atwilc3000_w4_command_complete_reset(void){
atwilc3000_log_event();
log_info("command complete Reset");
// static uint8_t hci_event_command_complete_reset[] = { 0x04, 0x0e, 0x04, 0x01, 0x03, 0x0c, 0x0c };
// TODO: check if correct event
// send HCI Read Local Version Information
the_uart_driver->receive_block(&event_buffer[0], 15);
the_uart_driver->set_block_received(&atwilc3000_w4_command_complete_read_local_version_information);
atwilc3000_send_command(&hci_read_local_version_information_command[0], sizeof(hci_read_local_version_information_command));
log_info("atwilc3000_start: wait for command complete for HCI Read Local Version Information");
}
static void atwilc3000_w4_command_complete_read_local_version_information(void){
atwilc3000_log_event();
log_info("command complete Read Local Version Information");
uint8_t firmware_version = event_buffer[7];
log_info("Firmware version 0x%02x", firmware_version);
if (firmware_version != 0xff){
log_info("Firmware already loaded, download complete");
download_complete(0);
return;
}
log_info("Running from ROM, start firmware download");
// TODO: check if firmware download can be skipped
atwilc3000_write_memory();
}
static void atwilc3000_write_memory(void){
atwilc3000_log_event();
// done?
if (fw_offset >= fw_size){
log_info("DONE!!!");
atwilc3000_vendor_specific_reset();
return;
}
// bytes to write
log_info("Write pos %u", fw_offset);
uint16_t bytes_to_write = btstack_min((fw_size - fw_offset), (255-8));
// setup write command
command_buffer[0] = 1;
command_buffer[1] = 0x52;
command_buffer[2] = 0xfc;
command_buffer[3] = 8; // NOTE: this is in violation of the Bluetooth Specification, but documented in the Atmel-NNNNN-ATWIL_Linux_Porting_Guide
little_endian_store_32(command_buffer, 4, IRAM_START + fw_offset);
little_endian_store_32(command_buffer, 8, bytes_to_write);
memcpy(&command_buffer[12], &fw_data[fw_offset], bytes_to_write);
//
fw_offset += bytes_to_write;
// send write command
the_uart_driver->receive_block(&event_buffer[0], 7);
the_uart_driver->set_block_received(&atwilc3000_write_memory);
atwilc3000_send_command(&command_buffer[0], 12 + bytes_to_write);
}
static void atwilc3000_vendor_specific_reset(void){
// send HCI Vendor Specific Reset
// the_uart_driver->receive_block(&event_buffer[0], 7);
// the_uart_driver->set_block_received(&atwilc3000_done);
the_uart_driver->set_block_sent(&atwilc3000_done);
atwilc3000_send_command(&hci_vendor_specific_reset_command[0], sizeof(hci_vendor_specific_reset_command));
}
static void atwilc3000_done(void){
log_info("done");
download_complete(0);
}
void btstack_chipset_atwilc3000_download_firmware(const btstack_uart_block_t * uart_driver, const uint8_t * da_fw_data, uint32_t da_fw_size, void (*done)(int result)){
the_uart_driver = uart_driver;
download_complete = done;
fw_data = da_fw_data;
fw_size = da_fw_size;
fw_offset = 0;
int res = the_uart_driver->open();
if (res) {
log_error("uart_block init failed %u", res);
download_complete(res);
}
download_count = 0;
atwilc3000_start();
}
// not used currently
static const btstack_chipset_t btstack_chipset_atwilc3000 = {
"atwilc3000",
NULL, // chipset_init not used
NULL, // chipset_next_command not used
NULL, // chipset_set_baudrate_command not needed as we're connected via SPI
NULL, // chipset_set_bd_addr not provided
};
// MARK: public API
const btstack_chipset_t * btstack_chipset_atwilc3000_instance(void){
return &btstack_chipset_atwilc3000;
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* 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.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH 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.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
/*
* btstack_chipset_atwilc3000.c
*
* Adapter to use atwilc3000-based chipsets with BTstack
*
*/
#ifndef __BTSTACK_CHIPSET_ATWILC3000_H
#define __BTSTACK_CHIPSET_ATWILC3000_H
#if defined __cplusplus
extern "C" {
#endif
#include "btstack_chipset.h"
#include "btstack_uart_block.h"
/**
* @brief get chipset instance
*/
const btstack_chipset_t * btstack_chipset_atwilc3000_instance(void);
/**
* @brief Download firmware via uart_driver
* @param uart_driver -- already initialized
* @param done callback. 0 = Success
*/
void btstack_chipset_atwilc3000_download_firmware(const btstack_uart_block_t * uart_driver, const uint8_t * fw, uint32_t fw_size, void (*done)(int result));
#if defined __cplusplus
}
#endif
#endif // __BTSTACK_CHIPSET_ATWILC3000_H

50
port/posix-h4-atwilc3000/.gitignore vendored Normal file
View File

@ -0,0 +1,50 @@
ancs_client_demo
ancs_client_demo.h
ble_central_test
ble_peripheral
ble_peripheral_sm_minimal
ble_peripheral_test
bluetooth_init_cc2560_2.44.c
bluetooth_init_cc2560a_2.14.c
bluetooth_init_cc2560B_1.2_BT_Spec_4.0.c
bluetooth_init_cc2564_2.14.c
bluetooth_init_cc2564B_1.2_BT_Spec_4.0.c
bnep_test
classic_test
gap_dedicated_bonding
gap_inquiry
gap_inquiry_and_bond
gap_le_advertisements
gatt_battery_query
gatt_browser
hfp_ag_demo
hfp_hf_demo
hsp_ag_demo
hsp_ag_test
hsp_hs_demo
hsp_hs_test
l2cap_test
le_counter
le_counter.h
le_streamer
le_streamer.h
led_counter
profile.h
sco_input.wav
sdp_bnep_query
sdp_general_query
sdp_rfcomm_query
sm_pairing_peripheral.h
spp_and_le_counter
spp_and_le_counter.h
spp_counter
spp_streamer
TIInit_12.10.28.c
TIInit_12.8.32.c
gatt_battery_query.h
gatt_browser.h
le_streamer_client
pbap_client_demo
sm_pairing_central
sm_pairing_peripheral

View File

@ -0,0 +1,44 @@
# Makefile for libusb based examples
BTSTACK_ROOT = ../..
CORE += \
btstack_chipset_atwilc3000.c \
wilc3000_bt_firmware.c \
btstack_link_key_db_fs.c \
btstack_run_loop_posix.c \
btstack_uart_block_posix.c \
hci_transport_h4.c \
le_device_db_fs.c \
main.c \
wav_util.c \
btstack_stdin_posix.c \
# examples
include ${BTSTACK_ROOT}/example/Makefile.inc
CFLAGS += -g -Wall -Werror \
-I$(BTSTACK_ROOT)/platform/posix \
-I$(BTSTACK_ROOT)/chipset/atwilc3000 \
-I$(BTSTACK_ROOT)/platform/embedded \
VPATH += ${BTSTACK_ROOT}/platform/posix
VPATH += ${BTSTACK_ROOT}/chipset/atwilc3000
ifeq ($(OS),Windows_NT)
LDFLAGS += -lws2_32
endif
# Command Line examples require porting to win32, so only build on other unix-ish hosts
ifneq ($(OS),Windows_NT)
EXAMPLES += ${EXAMPLES_CLI}
endif
# use pkg-config for portaudio
# CFLAGS += $(shell pkg-config portaudio-2.0 --cflags) -DHAVE_PORTAUDIO
# LDFLAGS += $(shell pkg-config portaudio-2.0 --libs)
# hard coded flags for portaudio in /usr/local/lib
# CFLAGS += -I/usr/local/include -DHAVE_PORTAUDIO
# LDFLAGS += -L/sw/lib -lportaudio -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,Carbon
all: ${EXAMPLES}

View File

@ -0,0 +1,9 @@
# POSIX H4 Port for Atmel ATWILC3000
This port allows to use the ATWILC3000 connected via UART with BTstack running on a POSIX host system.
It first downloads the hci_581_active_uart.hex firmware from the [GitHub atwilc3000/firmware](https://github.com/atwilc3000/firmware) repo, before BTstack starts up.
Please note that it does not detect if the firmware has already been downloaded, so you need to reset the ATWILC3000 before starting an example.
Tested with the official ATWILC3000 SHIELD on OS X.

View File

@ -0,0 +1,33 @@
//
// btstack_config.h for generic POSIX H4 port
//
#ifndef __BTSTACK_CONFIG
#define __BTSTACK_CONFIG
// Port related features
#define HAVE_MALLOC
#define HAVE_POSIX_FILE_IO
#define HAVE_BTSTACK_STDIN
#define HAVE_POSIX_TIME
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_HFP_WIDE_BAND_SPEECH
#define ENABLE_LE_CENTRAL
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LE_DATA_LENGTH_EXTENSION
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_SCO_OVER_HCI
#define ENABLE_SDP_DES_DUMP
// #define ENABLE_EHCILL
// BTstack configuration. buffers, sizes, ...
#define HCI_INCOMING_PRE_BUFFER_SIZE 14 // sizeof benep heade, avoid memcpy
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
#endif

View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* 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.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH 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.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#define __BTSTACK_FILE__ "main.c"
// *****************************************************************************
//
// minimal setup for HCI code
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "btstack_config.h"
#include "btstack_debug.h"
#include "btstack_event.h"
#include "btstack_link_key_db_fs.h"
#include "btstack_memory.h"
#include "btstack_run_loop.h"
#include "btstack_run_loop_posix.h"
#include "hci.h"
#include "hci_dump.h"
#include "btstack_stdin.h"
#include "btstack_chipset_atwilc3000.h"
#include "wilc3000_bt_firmware.h"
static int main_argc;
static const char ** main_argv;
static const btstack_uart_block_t * uart_driver;
static btstack_uart_config_t uart_config;
int btstack_main(int argc, const char * argv[]);
static hci_transport_config_uart_t transport_config = {
HCI_TRANSPORT_CONFIG_UART,
115200,
0, // main baudrate
0, // flow control
NULL,
};
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){
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) break;
printf("BTstack up and running.\n");
break;
default:
break;
}
}
static void sigint_handler(int param){
UNUSED(param);
printf("CTRL-C - SIGINT received, shutting down..\n");
log_info("sigint_handler: shutting down");
// reset anyway
btstack_stdin_reset();
// power down
hci_power_control(HCI_POWER_OFF);
hci_close();
log_info("Good bye, see you.\n");
exit(0);
}
static int led_state = 0;
void hal_led_toggle(void){
led_state = 1 - led_state;
printf("LED State %u\n", led_state);
}
static void phase2(int status){
if (status){
printf("Download firmware failed\n");
return;
}
printf("Phase 2: Main app\n");
// init HCI
const hci_transport_t * transport = hci_transport_h4_instance(uart_driver);
const btstack_link_key_db_t * link_key_db = btstack_link_key_db_fs_instance();
hci_init(transport, (void*) &transport_config);
hci_set_link_key_db(link_key_db);
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
// handle CTRL-c
signal(SIGINT, sigint_handler);
// setup app
btstack_main(main_argc, main_argv);
}
int main(int argc, const char * argv[]){
/// GET STARTED with BTstack ///
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
// use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT
hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_STDOUT);
// pick serial port and configure uart block driver
transport_config.device_name = "/dev/tty.usbserial-A96PXBJ7";
uart_driver = btstack_uart_block_posix_instance();
// extract UART config from transport config, but overide initial uart speed
uart_config.baudrate = 115200;
uart_config.flowcontrol = 0;
uart_config.device_name = transport_config.device_name;
uart_driver->init(&uart_config);
main_argc = argc;
main_argv = argv;
// phase #1 download firmware
printf("Phase 1: Download firmware\n");
// phase #2 start main app
btstack_chipset_atwilc3000_download_firmware(uart_driver, atwilc3000_fw_data, atwilc3000_fw_size, &phase2);
// phase2(0);
// go
btstack_run_loop_execute();
return 0;
}