您的位置:首页 > 产品设计 > UI/UE

CC2540/CC2541 : Change Scan Response Data( SRP) dynamically

2015-04-27 00:03 721 查看
     How to change the SRP data is a very imperative for most bluetooth low energy use case. But in official Texas Instruments(TI) example code, there is no demonstration  for this purpose. In here, I note how to reach the goal.

    In the TI forum , it sai possible to update RSP data by disabling/enabling advertising.  But for my feeble trying, the RSP do not be updated. So I use the "reboot" as my method.

   Before achieving the topic goal, I would like to refer to how to add uart receiving function in example SimpleBLEPeripheral. The is based on

ghostyu's example (in simplified chinese).

0. Copy while SimpleBLEPeripheral folder as a new folder SimpleBLEPeripheral_SerialPrint.

1. Add those file in your IAR project:

serialcommunication.c :

#include "bcomdef.h"
#include "OSAL.h"
#include "OSAL_PwrMgr.h"

#include "OnBoard.h"
#include "hal_uart.h"
#include "hal_lcd.h"
#include "serialcommunication.h"

#if defined ( PLUS_BROADCASTER )
#include "peripheralBroadcaster.h"
#else
#include "peripheral.h"
#endif

void SerialInitTransport(void)
{
halUARTCfg_t uartConfig;

// configure UART
uartConfig.configured           = TRUE;
uartConfig.baudRate             = SBP_UART_BR;
uartConfig.flowControl          = SBP_UART_FC;
uartConfig.flowControlThreshold = SBP_UART_FC_THRESHOLD;//enable when flowControl is valid
uartConfig.rx.maxBufSize        = SBP_UART_RX_BUF_SIZE;//UART RX
uartConfig.tx.maxBufSize        = SBP_UART_TX_BUF_SIZE;//UART TX
uartConfig.idleTimeout          = SBP_UART_IDLE_TIMEOUT;
uartConfig.intEnable            = SBP_UART_INT_ENABLE;//interrupt enable
uartConfig.callBackFunc         = sbpSerialAppCallback;//uart callback function

// start UART
// Note: Assumes no issue opening UART port.
(void)HalUARTOpen( SBP_UART_PORT, &uartConfig );

return;
}/*serialAppInitTransport*/

uint16 numBytes;

void sbpSerialAppCallback(uint8 port, uint8 event)
{
uint8  pktBuffer[SBP_UART_RX_BUF_SIZE];
// unused input parameter; PC-Lint error 715.
(void)event;
HalLcdWriteString("Data form my UART:", HAL_LCD_LINE_4 );
//return lengh
if( (numBytes = Hal_UART_RxBufLen(port)) > 0)
{
//int j;
//read all data
(void)HalUARTRead(port, pktBuffer, numBytes);
//uint8 blankStr[HAL_LCD_MAX_CHARS];
// memset(&blankStr[0], 32, HAL_LCD_MAX_CHARS);

HalLcdWriteString(pktBuffer, HAL_LCD_LINE_5 );

//GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA,
//  numBytes, &pktBuffer[0] );

//simpleProfileChar1 = pktBuffer[0];
}/*if */

}/*sbpSerialAppCallback*/

static uint8 sendMsgTo_TaskID;

void SerialApp_Init( uint8 taskID )
{
SerialInitTransport();
sendMsgTo_TaskID = taskID; //save task id, for spare using.
}/*SerialApp_Init*/


serialcommunication.h

#ifndef _SERIAL_COMMUNICATION_H_
#define _SERIAL_COMMUNICATION_H_

#ifdef __cplusplus
extern "C"
{
#endif

#define SBP_UART_PORT                  HAL_UART_PORT_0
//#define SBP_UART_FC                    TRUE
#define SBP_UART_FC                    FALSE
#define SBP_UART_FC_THRESHOLD          48
#define SBP_UART_RX_BUF_SIZE           128
#define SBP_UART_TX_BUF_SIZE           128
#define SBP_UART_IDLE_TIMEOUT          6
#define SBP_UART_INT_ENABLE            TRUE
#define SBP_UART_BR                     HAL_UART_BR_57600

// Serial Port Related
extern void SerialApp_Init(uint8 taskID);
extern void sbpSerialAppCallback(uint8 port, uint8 event);
void SerialInitTransport();

#ifdef __cplusplus
}
#endif

#endif/*_SERIAL_COMMUNICATION_H_*/


3. Modify simpleBLEPeripheral.c :

Add include  (about line 82):

#if defined FEATURE_OAD
#include "oad.h"
#include "oad_target.h"
#endif

#include "serialcommunication.h"
/*********************************************************************
* MACROS
*/


Initialize uart (in function void SimpleBLEPeripheral_Init( uint8 task_id ), about line 286):

