TI中文支持网
TI专业的中文技术问题搜集分享网站

CC2640的SimpleBLEPeripheral工程,无法使用SNV是咋回事?

我现在开发的东西,基于SimpleBLEPeripheral工程的FlashROM模式开发,未使用OAD。

现在需要在单片机上保存部分用户数据,数量不多,也就100字节左右吧,调试SNV时发现了诡异的问题:

无论是读取还是写入数据,函数都会返回0x02,也就是INVALIDPARAMETER错误。

写入的ID使用的是0x80和0x85,均如此。

已经纠结了一天,未能确定原因,但发现osal_snv_init()函数似乎没有被执行,在这个函数入口处打不上断点,在函数内写了个死循环while(1);也不会卡住;我单独在main()函数中单独调用osal_snv_init()函数的话,编译不过,现在我重点怀疑是因为osal_snv_init()没有执行导致的,但不知道该怎么办,因为这个函数包含在osal_snv.c中,而这个文件一旦加入工程,编译就报错(读写SNV的函数重复,但屏蔽掉后还有其它错误)。

请问这个是怎么回事?SimpleBLEPeripheral工程应该是可以用SNV的吧?

/****************************************************************************/

我再补充一下我的调试流程:

刚刚测试确认osal_snv_init()函数未编译,我把末尾分号去掉人为制造出了语法错误,编译通过……

顺着函数调用处向前查,发现该函数所在的stack_main()由ICall_startup.c文件中的startup_entry()函数调用,这个函数也没有编译。

startup_entry()再向前就查不到了,出现下面一堆我看不懂的东西:

#ifdef __TI_COMPILER_VERSION__
#pragma CODE_SECTION(startup_entry,"EntrySection")
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma location="EntrySection"
#endif

这一堆宏貌似是区分编译器,进行绝对地址定位,全工程搜索找不到函数调用位置。

换个思路:

不依赖上面那一堆东西,我自己调用osal_snv_init()进行初始化,挂osal_snv.h后,报函数未定义错误,工程本身似乎没有加入osal_snv.c文件。

手动添加到工程中后,osal_snv.c文件中的osal_snv_read()、osal_snv_write()与ICallBleAPI.c文件中的两个函数重复,编译不过。

屏蔽掉osal_snv.c中的osal_snv_read()和osal_snv_write()后,编译依然过不了,报Flash相关操作的函数未定义……

/****************************************************************************************************************************/

此问题已经解决,这两个函数不能在其他任务中访问,否则就会报错。谢谢各位网友的帮忙~

Alvin Chen:

你打开OSAL_SNV=2在预编译option里面,

然后包含头文件#include "osal_snv.h"。  

Alvin Chen:

回复 Alvin Chen:

