Compare commits

...

1 Commits

Author SHA1 Message Date
Ta-Shun Su 0bd4b66104 version 0.2 2019-04-30 17:31:35 +08:00
9 changed files with 990 additions and 727 deletions
@@ -87,7 +87,7 @@ extern const PIN_Config BoardGpioInitTable[];
#define Board_SPI0_MISO IOID_8 /* RF1.20 */
#define Board_SPI0_MOSI IOID_9 /* RF1.18 */
#define Board_SPI0_CLK IOID_10 /* RF1.16 */
#define Board_SPI0_CSN PIN_UNASSIGNED
#define Board_SPI0_CSN IOID_11
#define Board_SPI1_MISO PIN_UNASSIGNED
#define Board_SPI1_MOSI PIN_UNASSIGNED
#define Board_SPI1_CLK PIN_UNASSIGNED
@@ -55,7 +55,7 @@ extern "C"
// includes
// ****************************************************************************
#include "hal_types.h"
#include "npi/src/inc/npi_config.h"
#include "inc/npi_config.h"
// ****************************************************************************
// defines
@@ -0,0 +1,73 @@
#ifndef _CC2650_UTIL_H_
#error "include cc2650_util.h request"
#endif
#ifndef _CC2650_MASTER_H_
#define _CC2650_MASTER_H_
#include <ti/drivers/SPI.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
#include <ti/drivers/dma/UDMACC26XX.h>
static SPI_Handle spi_handle;
static SPI_Params spi_parameter;
static SPI_Transaction spi_transaction;
static uint8_t spi_ms_value; // memory select
static uint8_t spi_instruction[32] = {0};
#define SPI_MEM_BUFFER_SIZE 256
static uint16_t not_counter = 0; // writing counter, increase when notify
static uint16_t not_offset = 0; // writing pointer, current not writing index
static void HTA_main_init() {
// SPI initial
SPI_init();
// SPI parameters initialize
SPI_Params_init(&spi_parameter);
spi_parameter.transferMode = SPI_MODE_BLOCKING;
spi_parameter.mode = SPI_MASTER;
spi_parameter.bitRate = 8000000; // 12 MHz
spi_parameter.transferTimeout = 1000;
spi_parameter.dataSize = 8;
spi_parameter.frameFormat = SPI_POL0_PHA1;
// SPI open
spi_handle = SPI_open(Board_SPI0, &spi_parameter);
}
static void HTA_main_handle_notify(uint16 length, uint8 *value) {
not_counter = (not_counter + 1) & 0xFF;
// memory select
if (not_offset + length > SPI_MEM_BUFFER_SIZE) {
spi_ms_value = (spi_ms_value > 0) ? 0 : 1;
PIN_setOutputValue(sbp_pins_handle, Board_DIO12, spi_ms_value);
PIN_setOutputValue(sbp_pins_handle, Board_RLED, spi_ms_value);
not_offset = 0;
}
// buffer
spi_instruction[0] = 0x02; // instruction write
spi_instruction[1] = (uint8_t)(not_offset & 0xFF); // instruction address
spi_instruction[2] = (uint8_t)((not_offset >> 8) & 0xFF);
memcpy(spi_instruction + 3, value, length);
not_offset += length;
// SPI transaction
spi_transaction.rxBuf = NULL;
spi_transaction.txBuf = spi_instruction;
spi_transaction.count = length + 3;
SPI_transfer(spi_handle, &spi_transaction);
// update LED state
PIN_setOutputValue(sbp_pins_handle, Board_GLED, (not_counter & 0x10) ? Board_LED_ON : Board_LED_OFF);
}
#endif // _CC2650_MASTER_H_
@@ -0,0 +1,39 @@
#ifndef _CC2650_UTIL_H_
#error "include cc2650_util.h request"
#endif
#ifndef _CC2650_RAMP_H_
#define _CC2650_RAMP_H_
#include <xdc/runtime/Timestamp.h>
#define PERIODIC_BUFFER_SIZE 20
static uint16_t ramp_data_counter = 0;
static uint8_t not_buffer[PERIODIC_BUFFER_SIZE] = {0};
void HTA_event_ramp() {
uint32_t cpu_time = Timestamp_get32();
not_buffer[0] = (uint8_t)0x00; // chip_id
not_buffer[2] = cpu_time & 0xff;
not_buffer[3] = (cpu_time >> 8) & 0xff;
not_buffer[4] = (cpu_time >> 16) & 0xff;
not_buffer[5] = (cpu_time >> 24) & 0xff;
uint16_t i = 6;
uint8_t channel = 0;
for (; i + 1 < PERIODIC_BUFFER_SIZE; i += 2) {
not_buffer[i] = (0b10110000 & channel) | (0b00001111 & (uint8_t)(ramp_data_counter >> 6));
not_buffer[i + 1] = (uint8_t)(ramp_data_counter << 2);
ramp_data_counter = (ramp_data_counter + 1) & 0xFF;
}
not_buffer[1] = i - 2;
HTA_main_handle_notify(i, not_buffer);
}
#endif // _CC2650_RAMP_H_
@@ -0,0 +1,299 @@
/*
SPI data format
::
| | 1 | 2 | 3 |
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
-----------------------------------------------------------------
| header | counter | length | data[0] |
| ............................................. | data[length-1]|
header
fix 0xFF
counter
There are head counter and tail counter which increase when notify came in.
The tail counter should be equal to the head counter, which used to mark
this data in this section has finished memcpy.
length
data length in bytes
data
notify data content
*/
#ifndef _CC2650_UTIL_H_
#error "include cc2650_util.h request"
#endif
#ifndef _CC2650_SLAVE_H_
#define _CC2650_SLAVE_H_
#include <Board.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include <ti/drivers/pin/PINCC26xx.h>
//#include "cc2650/cc2650_ramp.h"
/*
* SPI parameter and function declaration
*/
static SPI_Handle spi_handle;
static SPI_Transaction spi_transaction;
static void HTA_main_spi_callback(SPI_Handle handle, SPI_Transaction *transaction);
/*
* pin parameter, configuration and function declaration
*/
// SPI_MISO Dio 8
// SPI_MOSI Dio 9
// SPI_CLK Dio 10
// SPI_CS Dio 11
// PIN_BF Dio 12
// PIN_RQ Dio 15
// PIN_RS Dio 14
// PIN_D1 Dio 13
// PIN_D2 Dio 16
// PIN_D3 Dio 21
// PIN_D4 Dio 22
#define HTA_LED_RD IOID_6
#define HTA_LED_GN IOID_7
#define HTA_PIN_BF IOID_12
#define HTA_PIN_RS IOID_15
#define HTA_PIN_D1 IOID_4
#define HTA_PIN_D2 IOID_5
#define HTA_PIN_D3 IOID_21
#define HTA_PIN_D4 IOID_22
static PIN_State hta_pins;
static PIN_Handle hta_pins_handle;
static PIN_Config HTA_pin_config_table[] = { //
// LED
HTA_LED_RD | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
HTA_LED_GN | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
// notify when buffer is stand by to ready to be read
HTA_PIN_BF | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
// master side request to clean spi buffer, and blocking notify handle
HTA_PIN_RS | PIN_INPUT_EN | PIN_PULLDOWN | PIN_HYSTERESIS,
// debug use pin
#ifdef HTA_PIN_D1
HTA_PIN_D1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
#endif
#ifdef HTA_PIN_D2
HTA_PIN_D2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
#endif
#ifdef HTA_PIN_D3
HTA_PIN_D3 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
#endif
#ifdef HTA_PIN_D4
HTA_PIN_D4 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
#endif
PIN_TERMINATE};
/*
* machine state
*/
#define FLAG_NOTIFY 0x004 // enable during notify handle
#define FLAG_TRANSFER 0x008 // enable during spi transaction
#define FLAG_RESET 0x010
void HTA_main_pin_callback(PIN_Handle handle, PIN_Id pin);
/*
* SPI
*/
// spi buffer size
#define SPI_TX_BUFFER_SIZE 512
// the threshold size let CC2650 should prepare to setup spi transaction
#define SPI_TX_BUFFER_NOTIFY 450
// the offset let start to pad data into spi buffer
#define SPI_TX_BUFFER_START 2
static uint8_t spi_tx_buffer[SPI_TX_BUFFER_SIZE] = {0};
/**
* initialization function
*/
static void HTA_main_init() {
// SPI initial
SPI_init();
// SPI parameters initialize
SPI_Params spi_parameter;
SPI_Params_init(&spi_parameter);
spi_parameter.transferMode = SPI_MODE_CALLBACK;
spi_parameter.transferCallbackFxn = HTA_main_spi_callback;
spi_parameter.mode = SPI_SLAVE;
spi_parameter.bitRate = 4000000; // 1 MHz, 100 us
/*spi_parameter.transferTimeout = 48000000 / 1000 / 200;*/ // system tick (blocking mode)
spi_parameter.dataSize = 8;
spi_parameter.frameFormat = SPI_POL0_PHA1;
// SPI open
spi_handle = SPI_open(Board_SPI0, &spi_parameter);
// SPI partial return
// spi complete when the CS signal up, no matter whether the whole buffer are transmitted or not.
SPI_control(spi_handle, SPICC26XXDMA_RETURN_PARTIAL_ENABLE, NULL);
// pin initialize
hta_pins_handle = PIN_open(&hta_pins, HTA_pin_config_table);
PIN_registerIntCb(hta_pins_handle, HTA_main_pin_callback);
PIN_setInterrupt(hta_pins_handle, HTA_PIN_RS | PIN_IRQ_NEGEDGE);
#ifdef _CC2650_RAMP_H_
HTA_set_event_callback(HTA_PERIODIC_EVT, HTA_event_ramp);
HTA_periodic_start();
HTA_periodic_set_frequency(10000 / 7);
#endif
}
/*
* spi function
*/
static uint8_t not_counter = 0; // writing counter, increase when notify
static uint32_t not_offset = SPI_TX_BUFFER_START; // writing pointer, also indicate the length of the data in buffer
/**
* notify handle
*/
static void HTA_main_handle_notify(uint16_t length, uint8_t *value) {
// set flag
flag_enable(FLAG_NOTIFY);
#ifdef HTA_PIN_D1
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D1, 1);
#endif
// update counter
uint8_t counter = not_counter++;
// reset
if (flag_mask(FLAG_RESET)) {
flag_disable(FLAG_RESET);
not_offset = SPI_TX_BUFFER_START;
counter = not_counter = 0;
// cancel last spi
if (flag_mask(FLAG_TRANSFER)) {
SPI_transferCancel(spi_handle);
}
// reset signal
PIN_setOutputValue(hta_pins_handle, HTA_PIN_BF, 0);
flag_disable(FLAG_TRANSFER);
#ifdef HTA_PIN_D4
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D4, 0);
#endif
} else if (flag_mask(FLAG_TRANSFER)) {
#ifdef HTA_PIN_D3
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D3, 1);
#endif
goto HTA_main_handle_notify_exit;
}
// update offset
uint32_t cnt_offset = not_offset;
uint32_t nxt_offset = cnt_offset + 3 + length;
// make sure it do not over buffer
if (nxt_offset < SPI_TX_BUFFER_SIZE) {
not_offset = nxt_offset;
// localize current buffer
uint8_t *p = spi_tx_buffer + cnt_offset;
// put data into spi_tx_buffer
memcpy(p + 3, value, length);
// 0xFF (header), counter, length, [data]
*p++ = 0xFF; // SPI data header
*p++ = counter;
*p++ = length;
}
// buffer switch if buffer almost full
if (nxt_offset >= SPI_TX_BUFFER_NOTIFY) {
// set flag
flag_enable(FLAG_TRANSFER);
#ifdef HTA_PIN_D2
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D2, 1);
#endif
// add data length information
spi_tx_buffer[0] = (uint8_t)(nxt_offset & 0xFF);
spi_tx_buffer[1] = (uint8_t)((nxt_offset >> 8) & 0xFF);
// set spi transaction parameter
spi_transaction.count = SPI_TX_BUFFER_SIZE;
spi_transaction.txBuf = spi_tx_buffer;
spi_transaction.rxBuf = NULL;
// start trigger transfer
SPI_transfer(spi_handle, &spi_transaction);
// set signal
#ifdef HTA_PIN_D2
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D2, 0);
#endif
PIN_setOutputValue(hta_pins_handle, HTA_PIN_BF, 1);
PIN_setOutputValue(hta_pins_handle, HTA_LED_RD, Board_LED_ON);
}
HTA_main_handle_notify_exit:
// restore flag
flag_disable(FLAG_NOTIFY);
#ifdef HTA_PIN_D1
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D1, 0);
#endif
#ifdef HTA_PIN_D3
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D3, 0);
#endif
PIN_setOutputValue(hta_pins_handle, HTA_LED_GN, (counter & 0x20) ? Board_LED_ON : Board_LED_OFF);
}
/**
* spi callback, reset flag and signal
*/
static void HTA_main_spi_callback(SPI_Handle handle, SPI_Transaction *transaction) {
// unset signal
PIN_setOutputValue(hta_pins_handle, HTA_PIN_BF, 0);
PIN_setOutputValue(hta_pins_handle, HTA_LED_RD, Board_LED_OFF);
flag_disable(FLAG_TRANSFER);
not_offset = SPI_TX_BUFFER_START;
spi_tx_buffer[0] = 0;
spi_tx_buffer[1] = 0;
}
/**
* pin callback
*/
void HTA_main_pin_callback(PIN_Handle handle, PIN_Id pin) {
if (pin == HTA_PIN_RS) {
// reset
flag_enable(FLAG_RESET);
#ifdef HTA_PIN_D4
PIN_setOutputValue(hta_pins_handle, HTA_PIN_D4, 1);
#endif
}
}
#endif // _CC2650_SLAVE_H_
@@ -0,0 +1,189 @@
#ifndef _CC2650_UTIL_H_
#define _CC2650_UTIL_H_
#include <Board.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <xdc/runtime/Timestamp.h>
#include <xdc/runtime/Types.h>
/*
* GAP GATT Attributes
*/
static const uint8_t att_device_name[GAP_DEVICE_NAME_LEN] = "BioProController";
static void HTA_util_init() {
GGS_SetParameter(GGS_DEVICE_NAME_ATT, strlen(att_device_name), (void *)att_device_name);
}
/*
* main function declaration
*/
static void HTA_main_init();
static void HTA_main_handle_notify(uint16_t length, uint8_t *value);
/*
* event flag
*/
#define HTA_PERIODIC_EVT 0x0001
static uint16_t event_flags;
#define flag_mask(flag) ((event_flags & (flag)) != 0)
#define flag_enable(flag) \
do { \
uint8 __key = Hwi_disable(); \
event_flags |= (flag); \
Hwi_restore(__key); \
} while (0)
#define flag_disable(flag) \
do { \
uint8 __key = Hwi_disable(); \
event_flags &= ~(flag); \
Hwi_restore(__key); \
} while (0)
#define flag_notify() \
do { \
Semaphore_post(semaphore); \
} while (0)
/*
* periodic function
*/
static ICall_Semaphore semaphore;
static void HTA_periodic_start();
static void HTA_periodic_set_frequency(uint32_t frequency);
/*
* periodic function implement
*/
#ifdef PERIODIC_USE_GPTIMER
#include <ti/drivers/timer/GPTimerCC26XX.h>
static GPTimerCC26XX_Handle hTimer;
static void HTA_periodic_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
// interrupt callback code goes here. Minimize processing in interrupt.
flag_enable(HTA_PERIODIC_EVT);
flag_notify();
}
static void HTA_periodic_start() {
// parameter init
GPTimerCC26XX_Params params;
GPTimerCC26XX_Params_init(&params);
params.width = GPT_CONFIG_16BIT;
params.mode = GPT_MODE_PERIODIC_DOWN; // = GPT_TAMR_TAMR_PERIODIC | GPT_TAMR_TACDIR_DOWN | GPT_TAMR_TAMIE;
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
// init
hTimer = GPTimerCC26XX_open(Board_GPTIMER0A, &params);
GPTimerCC26XX_setLoadValue(hTimer, 0xFFFFFF);
// start
GPTimerCC26XX_registerInterrupt(hTimer, HTA_periodic_callback, GPT_INT_TIMEOUT);
GPTimerCC26XX_start(hTimer);
}
static void HTA_periodic_set_frequency(uint32_t frequency) {
Types_FreqHz freq;
BIOS_getCpuFreq(&freq);
// freq.lo = 48000000
GPTimerCC26XX_Value loadVal = freq.lo / frequency; // 4799 100us execute this value
if (loadVal < 0xFFFF) {
GPTimerCC26XX_setLoadValue(hTimer, loadVal - 1);
} else {
loadVal = (0xFA0000 | (loadVal / 250)) - 1;
GPTimerCC26XX_setLoadValue(hTimer, loadVal);
}
}
#endif // PERIODIC_USE_GPTIMER
#ifdef PERIODIC_USE_CLOCK
#include <ti/sysbios/knl/Clock.h>
static Clock_Struct clock;
static void HTA_periodic_callback(UArg arg) {}
static void HTA_periodic_start() {
Clock_Params param;
Clock_Params_init(&param);
param.period = 1;
param.startFlag = true;
clock = Clock_create(HTA_periodic_callback, 1, &param, NULL);
}
static void HTA_periodic_set_frequency(uint32_t frequency) {
Types_FreqHz freq;
BIOS_getCpuFreq(&freq);
// freq.lo = 48000000
bool is_active = Clock_isActive(clock);
if (is_active) Clock_stop(clock);
Clock_setPeriod(clock, freq.lo / frequency);
if (is_active) Clock_start(clock);
}
#endif // PERIODIC_USE_CLOCK
/*
* periodic callback
*/
#define HTA_EVENT_CALLBACK_SIZE 4
typedef void (*HTA_event_callback_function)();
typedef struct {
uint16_t mask;
HTA_event_callback_function func;
} HTA_event_callback_data;
static HTA_event_callback_data _HTA_event_callback_data[HTA_EVENT_CALLBACK_SIZE] = {0};
static int HTA_set_event_callback(uint16_t mask, HTA_event_callback_function func) {
for (unsigned int i = 0; i < HTA_EVENT_CALLBACK_SIZE; i++) {
if (_HTA_event_callback_data[i].mask == 0) {
_HTA_event_callback_data[i].mask = mask;
_HTA_event_callback_data[i].func = func;
return 1;
}
}
return 0;
}
void HTA_event_call() {
for (unsigned int i = 0; i < HTA_EVENT_CALLBACK_SIZE; i++) {
if (flag_mask(_HTA_event_callback_data[i].mask)) {
_HTA_event_callback_data[i].func();
}
}
if (flag_mask(HTA_PERIODIC_EVT)) {
flag_disable(HTA_PERIODIC_EVT);
}
}
#endif
@@ -9,7 +9,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2013-2018, Texas Instruments Incorporated
All rights reserved.
@@ -45,121 +45,83 @@
Release Date: 2018-04-02 18:03:35
*****************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/hal/Hwi.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Queue.h>
#include <string.h>
#include "hal_types.h"
#include "hci_tl.h"
#include "hci_ext.h"
#include "gatt.h"
#include "hci.h"
#include "gapgattserver.h"
#include "gattservapp.h"
#include "gapbondmgr.h"
#define OSAL_SNV 0
#include "osal_snv.h"
#include "icall_apimsg.h"
#include "util.h"
#include <ti/mw/display/Display.h>
#include "inc/npi_ble.h"
#include "inc/npi_task.h"
#include <inc/hw_types.h>
#include "hal_defs.h"
#if defined ( USE_RCOSC )
#include "rcosc_calibration.h"
#endif // USE_RCOSC
#if defined ( GATT_TEST ) || defined ( GATT_QUAL )
#include "gatttest.h"
#if defined(GATT_TEST) || defined(GATT_QUAL)
#include "gatttest.h"
#endif
#include "host_test_app.h"
#if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
#include <driverlib/ioc.h>
#endif // USE_FPGA | DEBUG_SW_TRACE
#include "cc2650/cc2650_util.h"
/*********************************************************************
* CONSTANTS
*/
#include "cc2650/cc2650_slave.h"
// LE Event Lengths
#define HCI_CMD_COMPLETE_EVENT_LEN 3
#define HCI_CMD_VS_COMPLETE_EVENT_LEN 2
#define HCI_CMD_STATUS_EVENT_LEN 4
#define HCI_PHY_UPDATE_COMPLETE_EVENT_LEN 6
#define HCI_CMD_COMPLETE_EVENT_LEN 3
#define HCI_CMD_VS_COMPLETE_EVENT_LEN 2
#define HCI_CMD_STATUS_EVENT_LEN 4
#define HCI_PHY_UPDATE_COMPLETE_EVENT_LEN 6
static void HTA_init(void);
static void HTA_main(UArg a0, UArg a1);
static void HTA_handle_gap_event(ICall_HciExtEvt *message);
static void HTA_handle_att_event(gattMsgEvent_t *message);
static void HTA_handle_ble_event(ICall_HciExtEvt *message);
static void send_command_complete_event(uint8 eventCode, uint16 opcode, uint8 numParam, uint8 *param);
static void send_command_status_event(uint8_t eventCode, uint16_t status, uint16_t opcode);
static void send_ble_complete_event(uint8 eventLen, uint8 *pEvent);
extern void AssertHandler(uint8 assertCause, uint8 assertSubCause);
// Task configuration
#define HTA_TASK_PRIORITY 1
#define HTA_TASK_STACK_SIZE 644
#define HTA_TASK_STACK_SIZE 512
Task_Struct hta_task;
Char hta_task_stack[HTA_TASK_STACK_SIZE];
/*********************************************************************
* GLOBAL VARIABLES
*/
// Display Interface
Display_Handle dispHandle = NULL;
/*********************************************************************
* LOCAL VARIABLES
*/
// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID selfEntity;
// Semaphore globally used to post events to the application thread
static ICall_Semaphore sem;
// Task configuration
Task_Struct htaTask;
Char htaTaskStack[HTA_TASK_STACK_SIZE];
#if !defined ( GATT_DB_OFF_CHIP )
static uint8 deviceName[GAP_DEVICE_NAME_LEN] = { 0 };
static uint16 appearance = 17;
#endif
// Stack build revision
ICall_BuildRevision buildRev;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void HostTestApp_init(void);
static void HostTestApp_taskFxn(UArg a0, UArg a1);
static void HostTestApp_processGapEvent(ICall_HciExtEvt *pMsg);
static void HostTestApp_processBLEEvent(ICall_HciExtEvt *pMsg);
static void sendCommandCompleteEvent(uint8 eventCode, uint16 opcode,
uint8 numParam, uint8 *param);
static void sendCommandStatusEvent(uint8_t eventCode, uint16_t status,
uint16_t opcode);
static void sendBLECompleteEvent(uint8 eventLen, uint8 *pEvent);
/*********************************************************************
* EXTERN FUNCTIONS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
/*
* @fn HostTestApp_createTask
*
* @brief Task creation function for the Host Test App.
@@ -168,21 +130,30 @@ extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
*
* @return none
*/
void HostTestApp_createTask(void)
{
Task_Params taskParams;
void HostTestApp_createTask(void) {
/* main task */
Task_Params task_main_parameter;
Task_Params_init(&task_main_parameter);
task_main_parameter.stack = hta_task_stack;
task_main_parameter.stackSize = HTA_TASK_STACK_SIZE;
task_main_parameter.priority = 1;
// Configure task
Task_Params_init(&taskParams);
taskParams.stack = htaTaskStack;
taskParams.stackSize = HTA_TASK_STACK_SIZE;
taskParams.priority = HTA_TASK_PRIORITY;
Task_construct(&htaTask, HostTestApp_taskFxn, &taskParams, NULL);
Task_construct(&hta_task, HTA_main, &task_main_parameter, NULL);
}
/*********************************************************************
* @fn HostTestApp_init
// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID self;
// Semaphore globally used to post events to the application thread
extern ICall_Semaphore semaphore;
extern uint16_t event_flags;
// Stack build revision
ICall_BuildRevision build_reversion;
/*
* @fn HTA_init
*
* @brief Called during initialization and contains application
* specific initialization (ie. hardware initialization/setup,
@@ -193,118 +164,30 @@ void HostTestApp_createTask(void)
*
* @return none
*/
static void HostTestApp_init(void)
{
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &sem);
static void HTA_init(void) {
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&self, &semaphore);
#if defined( USE_FPGA )
// configure RF Core SMI Data Link
IOCPortConfigureSet(IOID_12, IOC_PORT_RFC_GPO0, IOC_STD_OUTPUT);
IOCPortConfigureSet(IOID_11, IOC_PORT_RFC_GPI0, IOC_STD_INPUT);
// Initialize GATT Client
VOID GATT_InitClient();
// configure RF Core SMI Command Link
IOCPortConfigureSet(IOID_10, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_OUT, IOC_STD_OUTPUT);
IOCPortConfigureSet(IOID_9, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_IN, IOC_STD_INPUT);
// Register to receive incoming ATT Indications or Notifications of attribute values.
GATT_RegisterForInd(self);
// configure RF Core tracer IO
IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT);
#else // !USE_FPGA
#if defined( DEBUG_SW_TRACE )
// configure RF Core tracer IO
IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT | IOC_CURRENT_4MA | IOC_SLEW_ENABLE);
#endif // DEBUG_SW_TRACE
#endif // USE_FPGA
// Register for GATT local events and ATT Responses pending for transmission.
GATT_RegisterForMsgs(self);
// Set device's Sleep Clock Accuracy
//HCI_EXT_SetSCACmd(40);
#if defined( USE_RCOSC )
RCOSC_enableCalibration();
#endif // USE_RCOSC
dispHandle = Display_open(Display_Type_LCD, NULL);
// Register for unprocessed HCI/Host event messages
GAP_RegisterForMsgs(selfEntity);
// Initialize GATT Client
VOID GATT_InitClient();
// Get build revision
VOID Util_buildRevision(&buildRev);
#if !defined ( GATT_DB_OFF_CHIP )
#if defined ( GATT_QUAL )
VOID GATTQual_AddService( GATT_ALL_SERVICES ); // Includes GAP and GATT Services
#else
// Add our services to GATT Server
VOID GGS_AddService( GATT_ALL_SERVICES );
VOID GATTServApp_AddService( GATT_ALL_SERVICES );
#if defined ( GATT_TEST )
VOID GATTTest_AddService( GATT_ALL_SERVICES );
#endif
#endif
GGS_AddService(GATT_ALL_SERVICES);
GATTServApp_AddService(GATT_ALL_SERVICES);
// Set device name
if ((buildRev.hostInfo & CENTRAL_CFG) && (buildRev.hostInfo & PERIPHERAL_CFG))
{
memcpy(deviceName, "TI BLE All", 10);
}
else if (buildRev.hostInfo & CENTRAL_CFG)
{
memcpy(deviceName, "TI BLE Central", 14);
}
else if (buildRev.hostInfo & PERIPHERAL_CFG)
{
memcpy(deviceName, "TI BLE Peripheral", 17);
}
else
{
memcpy(deviceName, "TI BLE Unknown", 14);
}
VOID GGS_SetParameter(GGS_DEVICE_NAME_ATT, strlen((char *)deviceName), deviceName);
VOID GGS_SetParameter(GGS_APPEARANCE_ATT, sizeof(uint16), (void*)&appearance);
#endif // GATT_DB_OFF_CHIP
Display_print0(dispHandle, 0, 0, "TI BLEv2.0");
Display_print0(dispHandle, 1, 0, "HostTestApp");
// Display Host build configuration
if ((buildRev.hostInfo & CENTRAL_CFG) && (buildRev.hostInfo & PERIPHERAL_CFG))
{
Display_print0(dispHandle, 2, 0, "All");
}
else if ((buildRev.hostInfo & CENTRAL_CFG) &&
(buildRev.hostInfo & BROADCASTER_CFG))
{
Display_print0(dispHandle, 2, 0, "Cent+Bcast");
}
else if ((buildRev.hostInfo & PERIPHERAL_CFG) &&
(buildRev.hostInfo & OBSERVER_CFG))
{
Display_print0(dispHandle, 2, 0, "Peri+Observ");
}
else if (buildRev.hostInfo & CENTRAL_CFG)
{
Display_print0(dispHandle, 2, 0, "Central");
}
else if (buildRev.hostInfo & PERIPHERAL_CFG)
{
Display_print0(dispHandle, 2, 0, "Peripheral");
}
else
{
Display_print1(dispHandle, 2, 0, "Unknown build cfg %d", buildRev.hostInfo);
}
// Register for unprocessed HCI/Host event messages
GAP_RegisterForMsgs(self);
}
/*********************************************************************
* @fn HostTestApp_taskFxn
/*
* @fn HTA_main
*
* @brief Application task entry point for the Host Test App.
*
@@ -312,365 +195,340 @@ static void HostTestApp_init(void)
*
* @return none
*/
static void HostTestApp_taskFxn(UArg a0, UArg a1)
{
// Initialize application
HostTestApp_init();
static void HTA_main(UArg a0, UArg a1) {
// Initialize application
HTA_init();
HTA_util_init();
HTA_main_init();
// Application main loop
for (;;)
{
// Waits for a signal to the semaphore associated with the calling thread.
// Note that the semaphore associated with a thread is signaled when a
// message is queued to the message receive queue of the thread or when
// ICall_signal() function is called onto the semaphore.
ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
// Application main loop
for (;;) {
// Waits for a signal to the semaphore associated with the calling thread.
// Note that the semaphore associated with a thread is signaled when a
// message is queued to the message receive queue of the thread or when
// ICall_signal() function is called onto the semaphore.
ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
if (errno == ICALL_ERRNO_SUCCESS)
{
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt *pMsg = NULL;
if (errno == ICALL_ERRNO_SUCCESS) {
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt * message = NULL;
if (ICall_fetchServiceMsg(&src, &dest,
(void **)&pMsg) == ICALL_ERRNO_SUCCESS)
{
bool dealloc = true;
if (ICall_fetchServiceMsg(&src, &dest, (void **)&message) == ICALL_ERRNO_SUCCESS) {
bool dealloc = true;
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
{
// Process incoming messages
switch (pMsg->hdr.event)
{
case HCI_GAP_EVENT_EVENT:
HostTestApp_processGapEvent(pMsg);
break;
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == self)) {
// Process incoming messages
switch (message->hdr.event) {
case HCI_GAP_EVENT_EVENT:
HTA_handle_gap_event(message);
break;
default:
break;
}
case GATT_MSG_EVENT:
HTA_handle_att_event((gattMsgEvent_t *)message);
break;
case GAP_MSG_EVENT:
break;
}
}
if (dealloc && message) {
ICall_freeMsg(message);
}
}
}
if (dealloc == true)
{
ICall_freeMsg(pMsg);
if (event_flags > 0) {
HTA_event_call();
}
}
}
}
}
/*********************************************************************
* @fn HostTestApp_processGapEvent
/*
* @fn HTA_handle_gap_event
*
* @brief Process an incoming GAP Event.
*
* @param pMsg - message to process
* @param message - message to process
*
* @return none
*/
static void HostTestApp_processGapEvent(ICall_HciExtEvt *pMsg)
{
switch(pMsg->hdr.status)
{
case HCI_COMMAND_COMPLETE_EVENT_CODE:
{
hciEvt_CmdComplete_t *pkt = (hciEvt_CmdComplete_t *)pMsg;
static void HTA_handle_gap_event(ICall_HciExtEvt *message) {
switch (message->hdr.status) {
case HCI_COMMAND_COMPLETE_EVENT_CODE: {
hciEvt_CmdComplete_t *pkt = (hciEvt_CmdComplete_t *)message;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
if (lastAppOpcodeSent == pkt->cmdOpcode) {
// application processes this as it was embedded message to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
} else {
osal_msg_hdr_t *msgHdr;
uint8 len;
msgHdr = (osal_msg_hdr_t *)message;
msgHdr--; // Backup to the message header
len = (uint8)(msgHdr->len - sizeof(hciEvt_CmdComplete_t));
send_command_complete_event(HCI_COMMAND_COMPLETE_EVENT_CODE, pkt->cmdOpcode, len, pkt->pReturnParam);
}
else
{
osal_msg_hdr_t *msgHdr;
uint8 len;
msgHdr = (osal_msg_hdr_t *)pMsg;
msgHdr--; // Backup to the msg header
len = (uint8)(msgHdr->len - sizeof ( hciEvt_CmdComplete_t ));
sendCommandCompleteEvent(HCI_COMMAND_COMPLETE_EVENT_CODE,
pkt->cmdOpcode, len, pkt->pReturnParam);
}
}
break;
break;
}
case HCI_DISCONNECTION_COMPLETE_EVENT_CODE:
break;
break;
case HCI_COMMAND_STATUS_EVENT_CODE:
{
hciEvt_CommandStatus_t *pkt = (hciEvt_CommandStatus_t *)pMsg;
case HCI_COMMAND_STATUS_EVENT_CODE: {
hciEvt_CommandStatus_t *pkt = (hciEvt_CommandStatus_t *)message;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
if (lastAppOpcodeSent == pkt->cmdOpcode) {
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
} else if (pkt->cmdOpcode == HCI_LE_SET_PHY) {
send_command_status_event(HCI_COMMAND_STATUS_EVENT_CODE, pkt->cmdStatus, pkt->cmdOpcode);
}
else if (pkt->cmdOpcode == HCI_LE_SET_PHY)
{
sendCommandStatusEvent(HCI_COMMAND_STATUS_EVENT_CODE, pkt->cmdStatus,
pkt->cmdOpcode);
break;
}
case HCI_LE_EVENT_CODE: {
HTA_handle_ble_event(message);
break;
}
case HCI_BLE_HARDWARE_ERROR_EVENT_CODE: {
AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR, 0);
break;
}
case HCI_VE_EVENT_CODE: {
hciEvt_VSCmdComplete_t *pkt = (hciEvt_VSCmdComplete_t *)message;
if (lastAppOpcodeSent == pkt->cmdOpcode) {
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
} else {
send_command_complete_event(HCI_VE_EVENT_CODE, pkt->cmdOpcode, pkt->length, pkt->pEventParam);
}
}
break;
case HCI_LE_EVENT_CODE:
{
HostTestApp_processBLEEvent(pMsg);
}
break;
case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
{
AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
}
break;
case HCI_VE_EVENT_CODE:
{
hciEvt_VSCmdComplete_t *pkt = (hciEvt_VSCmdComplete_t *)pMsg;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
}
else
{
sendCommandCompleteEvent(HCI_VE_EVENT_CODE, pkt->cmdOpcode,
pkt->length, pkt->pEventParam);
}
}
break;
default:
break;
}
break;
}
}
}
/*********************************************************************
* @fn HostTestApp_processBLEEvent
static void HTA_handle_att_event(gattMsgEvent_t *message) {
uint8_t method = message->method;
if (message->hdr.status == blePending) {
// pass
} else if ((method == ATT_READ_RSP) || (method == ATT_ERROR_RSP && message->msg.errorRsp.reqOpcode == ATT_READ_REQ)) {
// pass
} else if ((method == ATT_WRITE_RSP) || (method == ATT_ERROR_RSP && message->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)) {
// pass
} else if (method == ATT_HANDLE_VALUE_NOTI) {
#ifndef HTA_PIN_RS
#error "HTA_PIN_RS not defined"
#else
if (!PIN_getInputValue(HTA_PIN_RS)) {
attHandleValueNoti_t *att_notify = (attHandleValueNoti_t *)(&message->msg);
HTA_main_handle_notify(att_notify->len, att_notify->pValue);
}
#endif
}
// Free message. Needed only for ATT Protocol messages
GATT_bm_free(&message->msg, message->method);
}
/*
* @fn HTA_handle_ble_event
*
* @brief Process an incoming BLE Event.
* @param pMsg - message to process
* @param message - message to process
*
* @return None.
*/
static void HostTestApp_processBLEEvent(ICall_HciExtEvt *pMsg)
{
hciEvt_BLEPhyUpdateComplete_t *pEvt = (hciEvt_BLEPhyUpdateComplete_t *)pMsg;
uint8 event[HCI_PHY_UPDATE_COMPLETE_EVENT_LEN];
uint8 eventLen;
static void HTA_handle_ble_event(ICall_HciExtEvt *message) {
hciEvt_BLEPhyUpdateComplete_t *pEvt = (hciEvt_BLEPhyUpdateComplete_t *)message;
switch (pEvt->BLEEventCode)
{
case HCI_BLE_PHY_UPDATE_COMPLETE_EVENT:
{
event[0] = HCI_BLE_PHY_UPDATE_COMPLETE_EVENT; // event code
event[1] = pEvt->status; // status
event[2] = LO_UINT16(pEvt->connHandle); // connection handle (LSB)
event[3] = HI_UINT16(pEvt->connHandle); // connection handle (MSB)
event[4] = pEvt->txPhy; // TX PHY
event[5] = pEvt->rxPhy; // RX PHY
uint8 event[HCI_PHY_UPDATE_COMPLETE_EVENT_LEN];
uint8 eventLen = 0;
switch (pEvt->BLEEventCode) {
case HCI_BLE_PHY_UPDATE_COMPLETE_EVENT: {
event[0] = HCI_BLE_PHY_UPDATE_COMPLETE_EVENT; // event code
event[1] = pEvt->status; // status
event[2] = LO_UINT16(pEvt->connHandle); // connection handle (LSB)
event[3] = HI_UINT16(pEvt->connHandle); // connection handle (MSB)
event[4] = pEvt->txPhy; // TX PHY
event[5] = pEvt->rxPhy; // RX PHY
eventLen = HCI_PHY_UPDATE_COMPLETE_EVENT_LEN;
}
break;
break;
}
}
default:
eventLen = 0;
break;
}
if (eventLen > 0)
{
// Send BLE Complete Event
sendBLECompleteEvent(eventLen, event);
}
if (eventLen) {
// Send BLE Complete Event
send_ble_complete_event(eventLen, event);
}
}
//*****************************************************************************
// the function prototypes
/*******************************************************************************
/*
* This generic function sends a Command Complete or a Vendor Specific Command
* Complete Event to the Host.
*
*/
static void sendCommandCompleteEvent(uint8_t eventCode, uint16_t opcode,
uint8_t numParam, uint8_t *param)
{
npiPkt_t *msg;
uint8_t totalLength;
uint8_t txLen = 0; // Length to transmit
static void send_command_complete_event(uint8_t eventCode, uint16_t opcode, uint8_t numParam, uint8_t *param) {
npiPkt_t *msg;
uint8_t totalLength;
uint8_t txLen = 0; // Length to transmit
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Return Parameters (0..N)
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + numParam;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Return Parameters (0..N)
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + numParam;
// adjust the size of the event packet based on event code
// Note: If not a vendor specific event, then the event includes:
// Command Complete Data: Number of HCI Commands Allowed(1) + Command Opcode(2)
// Note: If a vendor specific event, then the event includes:
// Vendor Specific Command Complete Data: Vendor Specific Event Opcode(2)
totalLength += ( (eventCode != HCI_VE_EVENT_CODE) ?
HCI_CMD_COMPLETE_EVENT_LEN :
HCI_CMD_VS_COMPLETE_EVENT_LEN );
// adjust the size of the event packet based on event code
// Note: If not a vendor specific event, then the event includes:
// Command Complete Data: Number of HCI Commands Allowed(1) + Command Opcode(2)
// Note: If a vendor specific event, then the event includes:
// Vendor Specific Command Complete Data: Vendor Specific Event Opcode(2)
totalLength += ((eventCode != HCI_VE_EVENT_CODE) ? HCI_CMD_COMPLETE_EVENT_LEN : HCI_CMD_VS_COMPLETE_EVENT_LEN);
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
msg->pData = (uint8*)(msg+1);
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
if (msg) {
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
msg->pData = (uint8 *)(msg + 1);
txLen += 2;
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
// check if this isn't a vendor specific event
if ( eventCode != HCI_VE_EVENT_CODE )
{
msg->pData[2] = numParam + HCI_CMD_COMPLETE_EVENT_LEN;
msg->pData[3] = 1;// hciCtrlCmdToken; // event parameter 1
msg->pData[4] = LO_UINT16( opcode ); // event parameter 2
msg->pData[5] = HI_UINT16( opcode ); // event parameter 2
txLen += 2;
txLen += 4;
// check if this isn't a vendor specific event
if (eventCode != HCI_VE_EVENT_CODE) {
msg->pData[2] = numParam + HCI_CMD_COMPLETE_EVENT_LEN;
msg->pData[3] = 1; // hciCtrlCmdToken; // event parameter 1
msg->pData[4] = LO_UINT16(opcode); // event parameter 2
msg->pData[5] = HI_UINT16(opcode); // event parameter 2
// remaining event parameters
(void)memcpy(&msg->pData[6], param, numParam);
txLen += 4;
txLen += numParam;
// remaining event parameters
(void)memcpy(&msg->pData[6], param, numParam);
txLen += numParam;
} else { // it is a vendor specific event
// less one byte as number of complete packets not used in vendor specific event
msg->pData[2] = numParam + HCI_CMD_VS_COMPLETE_EVENT_LEN;
msg->pData[3] = param[0]; // event parameter 0: event opcode LSB
msg->pData[4] = param[1]; // event parameter 1: event opcode MSB
msg->pData[5] = param[2]; // event parameter 2: status
msg->pData[6] = LO_UINT16(opcode); // event parameter 3: command opcode LSB
msg->pData[7] = HI_UINT16(opcode); // event parameter 3: command opcode MSB
txLen += 6;
// remaining event parameters
// Note: The event opcode and status were already placed in the msg packet.
(void)memcpy(&msg->pData[8], &param[3], numParam - HCI_EVENT_MIN_LENGTH);
txLen += (numParam - HCI_EVENT_MIN_LENGTH);
}
msg->pktLen = txLen;
NPITask_sendToHost((uint8_t *)msg);
}
else // it is a vendor specific event
{
// less one byte as number of complete packets not used in vendor specific event
msg->pData[2] = numParam + HCI_CMD_VS_COMPLETE_EVENT_LEN;
msg->pData[3] = param[0]; // event parameter 0: event opcode LSB
msg->pData[4] = param[1]; // event parameter 1: event opcode MSB
msg->pData[5] = param[2]; // event parameter 2: status
msg->pData[6] = LO_UINT16( opcode ); // event parameter 3: command opcode LSB
msg->pData[7] = HI_UINT16( opcode ); // event parameter 3: command opcode MSB
txLen += 6;
// remaining event parameters
// Note: The event opcode and status were already placed in the msg packet.
(void)memcpy(&msg->pData[8], &param[3], numParam-HCI_EVENT_MIN_LENGTH);
txLen += (numParam-HCI_EVENT_MIN_LENGTH);
}
msg->pktLen = txLen;
NPITask_sendToHost((uint8_t *)msg);
}
}
/*******************************************************************************
/*
* This generic function sends a Command Complete or a Vendor Specific Command
* Complete Event to the Host.
*
*/
static void sendCommandStatusEvent(uint8_t eventCode, uint16_t status,
uint16_t opcode)
{
npiPkt_t *msg;
uint8_t totalLength;
static void send_command_status_event(uint8_t eventCode, uint16_t status, uint16_t opcode) {
npiPkt_t *msg;
uint8_t totalLength;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Command Status Event Data: Status (1) + Num HCI Cmd Pkt (1) + Cmd Opcode (2)
totalLength = sizeof(npiPkt_t) +
HCI_EVENT_MIN_LENGTH +
HCI_CMD_STATUS_EVENT_LEN;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Command Status Event Data: Status (1) + Num HCI Cmd Pkt (1) + Cmd Opcode (2)
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + HCI_CMD_STATUS_EVENT_LEN;
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg) {
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
// fill in length and data pointer
msg->pktLen = HCI_EVENT_MIN_LENGTH + HCI_CMD_STATUS_EVENT_LEN;
msg->pData = (uint8*)(msg+1);
// fill in length and data pointer
msg->pktLen = HCI_EVENT_MIN_LENGTH + HCI_CMD_STATUS_EVENT_LEN;
msg->pData = (uint8 *)(msg + 1);
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
msg->pData[2] = HCI_CMD_STATUS_EVENT_LEN;
msg->pData[3] = status;
msg->pData[4] = 1; // number of HCI command packets
msg->pData[5] = LO_UINT16(opcode); // opcode (LSB)
msg->pData[6] = HI_UINT16(opcode); // opcode (MSB)
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
msg->pData[2] = HCI_CMD_STATUS_EVENT_LEN;
msg->pData[3] = status;
msg->pData[4] = 1; // number of HCI command packets
msg->pData[5] = LO_UINT16(opcode); // opcode (LSB)
msg->pData[6] = HI_UINT16(opcode); // opcode (MSB)
NPITask_sendToHost((uint8_t *)msg);
}
}
/*******************************************************************************
* This is a generic function used to send BLE Complete Event to the
* Host processor.
*
*/
static void sendBLECompleteEvent(uint8 eventLen, uint8 *pEvent)
{
npiPkt_t *msg;
uint8_t totalLength;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Event Data: eventLen
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + eventLen;
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
// fill in length and data pointer
msg->pktLen = HCI_EVENT_MIN_LENGTH + eventLen;
msg->pData = (uint8*)(msg+1);
// fill in BLE Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = HCI_LE_EVENT_CODE;
msg->pData[2] = eventLen;
// populate event data
if (eventLen > 0)
{
memcpy(&msg->pData[3], pEvent, eventLen);
NPITask_sendToHost((uint8_t *)msg);
}
NPITask_sendToHost((uint8_t *)msg);
}
}
/*********************************************************************
*********************************************************************/
/*
* This is a generic function used to send BLE Complete Event to the Host processor.
*/
static void send_ble_complete_event(uint8 eventLen, uint8 *pEvent) {
npiPkt_t *msg;
uint8_t totalLength;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Event Data: eventLen
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + eventLen;
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg) {
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
// fill in length and data pointer
msg->pktLen = HCI_EVENT_MIN_LENGTH + eventLen;
msg->pData = (uint8 *)(msg + 1);
// fill in BLE Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = HCI_LE_EVENT_CODE;
msg->pData[2] = eventLen;
// populate event data
if (eventLen > 0) {
memcpy(&msg->pData[3], pEvent, eventLen);
}
NPITask_sendToHost((uint8_t *)msg);
}
}
@@ -9,7 +9,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2013-2018, Texas Instruments Incorporated
All rights reserved.
@@ -49,37 +49,16 @@
#define HOSTESTAPP_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
/*********************************************************************
* INCLUDES
*/
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* MACROS
*/
/*********************************************************************
* FUNCTIONS
*/
/*
* Task creation function for the Host Test App.
*/
extern void HostTestApp_createTask(void);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* HOSTESTAPP_H */
#endif
@@ -8,7 +8,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2013-2018, Texas Instruments Incorporated
All rights reserved.
@@ -44,26 +44,29 @@
Release Date: 2018-04-02 18:03:35
*****************************************************************************/
/*******************************************************************************
* INCLUDES
*/
#include <xdc/runtime/Error.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
#include <ti/sysbios/BIOS.h>
#include "icall.h"
#include "hal_assert.h"
#include "board.h"
#include "hal_assert.h"
#include "icall.h"
#include "inc/npi_task.h"
#include "host_test_app.h"
/* Header files required to enable instruction fetch cache */
#include <inc/hw_memmap.h>
#include <driverlib/vims.h>
#include <inc/hw_memmap.h>
#ifndef USE_DEFAULT_USER_CFG
#include "ble_user_config.h"
@@ -71,70 +74,12 @@
// BLE user defined configuration
bleUserCfg_t user0Cfg = BLE_USER_CFG;
#endif // USE_DEFAULT_USER_CFG
#endif // USE_DEFAULT_USER_CFG
#include <ti/mw/display/Display.h>
#ifdef USE_FPGA
#include <inc/hw_prcm.h>
#endif // USE_FPGA
/*******************************************************************************
* MACROS
*/
/*******************************************************************************
* CONSTANTS
*/
#if defined( USE_FPGA )
#define RFC_MODE_BLE PRCM_RFCMODESEL_CURR_MODE1
#define RFC_MODE_ANT PRCM_RFCMODESEL_CURR_MODE4
#define RFC_MODE_EVERYTHING_BUT_ANT PRCM_RFCMODESEL_CURR_MODE5
#define RFC_MODE_EVERYTHING PRCM_RFCMODESEL_CURR_MODE6
//
#define SET_RFC_BLE_MODE(mode) HWREG( PRCM_BASE + PRCM_O_RFCMODESEL ) = (mode)
#endif // USE_FPGA
/*******************************************************************************
* TYPEDEFS
*/
/*******************************************************************************
* LOCAL VARIABLES
*/
/*******************************************************************************
* GLOBAL VARIABLES
*/
#ifdef CC1350_LAUNCHXL
#ifdef POWER_SAVING
// Power Notify Object for wake-up callbacks
Power_NotifyObj rFSwitchPowerNotifyObj;
static uint8_t rFSwitchNotifyCb(uint8_t eventType, uint32_t *eventArg,
uint32_t *clientArg);
#endif //POWER_SAVING
PIN_State radCtrlState;
PIN_Config radCtrlCfg[] =
{
Board_DIO1_RFSW | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* RF SW Switch defaults to 2.4GHz path*/
Board_DIO30_SWPWR | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* Power to the RF Switch */
PIN_TERMINATE
};
PIN_Handle radCtrlHandle;
#endif //CC1350_LAUNCHXL
/*******************************************************************************
* EXTERNS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
extern Display_Handle dispHandle;
/*******************************************************************************
/*
* @fn Main
*
* @brief Application Main
@@ -149,68 +94,38 @@ extern Display_Handle dispHandle;
*
* @return None.
*/
int main()
{
#if defined( USE_FPGA )
HWREG(PRCM_BASE + PRCM_O_PDCTL0) &= ~PRCM_PDCTL0_RFC_ON;
HWREG(PRCM_BASE + PRCM_O_PDCTL1) &= ~PRCM_PDCTL1_RFC_ON;
#endif // USE_FPGA
int main() {
/* Register Application callback to trap asserts raised in the Stack */
RegisterAssertCback(AssertHandler);
/* Register Application callback to trap asserts raised in the Stack */
RegisterAssertCback(AssertHandler);
PIN_init(BoardGpioInitTable);
PIN_init(BoardGpioInitTable);
#ifdef CC1350_LAUNCHXL
// Enable 2.4GHz Radio
radCtrlHandle = PIN_open(&radCtrlState, radCtrlCfg);
// Enable iCache prefetching
VIMSConfigure(VIMS_BASE, TRUE, TRUE);
#ifdef POWER_SAVING
Power_registerNotify(&rFSwitchPowerNotifyObj,
PowerCC26XX_ENTERING_STANDBY | PowerCC26XX_AWAKE_STANDBY,
(Power_NotifyFxn) rFSwitchNotifyCb, NULL);
#endif //POWER_SAVING
#endif //CC1350_LAUNCHXL
// Enable cache
VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
#if defined( USE_FPGA )
// set RFC mode to support BLE
// Note: This must be done before the RF Core is released from reset!
SET_RFC_BLE_MODE(RFC_MODE_BLE);
#endif // USE_FPGA
/* Initialize ICall module */
ICall_init();
// Enable iCache prefetching
VIMSConfigure(VIMS_BASE, TRUE, TRUE);
/* Start tasks of external images */
ICall_createRemoteTasks();
// Enable cache
VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
/* Kick off application */
HostTestApp_createTask();
#if !defined( POWER_SAVING ) || defined( USE_FPGA )
/* Set constraints for Standby, powerdown and idle mode */
// PowerCC26XX_SB_DISALLOW may be redundant
Power_setConstraint(PowerCC26XX_SB_DISALLOW);
Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
#endif // POWER_SAVING | USE_FPGA
/* Kick off NPI */
NPITask_createTask(ICALL_SERVICE_CLASS_BLE);
/* Initialize ICall module */
ICall_init();
/* enable interrupts and start SYS/BIOS */
BIOS_start();
/* Start tasks of external images */
ICall_createRemoteTasks();
/* Kick off application */
HostTestApp_createTask();
/* Kick off NPI */
NPITask_createTask(ICALL_SERVICE_CLASS_BLE);
/* enable interrupts and start SYS/BIOS */
BIOS_start();
return 0;
return 0;
}
/*******************************************************************************
/*
* @fn AssertHandler
*
* @brief This is the Application's callback handler for asserts raised
@@ -246,57 +161,9 @@ int main()
*
* @return None.
*/
void AssertHandler(uint8 assertCause, uint8 assertSubcause)
{
// Open the display if the app has not already done so
if ( !dispHandle )
{
dispHandle = Display_open(Display_Type_LCD, NULL);
}
void AssertHandler(uint8 assertCause, uint8 assertSubcause) {}
Display_print0(dispHandle, 0, 0, ">>>STACK ASSERT");
// check the assert cause
switch (assertCause)
{
// This assert is raised from the BLE Stack when a malloc failure occurs.
case HAL_ASSERT_CAUSE_OUT_OF_MEMORY:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> OUT OF MEMORY!");
break;
case HAL_ASSERT_CAUSE_INTERNAL_ERROR:
// check the subcause
if (assertSubcause == HAL_ASSERT_SUBCAUSE_FW_INERNAL_ERROR)
{
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> INTERNAL FW ERROR!");
}
else
{
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> INTERNAL ERROR!");
}
break;
// An assert originating from an ICall failure.
case HAL_ASSERT_CAUSE_ICALL_ABORT:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> ICALL ABORT!");
HAL_ASSERT_SPINLOCK;
break;
default:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> DEFAULT SPINLOCK!");
HAL_ASSERT_SPINLOCK;
}
return;
}
/*******************************************************************************
/*
* @fn exceptionHandler
*
* @brief Generic spinlock to trap RTOS raised errors.
@@ -311,13 +178,11 @@ void AssertHandler(uint8 assertCause, uint8 assertSubcause)
*
* @return None.
*/
void exceptionHandler( void )
{
volatile uint8 i = 1;
while(i);
void exceptionHandler(void) {
for (;;);
}
/*******************************************************************************
/*
* @fn smallErrorHook
*
* @brief Error handler to be hooked into TI-RTOS.
@@ -332,45 +197,6 @@ void exceptionHandler( void )
*
* @return None.
*/
void smallErrorHook(Error_Block *eb)
{
for (;;);
void smallErrorHook(Error_Block *eb) {
for (;;);
}
#if defined (CC1350_LAUNCHXL) && defined (POWER_SAVING)
/*******************************************************************************
* @fn rFSwitchNotifyCb
*
* @brief Power driver callback to toggle RF switch on Power state
* transitions.
*
* input parameters
*
* @param eventType - The state change.
* @param eventArg - Not used.
* @param clientArg - Not used.
*
* @return Power_NOTIFYDONE to indicate success.
*/
static uint8_t rFSwitchNotifyCb(uint8_t eventType, uint32_t *eventArg,
uint32_t *clientArg)
{
if (eventType == PowerCC26XX_ENTERING_STANDBY)
{
// Power down RF Switch
PIN_setOutputValue(radCtrlHandle, Board_DIO30_SWPWR, 0);
}
else if (eventType == PowerCC26XX_AWAKE_STANDBY)
{
// Power up RF Switch
PIN_setOutputValue(radCtrlHandle, Board_DIO30_SWPWR, 1);
}
// Notification handled successfully
return Power_NOTIFYDONE;
}
#endif //CC1350_LAUNCHXL || POWER_SAVING
/*******************************************************************************
*/