void SimpleBLEPeripheral_Init( uint8 task_id )
{
simpleBLEPeripheral_TaskID = task_id;

SerialApp_Init(task_id);
// Setup the GAP


Now, you could use a serial com-port program(like
sscom) to send data via uart.

    I assume the new SRP data is from UART, and received data be only the new SRP string. Modifying the UART callback function, to add some processing for save RSP values:

uint16 numBytes;

void sbpSerialAppCallback(uint8 port, uint8 event)
{
uint8 pktBuffer[SBP_UART_RX_BUF_SIZE];
// unused input parameter; PC-Lint error 715.
(void)event;
HalLcdWriteString("Data form my UART:", HAL_LCD_LINE_4 );

//return length
if( 0 < (numBytes = Hal_UART_RxBufLen(port)))
{

/*that should use timer + process_event to update LCD content*/
//(void)HalUARTRead(port, pktBuffer, numBytes);

/*
baud rate = 57600-> byterate = 7200, it is, for one byte,  it needs 138 us
nop cast 1 clock, for CC254X, the crytal be 32MHz
it is needed to be dalay over 138us ->  4416 nop operations

if there is no delay in here, the uart-in data would be lost.

most persons use 6000 (192us) as delay constant (a superstition?)
*/
int i = 0;
for(i = 0 ;0 < 6000;i++)
asm("nop");

/*string sequence may be ended at 0x0A(enter) 0x0D(new line)*/
if(0x0A == pData[numBytes - 1] || 0x0D == pData[numBytes - 1])
numBytes--;

if(0x0A == pData[numBytes - 2] || 0x0D == pData[numBytes - 2])
numBytes--;

uint8 buffer[32];
uint16 scanRspDataSize;

memset(&buffer[0], 0, 32);

osal_snv_write(NV_MEM_ID, 32, &buffer[0]);

SetRspData(&pData[0], numBytes, &buffer[0], &scanRspDataSize);
osal_snv_write(NV_MEM_ID, scanRspDataSize, &buffer[0]);
HAL_SYSTEM_RESET();
}/*if */

}/*sbpSerialAppCallback*/


  that is,clean the non-volatile memory, and save the organized RSP data, then reboot.

the NV_MEM_ID is 0xFE, it is my choice only. you could use other value.

the SetRspData function, which is for organizing data as RSP format, be :

(I wrote it in simpleBLEPeripheral.c)

void SetRspData(uint8 *pName, uint16 nameLen,
uint8 *pRspData, uint16 *pScanRspDataSize)
{

if(nameLen  > 31 - (2 + (5 + 1) + (1 + 2)) )
nameLen =  31 - (2 + (5 + 1) + (1 + 2));

pRspData[0] = nameLen + 1;
pRspData[1] = GAP_ADTYPE_LOCAL_NAME_COMPLETE;
memcpy(&pRspData[2], pName, nameLen);

int16  i;

i = nameLen + 2;
pRspData[i++] = 0x05;
pRspData[i++] = GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE;
pRspData[i++] = LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL );
pRspData[i++] = HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL );
pRspData[i++] = LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL );
pRspData[i++] = HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL );

pRspData[i++] = 0x02;
pRspData[i++] =GAP_ADTYPE_POWER_LEVEL;
pRspData[i++] = 0;       // 0dBm;

*pScanRspDataSize =  i;
}/*SetRspData*/


Now modify the void SimpleBLEPeripheral_Init( uint8 task_id ) in simpleBLEPeripheral.c, about line 315 :

// Set the GAP Role Parameters

GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable );
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );

uint8 defaultName[32];

memset(&defaultName[0], 0, 32);
sprintf((char*)&defaultName[0], "defaultRSP");

uint8 buffer[32];
memset(&buffer[0], 0, 32);

uint8 ret;

uint16 scanRspDataSize;
scanRspDataSize = 0;

ret = osal_snv_read(NV_MEM_ID, 32 , &buffer[0]);

if(SUCCESS == ret )
{
int i;
scanRspDataSize = 0;
scanRspDataSize = 1 + buffer[0];
i = 1 + buffer[0];
scanRspDataSize += 1 + buffer[i];
i += 1 + buffer[i];
scanRspDataSize += 1 + buffer[i];
}/*if*/

if(NV_OPER_FAILED == ret)
{
memset(&buffer[0], 0, 31);
SetRspData(&defaultName[0], strlen((char*)&defaultName[0]),
&buffer[0], &scanRspDataSize);
//ret = osal_snv_read(0xfe, 32 , &buffer[0]);
//osal_snv_write(0xfe, sizeof(scanRspData), &scanRspData[0]);
}/*if */

GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, scanRspDataSize, &buffer[0] );


That is, to read the non-volatile memory: if there is no data, use default name, otherwise use saved data. That data would be used for SRP, the peripheral name.

If you use serial comport program to send a string into the CC2540 (or CC2541), the board would reboot, and the string be the new peripheral name.

Extra:

If you would like to print data to uart (that could use for echoing), the serialcommunication.c could be add function SerialPrintf :

// ref : http://bbs.elecfans.com/jishu_431223_2_1.html#comment_top 
#ifdef HAL_UART_DMA_TX_MAX
#define PRINT_BUF_LEN HAL                 UART_DMA_TX_MAX
#else
#define PRINT_BUF_LEN                     (128)
#endif

int SerialPrintf(const char *fmt, ...)
{
uint32  ulLen;
va_list ap;

char *pBuf;

pBuf = (char*)osal_mem_alloc(PRINT_BUF_LEN);

va_start(ap, fmt);
ulLen = vsprintf(pBuf, fmt, ap);
va_end(ap);

HalUARTWrite(HAL_UART_PORT_0, (uint8*)pBuf, ulLen);
osal_mem_free(pBuf);

return ulLen;
}/*SerialPrintf*/


And do not forget adding include head to avoid compiling warning.

#include "stdarg.h"
#include "stdio.h"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息