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"
沒有留言:
張貼留言