微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI蓝牙设计交流 > CC2541 snv读写及simpleBLE数据发送的问题

CC2541 snv读写及simpleBLE数据发送的问题

时间:10-02 整理:3721RD 点击:

你好!
有两个问题让我疑惑,项目设计也卡在这边,希望贵司能够提供一些技术支持,指点一下问题:

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》。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top