#define BUF_LEN 10
#define SNV_ID_APP 0x80
uint8 buf[BUF_LEN] = {0,};
// Initialize application
simple_peripheral_init();
uint8 status = SUCCESS;
//Read from SNV flash
status = osal_snv_read(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
if(status != SUCCESS)
{
DISPLAY_WRITE_STRING_VALUE("SNV READ FAIL: %d", status, LCD_PAGE5);
//Write first time to initialize SNV ID
osal_snv_write(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
}
//Increment value and write to SNV flash
uint8 x;
for(x = 0; x < BUF_LEN; x++)
buf[x] = x + 1;
status = osal_snv_write(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
if(status != SUCCESS)
DISPLAY_WRITE_STRING_VALUE("SNV WRITE FAIL: %d", status, LCD_PAGE6);
else
DISPLAY_WRITE_STRING_VALUE("Num of Resets: %d", buf[0], LCD_PAGE6);

3.10.3 Using Simple NV for Flash Storage

The Simple NV (SNV) area of flash is used for storing persistent data, such as encryption keys from

bonding or to store custom defined parameters. The protocol stack can be configured to reserve up to two

4kB flash pages for SNV, although valid data is only stored in one active flash page. To minimize the

number of erase cycles on the flash, the SNV manager performs compactions on the flash sector (or

sectors) when the sector has 80% invalidated data. A compaction is the copying of valid data to a

temporary area followed by an erase of the sector where the data was previously stored. Depending on

the OSAL_SNV value as described in Table 3-2, this valid data is then either placed back in the newly

erased sector or remains in a new sector. The number of flash sectors allocated to SNV can be configured

by setting the OSAL_SNV preprocessor symbol in the stack project. Table 3-2 lists the valid values that

can be configured as well as the corresponding trade-offs.

Table 3-2. OSAL_SNV Values

OSAL_SNV Value Description

0 SNV is disabled. Storing of bonding keys in NV is not possible. Maximizes code space for the

application and/or stack project. GAP Bond Manager must be disabled. In the Stack project, set preprocessor

symbol NO_OSAL_SNV and disable GAP Bond Manager. See Section 10.4 for configuring

Bluetooth low energy protocol stack features.

1 (default) One flash sector is allocated to SNV. Bonding info is stored in NV. Flash compaction uses flash cache

RAM for intermediate storage, thus a power-loss during compaction results in SNV data loss. Also,

due to temporarily disabling the cache, a system performance degradation may occur during the

compaction. Set preprocessor symbol OSAL_SNV=1 in the Stack project.

2 Two flash sectors are allocated to SNV. Bonding information is stored in NV. SNV data is protected

against power-loss during compaction.

Other values for OSAL_SNV are invalid. Using less than the maximum value has the net effect of

allocating more code space to the application or stack project. SNV can be read from or written to using

the following APIs.

uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf)

Read data from NV.

Parameters id – valid NV item

len – length of data to read

pBuf – pointer to buffer to store data read

Returns SUCCESS: NV item read successfully

NV_OPER_FAILED: failure reading NV item

uint8 osal_snv_write( osalSnvId_t id, osalSnvLen_t len, void *pBuf)

Write data to NV

Parameters id – valid NV item

len – length of data to write

pBuf – pointer to buffer containing data to be written. All contents are updated at once.

user1980778:

回复 Alvin Chen:

您好,已经在Option的预定义框中加上了OSAL_SNV=2语句,依然返回0x02代码。

user1980778:

回复 Alvin Chen:

您好,不知您能否看懂中文,我能阅读英语但我不会说英语,请见谅。
您后面的内容好像是文档中的资料。上面程序中,您使用status变量接收返回值,我也是类似的写法,然后这个变量的值为0x02。

Alvin Chen:

回复 user1980778:

/******************************************************************************@filesimple_peripheral.c@brief This file contains the Simple Peripheral sample application for usewith the CC2650 Bluetooth Low Energy Protocol Stack.Group: CMCU, SCSTarget Device: CC2640R2******************************************************************************Copyright (c) 2013-2017, Texas Instruments IncorporatedAll rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditionsare met:*Redistributions of source code must retain the above copyrightnotice, this list of conditions and the following disclaimer.*Redistributions in binary form must reproduce the above copyrightnotice, this list of conditions and the following disclaimer in thedocumentation and/or other materials provided with the distribution.*Neither the name of Texas Instruments Incorporated nor the names ofits contributors may be used to endorse or promote products derivedfrom this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER ORCONTRIBUTORS 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 OROTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.******************************************************************************Release Name: simplelink_cc2640r2_sdk_01_50_00_58Release Date: 2017-10-17 18:09:51*****************************************************************************//********************************************************************** INCLUDES*/
#include <string.h>#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/display/Display.h>#if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
#include <driverlib/ioc.h>
#endif // USE_FPGA | DEBUG_SW_TRACE#include <icall.h>
#include "util.h"
/* This Header file contains all BLE API and icall structure definition */
#include "icall_ble_api.h"#include "devinfoservice.h"
#include "simple_gatt_profile.h"
#include "ll_common.h"#include "peripheral.h"#ifdef USE_RCOSC
#include "rcosc_calibration.h"
#endif //USE_RCOSC#include "board_key.h"#include "board.h"
#include <driverlib/aon_batmon.h>
#include "simple_peripheral.h"
#include "osal_snv.h"
#define BUF_LEN 10
#define SNV_ID_APP 0x80
/********************************************************************** CONSTANTS*/// Advertising interval when device is discoverable (units of 625us, 160=100ms)
#define DEFAULT_ADVERTISING_INTERVAL160// General discoverable mode: advertise indefinitely
#define DEFAULT_DISCOVERABLE_MODEGAP_ADTYPE_FLAGS_GENERAL// Minimum connection interval (units of 1.25ms, 80=100ms) for automatic
// parameter update request
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL80// Maximum connection interval (units of 1.25ms, 800=1000ms) for automatic
// parameter update request
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL800// Slave latency to use for automatic parameter update request
#define DEFAULT_DESIRED_SLAVE_LATENCY0// Supervision timeout value (units of 10ms, 1000=10s) for automatic parameter
// update request
#define DEFAULT_DESIRED_CONN_TIMEOUT1000// After the connection is formed, the peripheral waits until the central
// device asks for its preferred connection parameters
#define DEFAULT_ENABLE_UPDATE_REQUESTGAPROLE_LINK_PARAM_UPDATE_WAIT_REMOTE_PARAMS// Connection Pause Peripheral time value (in seconds)
#define DEFAULT_CONN_PAUSE_PERIPHERAL6// How often to perform periodic event (in msec)
#define SBP_PERIODIC_EVT_PERIOD5000// Application specific event ID for HCI Connection Event End Events
#define SBP_HCI_CONN_EVT_END_EVT0x0001// Type of Display to open
#if !defined(Display_DISABLE_ALL)#if defined(BOARD_DISPLAY_USE_LCD) && (BOARD_DISPLAY_USE_LCD!=0)#define SBP_DISPLAY_TYPE Display_Type_LCD#elif defined (BOARD_DISPLAY_USE_UART) && (BOARD_DISPLAY_USE_UART!=0)#define SBP_DISPLAY_TYPE Display_Type_UART#else // !BOARD_DISPLAY_USE_LCD && !BOARD_DISPLAY_USE_UART#define SBP_DISPLAY_TYPE 0 // Option not supported#endif // BOARD_DISPLAY_USE_LCD && BOARD_DISPLAY_USE_UART
#else // BOARD_DISPLAY_USE_LCD && BOARD_DISPLAY_USE_UART#define SBP_DISPLAY_TYPE 0 // No Display
#endif // !Display_DISABLE_ALL// Task configuration
#define SBP_TASK_PRIORITY1#ifndef SBP_TASK_STACK_SIZE
#define SBP_TASK_STACK_SIZE644
#endif// Application events
#define SBP_STATE_CHANGE_EVT0x0001
#define SBP_CHAR_CHANGE_EVT0x0002
#define SBP_PAIRING_STATE_EVT0x0004
#define SBP_PASSCODE_NEEDED_EVT0x0008// Internal Events for RTOS application
#define SBP_ICALL_EVTICALL_MSG_EVENT_ID // Event_Id_31
#define SBP_QUEUE_EVTUTIL_QUEUE_EVENT_ID // Event_Id_30
#define SBP_PERIODIC_EVTEvent_Id_00// Bitwise OR of all events to pend on
#define SBP_ALL_EVENTS(SBP_ICALL_EVT| \SBP_QUEUE_EVT| \SBP_PERIODIC_EVT)/********************************************************************** TYPEDEFS*/// App event passed from profiles.
typedef struct
{appEvtHdr_t hdr;// event header.uint8_t *pData;// event data
} sbpEvt_t;/********************************************************************** 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;// Event globally used to post local events and pend on system and
// local events.
static ICall_SyncHandle syncEvent;// Clock instances for internal periodic events.
static Clock_Struct periodicClock;// Queue object used for app messages
static Queue_Struct appMsg;
static Queue_Handle appMsgQueue;// Task configuration
Task_Struct sbpTask;
Char sbpTaskStack[SBP_TASK_STACK_SIZE];// Scan response data (max size = 31 bytes)
static uint8_t scanRspData[] =
{// complete name0x14,// length of this dataGAP_ADTYPE_LOCAL_NAME_COMPLETE,'S','i','m','p','l','e','B','L','E','P','e','r','i','p','h','e','r','a','l',// connection interval range0x05,// length of this dataGAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),// 100msHI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),// 1sHI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),// Tx power level0x02,// length of this dataGAP_ADTYPE_POWER_LEVEL,0// 0dBm
};// Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertising)
static uint8_t advertData[] =
{// Flags: this field sets the device to use general discoverable// mode (advertises indefinitely) instead of general// discoverable mode (advertise for 30 seconds at a time)0x02,// length of this dataGAP_ADTYPE_FLAGS,DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,// service UUID, to notify central devices what services are included// in this peripheral0x03,// length of this dataGAP_ADTYPE_16BIT_MORE,// some of the UUID's, but not allLO_UINT16(SIMPLEPROFILE_SERV_UUID),HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};// GAP GATT Attributes
static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple Peripheral";// Globals used for ATT Response retransmission
static gattMsgEvent_t *pAttRsp = NULL;
static uint8_t rspTxRetry = 0;/********************************************************************** LOCAL FUNCTIONS*/static void SimpleBLEPeripheral_init( void );
static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1);static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *pMsg);
static uint8_t SimpleBLEPeripheral_processGATTMsg(gattMsgEvent_t *pMsg);
static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg);
static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState);
static void SimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID);
static void SimpleBLEPeripheral_performPeriodicTask(void);
static void SimpleBLEPeripheral_clockHandler(UArg arg);static void SimpleBLEPeripheral_sendAttRsp(void);
static void SimpleBLEPeripheral_freeAttRsp(uint8_t status);static void SimpleBLEPeripheral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,uint8_t uiInputs, uint8_t uiOutputs);
static void SimpleBLEPeripheral_pairStateCB(uint16_t connHandle, uint8_t state,uint8_t status);
static void SimpleBLEPeripheral_processPairState(uint8_t state, uint8_t status);
static void SimpleBLEPeripheral_processPasscode(uint8_t uiOutputs);static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState);
static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID);
static uint8_t SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state,uint8_t *pData);/********************************************************************** EXTERN FUNCTIONS*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);/********************************************************************** PROFILE CALLBACKS*/// Peripheral GAPRole Callbacks
static gapRolesCBs_t SimpleBLEPeripheral_gapRoleCBs =
{SimpleBLEPeripheral_stateChangeCB// GAPRole State Change Callbacks
};// GAP Bond Manager Callbacks
// These are set to NULL since they are not needed. The application
// is set up to only perform justworks pairing.
static gapBondCBs_t simpleBLEPeripheral_BondMgrCBs =
{(pfnPasscodeCB_t) SimpleBLEPeripheral_passcodeCB, // Passcode callbackSimpleBLEPeripheral_pairStateCB// Pairing / Bonding state Callback
};// Simple GATT Profile Callbacks
static simpleProfileCBs_t SimpleBLEPeripheral_simpleProfileCBs =
{SimpleBLEPeripheral_charValueChangeCB // Simple GATT Characteristic value change callback
};/********************************************************************** PUBLIC FUNCTIONS*//********************************************************************** @fnSimpleBLEPeripheral_createTask** @briefTask creation function for the Simple Peripheral.** @paramNone.** @returnNone.*/
void SimpleBLEPeripheral_createTask(void)
{Task_Params taskParams;// Configure taskTask_Params_init(&taskParams);taskParams.stack = sbpTaskStack;taskParams.stackSize = SBP_TASK_STACK_SIZE;taskParams.priority = SBP_TASK_PRIORITY;Task_construct(&sbpTask, SimpleBLEPeripheral_taskFxn, &taskParams, NULL);
}/********************************************************************** @fnSimpleBLEPeripheral_init** @briefCalled during initialization and contains application*specific initialization (ie. hardware initialization/setup,*table initialization, power up notification, etc), and*profile initialization/setup.** @paramNone.** @returnNone.*/
static void SimpleBLEPeripheral_init(void)
{// ******************************************************************// N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp// ******************************************************************// Register the current thread as an ICall dispatcher application// so that the application can send and receive messages.ICall_registerApp(&selfEntity, &syncEvent);#ifdef USE_RCOSCRCOSC_enableCalibration();
#endif // USE_RCOSC#if defined( USE_FPGA )// configure RF Core SMI Data LinkIOCPortConfigureSet(IOID_12, IOC_PORT_RFC_GPO0, IOC_STD_OUTPUT);IOCPortConfigureSet(IOID_11, IOC_PORT_RFC_GPI0, IOC_STD_INPUT);// configure RF Core SMI Command LinkIOCPortConfigureSet(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);// configure RF Core tracer IOIOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT);
#else // !USE_FPGA#if defined( DEBUG_SW_TRACE )// configure RF Core tracer IOIOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT | IOC_CURRENT_4MA | IOC_SLEW_ENABLE);#endif // DEBUG_SW_TRACE
#endif // USE_FPGA// Create an RTOS queue for message from profile to be sent to app.appMsgQueue = Util_constructQueue(&appMsg);// Create one-shot clocks for internal periodic events.Util_constructClock(&periodicClock, SimpleBLEPeripheral_clockHandler,SBP_PERIODIC_EVT_PERIOD, 0, false, SBP_PERIODIC_EVT);// Set GAP Parameters: After a connection was established, delay in seconds// before sending when GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE,...)// uses GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_PARAMS or// GAPROLE_LINK_PARAM_UPDATE_INITIATE_APP_PARAMS// For current defaults, this has no effect.GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);// Setup the Peripheral GAPRole Profile. For more information see the User's// Guide:// software-dl.ti.com/.../{// Device starts advertising upon initialization of GAPuint8_t initialAdvertEnable =FALSE;// By setting this to zero, the device will go into the waiting state after// being discoverable for 30.72 second, and will not being advertising again// until re-enabled by the applicationuint16_t advertOffTime = 0;uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;uint8_t scMode = GAPBOND_SECURE_CONNECTION_ALLOW;// Set the Peripheral GAPRole ParametersGAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),&initialAdvertEnable);GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),&advertOffTime);GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),scanRspData);GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t),&enableUpdateRequest);GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),&desiredMinInterval);GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),&desiredMaxInterval);GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),&desiredSlaveLatency);GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),&desiredConnTimeout);GAPBondMgr_SetParameter(GAPBOND_SECURE_CONNECTION, sizeof(uint8_t), &scMode);}// Set the Device Name characteristic in the GAP GATT Service// For more information, see the section in the User's Guide:// software-dl.ti.com/.../htmlGGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);// Set GAP Parameters to set the advertising interval// For more information, see the GAP section of the User's Guide:// software-dl.ti.com/.../html{// Use the same interval for general and limited advertising.// Note that only general advertising will occur based on the above configurationuint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);}// Setup the GAP Bond Manager. For more information see the section in the// User's Guide:// software-dl.ti.com/.../{// Don't send a pairing request after connecting; the peer device must// initiate pairinguint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;// Use authenticated pairing: require passcode.uint8_t mitm = TRUE;// This device only has display capabilities. Therefore, it will display the// passcode during pairing. However, since the default passcode is being// used, there is no need to display anything.uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;// Request bonding (storing long-term keys for re-encryption upon subsequent// connections without repairing)uint8_t bonding = TRUE;GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);}// Initialize GATT attributesGGS_AddService(GATT_ALL_SERVICES);// GAP GATT ServiceGATTServApp_AddService(GATT_ALL_SERVICES);// GATT ServiceDevInfo_AddService();// Device Information ServiceSimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile// Setup the SimpleProfile Characteristic Values// For more information, see the sections in the User's Guide:// software-dl.ti.com/.../{uint8_t charValue1 = 1;uint8_t charValue2 = 2;uint8_t charValue3 = 3;uint8_t charValue4 = 4;uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),&charValue1);SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),&charValue2);SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),&charValue3);SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),&charValue4);SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,charValue5);}// Register callback with SimpleGATTprofileSimpleProfile_RegisterAppCBs(&SimpleBLEPeripheral_simpleProfileCBs);// Start the DeviceVOID GAPRole_StartDevice(&SimpleBLEPeripheral_gapRoleCBs);// Start Bond Manager and register callbackVOID GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs);// Register with GAP for HCI/Host messages. This is needed to receive HCI// events. For more information, see the section in the User's Guide:// software-dl.ti.com/.../htmlGAP_RegisterForMsgs(selfEntity);// Register for GATT local events and ATT Responses pending for transmissionGATT_RegisterForMsgs(selfEntity);//Set default values for Data Length Extension{//Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)#define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)#define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)//This API is documented in hci.h//See the LE Data Length Extension section in the BLE-Stack User's Guide for information on using this command://software-dl.ti.com/.../index.html//HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);}#if !defined (USE_LL_CONN_PARAM_UPDATE)// Get the currently set local supported LE features// The HCI will generate an HCI event that will get received in the main// loopHCI_LE_ReadLocalSupportedFeaturesCmd();
#endif // !defined (USE_LL_CONN_PARAM_UPDATE)dispHandle = Display_open(Display_Type_UART, NULL);Display_print0(dispHandle, 0, 0, "BLE Peripheral");uint8 status = SUCCESS;uint8 buf[20];//Read from SNV flashstatus = osal_snv_read(SNV_ID_APP, BUF_LEN, (uint8 *)buf);if(status == SUCCESS){Display_print0(dispHandle, 0, 0, "SNV READ OK");//Write first time to initialize SNV ID}//Increment value and write to SNV flashuint8 x;for(x = 0; x < BUF_LEN; x++){buf[x] = 0X30 + 0;}status = osal_snv_write(SNV_ID_APP, BUF_LEN, (uint8 *)buf);if(status == SUCCESS){Display_print0(dispHandle, 0, 0, "SNV WROTE OK");}Util_startClock(&periodicClock);}/********************************************************************** @fnSimpleBLEPeripheral_taskFxn** @briefApplication task entry point for the Simple Peripheral.** @parama0, a1 - not used.** @returnNone.*/
static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
{// Initialize applicationSimpleBLEPeripheral_init();// Application main loopfor (;;){uint32_t events;// Waits for an event to be posted associated with the calling thread.// Note that an event associated with a thread is posted when a// message is queued to the message receive queue of the threadevents = Event_pend(syncEvent, Event_Id_NONE, SBP_ALL_EVENTS,ICALL_TIMEOUT_FOREVER);if (events){ICall_EntityID dest;ICall_ServiceEnum src;ICall_HciExtEvt *pMsg = NULL;// Fetch any available messages that might have been sent from the stackif (ICall_fetchServiceMsg(&src, &dest,(void **)&pMsg) == ICALL_ERRNO_SUCCESS){uint8 safeToDealloc = TRUE;if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity)){ICall_Stack_Event *pEvt = (ICall_Stack_Event *)pMsg;// Check for BLE stack events firstif (pEvt->signature == 0xffff){// The GATT server might have returned a blePending as it was trying// to process an ATT Response. Now that we finished with this// connection event, let's try sending any remaining ATT Responses// on the next connection event.if (pEvt->event_flag & SBP_HCI_CONN_EVT_END_EVT){// Try to retransmit pending ATT Response (if any)SimpleBLEPeripheral_sendAttRsp();}}else{// Process inter-task messagesafeToDealloc = SimpleBLEPeripheral_processStackMsg((ICall_Hdr *)pMsg);}}if (pMsg && safeToDealloc){ICall_freeMsg(pMsg);}}// If RTOS queue is not empty, process app message.if (events & SBP_QUEUE_EVT){while (!Queue_empty(appMsgQueue)){sbpEvt_t *pMsg = (sbpEvt_t *)Util_dequeueMsg(appMsgQueue);if (pMsg){// Process message.SimpleBLEPeripheral_processAppMsg(pMsg);// Free the space from the message.ICall_free(pMsg);}}}if (events & SBP_PERIODIC_EVT){Util_startClock(&periodicClock);// Perform periodic application taskSimpleBLEPeripheral_performPeriodicTask();}}}
}/********************************************************************** @fnSimpleBLEPeripheral_processStackMsg** @briefProcess an incoming stack message.** @parampMsg - message to process** @returnTRUE if safe to deallocate incoming message, FALSE otherwise.*/
static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *pMsg)
{uint8_t safeToDealloc = TRUE;switch (pMsg->event){case GATT_MSG_EVENT:// Process GATT messagesafeToDealloc = SimpleBLEPeripheral_processGATTMsg((gattMsgEvent_t *)pMsg);break;case HCI_GAP_EVENT_EVENT:{// Process HCI messageswitch(pMsg->status){case HCI_COMMAND_COMPLETE_EVENT_CODE:// Process HCI Command Complete Event{#if !defined (USE_LL_CONN_PARAM_UPDATE)// This code will disable the use of the LL_CONNECTION_PARAM_REQ// control procedure (for connection parameter updates, the// L2CAP Connection Parameter Update procedure will be used// instead). To re-enable the LL_CONNECTION_PARAM_REQ control// procedures, define the symbol USE_LL_CONN_PARAM_UPDATE// The L2CAP Connection Parameter Update procedure is used to// support a delta between the minimum and maximum connection// intervals required by some iOS devices.// Parse Command Complete Event for opcode and statushciEvt_CmdComplete_t* command_complete = (hciEvt_CmdComplete_t*) pMsg;uint8_tpktStatus = command_complete->pReturnParam[0];//find which command this command complete is forswitch (command_complete->cmdOpcode){case HCI_LE_READ_LOCAL_SUPPORTED_FEATURES:{if (pktStatus == SUCCESS){uint8_t featSet[8];// Get current feature set from received event (bits 1-9// of the returned datamemcpy( featSet, &command_complete->pReturnParam[1], 8 );// Clear bit 1 of byte 0 of feature set to disable LL// Connection Parameter UpdatesCLR_FEATURE_FLAG( featSet[0], LL_FEATURE_CONN_PARAMS_REQ );// Update controller with modified featuresHCI_EXT_SetLocalSupportedFeaturesCmd( featSet );}}break;default://do nothingbreak;}
#endif // !defined (USE_LL_CONN_PARAM_UPDATE)}break;case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);break;default:break;}}break;default:// do nothingbreak;}return (safeToDealloc);
}/********************************************************************** @fnSimpleBLEPeripheral_processGATTMsg** @briefProcess GATT messages and events.** @returnTRUE if safe to deallocate incoming message, FALSE otherwise.*/
static uint8_t SimpleBLEPeripheral_processGATTMsg(gattMsgEvent_t *pMsg)
{// See if GATT server was unable to transmit an ATT responseif (pMsg->hdr.status == blePending){// No HCI buffer was available. Let's try to retransmit the response// on the next connection event.if (HCI_EXT_ConnEventNoticeCmd(pMsg->connHandle, selfEntity,SBP_HCI_CONN_EVT_END_EVT) == SUCCESS){// First free any pending responseSimpleBLEPeripheral_freeAttRsp(FAILURE);// Hold on to the response message for retransmissionpAttRsp = pMsg;// Don't free the response message yetreturn (FALSE);}}else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT){// ATT request-response or indication-confirmation flow control is// violated. All subsequent ATT requests or indications will be dropped.// The app is informed in case it wants to drop the connection.// Display the opcode of the message that caused the violation.}else if (pMsg->method == ATT_MTU_UPDATED_EVENT){// MTU size updated}// Free message payload. Needed only for ATT Protocol messagesGATT_bm_free(&pMsg->msg, pMsg->method);// It's safe to free the incoming messagereturn (TRUE);
}/********************************************************************** @fnSimpleBLEPeripheral_sendAttRsp** @briefSend a pending ATT response message.** @paramnone** @returnnone*/
static void SimpleBLEPeripheral_sendAttRsp(void)
{// See if there's a pending ATT Response to be transmittedif (pAttRsp != NULL){uint8_t status;// Increment retransmission countrspTxRetry++;// Try to retransmit ATT response till either we're successful or// the ATT Client times out (after 30s) and drops the connection.status = GATT_SendRsp(pAttRsp->connHandle, pAttRsp->method, &(pAttRsp->msg));if ((status != blePending) && (status != MSG_BUFFER_NOT_AVAIL)){// Disable connection event end noticeHCI_EXT_ConnEventNoticeCmd(pAttRsp->connHandle, selfEntity, 0);// We're done with the response messageSimpleBLEPeripheral_freeAttRsp(status);}else{// Continue retrying}}
}/********************************************************************** @fnSimpleBLEPeripheral_freeAttRsp** @briefFree ATT response message.** @paramstatus - response transmit status** @returnnone*/
static void SimpleBLEPeripheral_freeAttRsp(uint8_t status)
{// See if there's a pending ATT response messageif (pAttRsp != NULL){// See if the response was sent out successfullyif (status == SUCCESS){}else{// Free response payloadGATT_bm_free(&pAttRsp->msg, pAttRsp->method);}// Free response messageICall_freeMsg(pAttRsp);// Reset our globalspAttRsp = NULL;rspTxRetry = 0;}
}/********************************************************************** @fnSimpleBLEPeripheral_processAppMsg** @briefProcess an incoming callback from a profile.** @parampMsg - message to process** @returnNone.*/
static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg)
{switch (pMsg->hdr.event){case SBP_STATE_CHANGE_EVT:{SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)pMsg->hdr.state);}break;case SBP_CHAR_CHANGE_EVT:{SimpleBLEPeripheral_processCharValueChangeEvt(pMsg->hdr.state);}break;// Pairing eventcase SBP_PAIRING_STATE_EVT:{SimpleBLEPeripheral_processPairState(pMsg->hdr.state, *pMsg->pData);ICall_free(pMsg->pData);break;}// Passcode eventcase SBP_PASSCODE_NEEDED_EVT:{SimpleBLEPeripheral_processPasscode(*pMsg->pData);ICall_free(pMsg->pData);break;}default:// Do nothing.break;}
}/********************************************************************** @fnSimpleBLEPeripheral_stateChangeCB** @briefCallback from GAP Role indicating a role state change.** @paramnewState - new state** @returnNone.*/
static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState)
{SimpleBLEPeripheral_enqueueMsg(SBP_STATE_CHANGE_EVT, newState, 0);
}/********************************************************************** @fnSimpleBLEPeripheral_processStateChangeEvt** @briefProcess a pending GAP Role state change event.** @paramnewState - new state** @returnNone.*/
static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState)
{
#ifdef PLUS_BROADCASTERstatic bool firstConnFlag = false;
#endif // PLUS_BROADCASTERswitch ( newState ){case GAPROLE_STARTED:{uint8_t ownAddress[B_ADDR_LEN];uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);// use 6 bytes of device address for 8 bytes of system ID valuesystemId[0] = ownAddress[0];systemId[1] = ownAddress[1];systemId[2] = ownAddress[2];// set middle bytes to zerosystemId[4] = 0x00;systemId[3] = 0x00;// shift three bytes upsystemId[7] = ownAddress[5];systemId[6] = ownAddress[4];systemId[5] = ownAddress[3];DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);// Display device address}break;case GAPROLE_ADVERTISING:break;#ifdef PLUS_BROADCASTER// After a connection is dropped, a device in PLUS_BROADCASTER will continue// sending non-connectable advertisements and shall send this change of// state to the application.These are then disabled here so that sending// connectable advertisements can resume.case GAPROLE_ADVERTISING_NONCONN:{uint8_t advertEnabled = FALSE;// Disable non-connectable advertising.GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),&advertEnabled);advertEnabled = TRUE;// Enabled connectable advertising.GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),&advertEnabled);// Reset flag for next connection.firstConnFlag = false;SimpleBLEPeripheral_freeAttRsp(bleNotConnected);}break;
#endif //PLUS_BROADCASTERcase GAPROLE_CONNECTED:{linkDBInfo_t linkInfo;uint8_t numActive = 0;Util_startClock(&periodicClock);numActive = linkDB_NumActive();// Use numActive to determine the connection handle of the last// connectionif ( linkDB_GetInfo( numActive - 1, &linkInfo ) == SUCCESS ){}else{uint8_t peerAddress[B_ADDR_LEN];GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);}#ifdef PLUS_BROADCASTER// Only turn advertising on for this state when we first connect// otherwise, when we go from connected_advertising back to this state// we will be turning advertising back on.if (firstConnFlag == false){uint8_t advertEnabled = FALSE; // Turn on Advertising// Disable connectable advertising.GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),&advertEnabled);// Set to true for non-connectable advertising.advertEnabled = TRUE;// Enable non-connectable advertising.GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),&advertEnabled);firstConnFlag = true;}#endif // PLUS_BROADCASTER}break;case GAPROLE_CONNECTED_ADV:break;case GAPROLE_WAITING:Util_stopClock(&periodicClock);SimpleBLEPeripheral_freeAttRsp(bleNotConnected);// Clear remaining linesbreak;case GAPROLE_WAITING_AFTER_TIMEOUT:SimpleBLEPeripheral_freeAttRsp(bleNotConnected);// Clear remaining lines#ifdef PLUS_BROADCASTER// Reset flag for next connection.firstConnFlag = false;#endif // PLUS_BROADCASTERbreak;case GAPROLE_ERROR:break;default:break;}}/********************************************************************** @fnSimpleBLEPeripheral_charValueChangeCB** @briefCallback from Simple Profile indicating a characteristic*value change.** @paramparamID - parameter ID of the value that was changed.** @returnNone.*/
static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID)
{SimpleBLEPeripheral_enqueueMsg(SBP_CHAR_CHANGE_EVT, paramID, 0);
}/********************************************************************** @fnSimpleBLEPeripheral_processCharValueChangeEvt** @briefProcess a pending Simple Profile characteristic value change*event.** @paramparamID - parameter ID of the value that was changed.** @returnNone.*/
static void SimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID)
{uint8_t newValue;switch(paramID){case SIMPLEPROFILE_CHAR1:SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);break;case SIMPLEPROFILE_CHAR3:SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);break;default:// should not reach here!break;}
}/********************************************************************** @fnSimpleBLEPeripheral_performPeriodicTask** @briefPerform a periodic application task. This function gets called*every five seconds (SBP_PERIODIC_EVT_PERIOD). In this example,*the value of the third characteristic in the SimpleGATTProfile*service is retrieved from the profile, and then copied into the*value of the the fourth characteristic.** @paramNone.** @returnNone.*/static void SimpleBLEPeripheral_performPeriodicTask(void)
{//uint8_t valueToCopy;// Call to retrieve the value of the third characteristic in the profile/*if (SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &valueToCopy) == SUCCESS){// Call to set that value of the fourth characteristic in the profile.// Note that if notifications of the fourth characteristic have been// enabled by a GATT client device, then a notification will be sent// every time this function is called.SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),&valueToCopy);}*/}/********************************************************************** @fnSimpleBLEPeripheral_pairStateCB** @briefPairing state callback.** @returnnone*/
static void SimpleBLEPeripheral_pairStateCB(uint16_t connHandle, uint8_t state,uint8_t status)
{uint8_t *pData;// Allocate space for the event data.if ((pData = ICall_malloc(sizeof(uint8_t)))){*pData = status;// Queue the event.SimpleBLEPeripheral_enqueueMsg(SBP_PAIRING_STATE_EVT, state, pData);}
}/********************************************************************** @fnSimpleBLEPeripheral_processPairState** @briefProcess the new paring state.** @returnnone*/
static void SimpleBLEPeripheral_processPairState(uint8_t state, uint8_t status)
{if (state == GAPBOND_PAIRING_STATE_STARTED){}else if (state == GAPBOND_PAIRING_STATE_COMPLETE){if (status == SUCCESS){}else{}}else if (state == GAPBOND_PAIRING_STATE_BONDED){if (status == SUCCESS){}}else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED){if (status == SUCCESS){}else{}}
}/********************************************************************** @fnSimpleBLEPeripheral_passcodeCB** @briefPasscode callback.** @returnnone*/
static void SimpleBLEPeripheral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,uint8_t uiInputs, uint8_t uiOutputs)
{uint8_t *pData;// Allocate space for the passcode event.if ((pData = ICall_malloc(sizeof(uint8_t)))){*pData = uiOutputs;// Enqueue the event.SimpleBLEPeripheral_enqueueMsg(SBP_PASSCODE_NEEDED_EVT, 0, pData);}
}/********************************************************************** @fnSimpleBLEPeripheral_processPasscode** @briefProcess the Passcode request.** @returnnone*/
static void SimpleBLEPeripheral_processPasscode(uint8_t uiOutputs)
{// This app uses a default passcode. A real-life scenario would handle all// pairing scenarios and likely generate this randomly.uint32_t passcode = B_APP_DEFAULT_PASSCODE;// Display passcode to userif (uiOutputs != 0){}uint16_t connectionHandle;GAPRole_GetParameter(GAPROLE_CONNHANDLE, &connectionHandle);// Send passcode responseGAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode);
}/********************************************************************** @fnSimpleBLEPeripheral_clockHandler** @briefHandler function for clock timeouts.** @paramarg - event type** @returnNone.*/
static void SimpleBLEPeripheral_clockHandler(UArg arg)
{// Wake up the application.Event_post(syncEvent, arg);
}/********************************************************************** @fnSimpleBLEPeripheral_enqueueMsg** @briefCreates a message and puts the message in RTOS queue.** @paramevent - message event.* @paramstate - message state.* @parampData - message data pointer.** @returnTRUE or FALSE*/
static uint8_t SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state,uint8_t *pData)
{sbpEvt_t *pMsg = ICall_malloc(sizeof(sbpEvt_t));// Create dynamic pointer to message.if (pMsg){pMsg->hdr.event = event;pMsg->hdr.state = state;pMsg->pData = pData;// Enqueue the message.return Util_enqueueMsg(appMsgQueue, syncEvent, (uint8_t *)pMsg);}return FALSE;
}
/*********************************************************************
*********************************************************************/

你好,我用手里的CC2640R2写了一段程序,我刚测试了可以的。你可以参照。

user1980778:

回复 Alvin Chen:

在APP和Stack的预编译选项中都添加了OSAL_SNV=2,还是不行,我已经怀疑人生……

user1980778:

回复 Alvin Chen:

这个程序中涉及SNV的部分不就是564~581这一段吗?我也是这么用的呀,依旧返回0x02,写入读取均失败,真是邪门了……

Eggsy Pang:

回复 user1980778:

CC2640的SimpleBLEPeripheral_onchip_oad例程直接有SNV操作,你玩一下看看行不行

赞(0)
未经允许不得转载:TI中文支持网 » CC2640的SimpleBLEPeripheral工程,无法使用SNV是咋回事?
分享到: 更多 (0)