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

来源:互联网 发布:蓝光电影播放器 mac 编辑:程序博客网 时间:2024/06/01 09:32

     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 onghostyu'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"#endifvoid 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 __cplusplusextern "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 Relatedextern 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)#endifint 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"


1 0
原创粉丝点击