CC2541 snv读写及simpleBLE数据发送的问题
你好!
有两个问题让我疑惑,项目设计也卡在这边,希望贵司能够提供一些技术支持,指点一下问题:
1. 我遇到一个非常奇怪的问题,这个问题我在贵司的论坛上看到过去年的时候有人问,可是一直没有被解答,
如下代码,
uint8 cali[4]={0x10,0x20,0x30,0x40};
uint8 cali_temp[4]={0x50,0x60,0x70,0x80};
uint8 m=0xce;
if(osal_snv_read(0x90,4,&cali_temp) == SUCCESS)
{
m=0x77;
}
else
{
m=0xaa;
}
单单只是执行snv_read的话,返回值总是NV_OPER_FAILED,而m的值为0xaa,也就是说读取snv失败了,可是如果我执行下面的代码,读取却成功了(即先write一次,再read):
if(osal_snv_write(0x90,4,cali) == SUCCESS)
{
...
}
else
{
...
}
if(osal_snv_read(0x90,4,cali_temp) == SUCCESS)
{
m=0x77;
}
else
{
m=0xaa;
}
cali_temp[]数组的值被赋予了{0x10,0x20,0x30,0x40}的值。
因为我们的设计需要存储一些数据,所以CPU每次reset都需要预先从snv读取一些数据,但是看起来读取操作出现错误了,而开机只能先读取保存的数据,请问这是怎么回事呢?
2. simpleBLECentral项目,本身他是只发送一个字节的,根据源程序,我稍微修改了一下,增加了第二个发送字节,用于在peripheral端检测接受的数据,如:
if ( simpleBLEDoWrite )
{
// Do a write
attWriteReq_t req;
req.handle = simpleBLECharHdl;
req.len = 2;
req.value[0] = simpleBLECharVal;
req.value[1] = 0x7c;
req.sig = 0;
req.cmd = 0;
status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
}
else
{
// Do a read
attReadReq_t req;
req.handle = simpleBLECharHdl;
status = GATT_ReadCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
}
可是在调试的过程中发现,GATT_WriteCharValue无法发送数据,总是发送错误,LCD上提示"Write Error 13", 请问问题是出在哪里啊,TI协议栈能够支持多字节数据发送么?
有TI工程师么?先顶起来!
根据这个问题,我又仔细调试了下,
我用的是simpleBLEPeripheral工程,在SimpleBLEPeripheral_Main.c的Main()中已经有osal_snv_init()函数,当然,为了确保一点,我还是在我的osal_snv_read()前加了这个函数,可是发现还是无效。
/* Initialize NV system */
osal_snv_init();
/* Initialize LL */
/* Initialize the operating system */
osal_init_system();
另外在调试的同时,发现peripheral.c中GAPRole_Init()函数也有调用osal_snv_read()函数,debug结果是读取的返回都是NV_OPER_FAILED, 也就是说其实所有的osal_snv_read()都fail了,经过深入的调试,
// Restore Items from NV
VOID osal_snv_read( BLE_NVID_IRK, KEYLEN, gapRole_IRK );
VOID osal_snv_read( BLE_NVID_CSRK, KEYLEN, gapRole_SRK );
VOID osal_snv_read( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter );
我发现在单独掉用osal_snv_read时,语句 uint16 offset = findItem(activePg, pgOff, id);执行后,offset都是0,意味着所有返回都是NV_OPER_FAILED
uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf )
{
uint16 offset = findItem(activePg, pgOff, id);
if (offset != 0)
{
HalFlashRead(activePg, offset, pBuf, len);
return SUCCESS;
}
return NV_OPER_FAILED;
}
然后我决定先write,再read,尝试看下这之间的不同,结果我发现....
第一次调用osal_snv_write(),offset一样也是0,注意:此时pgoff值为4,所以osal_snv_write()能够返回SUCCESS是执行了蓝色代码,而后pgoff值变为12,之后再调用osal_snv_read()后offset就不为0了,值为4;
uint8 osal_snv_write( osalSnvId_t id, osalSnvLen_t len, void *pBuf )
{
uint16 alignedLen;
{
uint16 offset = findItem(activePg, pgOff, id);
if (offset > 0)
{
uint8 tmp;
osalSnvLen_t i;
.....
.....
}
alignedLen = ((len + OSAL_NV_WORD_SIZE - 1) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE;
if ( pgOff + alignedLen + OSAL_NV_WORD_SIZE > OSAL_NV_PAGE_SIZE )
{
setXferPage();
compactPage(activePg);
}
// pBuf shall be referenced beyond its valid length to save code size.
writeItem(activePg, pgOff, id, alignedLen, pBuf);
if (failF)
{
return NV_OPER_FAILED;
}
pgOff += alignedLen + OSAL_NV_WORD_SIZE;
return SUCCESS;
}
所以我觉得关键还是在offset = findItem(activePg, pgOff, id);,不知道为什么返回都是0呢?
根据这个问题,我又仔细调试了下,
我用的是simpleBLEPeripheral工程,在SimpleBLEPeripheral_Main.c的Main()中已经有osal_snv_init()函数,当然,为了确保一点,我还是在我的osal_snv_read()前加了这个函数,可是发现还是无效。
/* Initialize NV system */
osal_snv_init();
/* Initialize LL */
/* Initialize the operating system */
osal_init_system();
另外在调试的同时,发现peripheral.c中GAPRole_Init()函数也有调用osal_snv_read()函数,debug结果是读取的返回都是NV_OPER_FAILED, 也就是说其实所有的osal_snv_read()都fail了,经过深入的调试,
// Restore Items from NV
VOID osal_snv_read( BLE_NVID_IRK, KEYLEN, gapRole_IRK );
VOID osal_snv_read( BLE_NVID_CSRK, KEYLEN, gapRole_SRK );
VOID osal_snv_read( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter );
我发现在单独掉用osal_snv_read时,语句 uint16 offset = findItem(activePg, pgOff, id);执行后,offset都是0,意味着所有返回都是NV_OPER_FAILED
uint8 osal_snv_read( osalSnvId_t id, osalSnvLen_t len, void *pBuf )
{
uint16 offset = findItem(activePg, pgOff, id);
if (offset != 0)
{
HalFlashRead(activePg, offset, pBuf, len);
return SUCCESS;
}
return NV_OPER_FAILED;
}
然后我决定先write,再read,尝试看下这之间的不同,结果我发现....
第一次调用osal_snv_write(),offset一样也是0,注意:此时pgoff值为4,所以osal_snv_write()能够返回SUCCESS是执行了蓝色代码,而后pgoff值变为12,之后再调用osal_snv_read()后offset就不为0了,值为4;
uint8 osal_snv_write( osalSnvId_t id, osalSnvLen_t len, void *pBuf )
{
uint16 alignedLen;
{
uint16 offset = findItem(activePg, pgOff, id);
if (offset > 0)
{
uint8 tmp;
osalSnvLen_t i;
.....
.....
}
alignedLen = ((len + OSAL_NV_WORD_SIZE - 1) / OSAL_NV_WORD_SIZE) * OSAL_NV_WORD_SIZE;
if ( pgOff + alignedLen + OSAL_NV_WORD_SIZE > OSAL_NV_PAGE_SIZE )
{
setXferPage();
compactPage(activePg);
}
// pBuf shall be referenced beyond its valid length to save code size.
writeItem(activePg, pgOff, id, alignedLen, pBuf);
if (failF)
{
return NV_OPER_FAILED;
}
pgOff += alignedLen + OSAL_NV_WORD_SIZE;
return SUCCESS;
}
所以我觉得关键还是在offset = findItem(activePg, pgOff, id);,不知道为什么返回都是0呢?
1、NV也是一段存储区域,不是莫名其妙就有数据的,需要先写进去的;而且osal_snv_read此API明确的有说,不要试图去读取一段没有被写入过的区域,否则会导致返回NV_OPEN_FAILED.
2、GATT_WriteCharValue只能写一个characteristic值的前8位数据,你这种情况要使用GATT_WriteLongCharValue
按照你的说法,这个就没意义了,每次要先写才能读还怎么保存数据,之前存的数据开机读一下就不行了
请问你解决了吗?我也是这个问题的
一样的情况,如楼主有解决办法的话也希望能请教一下,万分感谢!共勉!
嗨,你好,你说的遇到的同样的情况是第一种写flash的问题还是第二条只能传一个字节的问题?
请问这个问题是否已经解决了呢?我也是这样的情况,先写就可以读,先读失败的情况
哦,知道了,因为调试的时候是重新烧录FLASH的,所以是未写状态,所以调试的时候会读取失败
怎么解决了,怎么都只能先写才能后读?
草,晕死。找到问题了,第一次下载不断电情况下是调试状态,这样NV是写不进,下载后要断后,我擦,搞了两晚
看我个性签名档的博客地址,《CC2541之snv》。