微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI Zigbee设计交流 > CC2530内部flash数据丢失问题求教

CC2530内部flash数据丢失问题求教

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

 我这里使用的TI的CC2530开发的产品中使用了内部的flash存储的数据最近发现有丢失现象,协议栈使用的是Zstack-CC2530-2.3.0-1.4.0,flash读写函数使用的是协议栈中提供的osal_nv_write(),osal_nv_read()和osal_nv_item_init()函数,在调用osal_nv_write()和osal_nv_read()之前都先调用的osal_nv_item_init(),判断osal_nv_item_init()返回成功才进行执行读写函数,程序中使用的NV item在 0x201-0x302之间,每一个item最多存储2个字节的数据,在研发阶段都没有发现什么问题,现在工程现场应用了一段时间,发现有些产品中这些数据被清除了,请帮忙分析一下原因。在客户应用中是否出现过这样的问题,我们在应用时还需要注意哪些问题,谢谢支持!

数据被清除,是指全部NV数据都没有吗?

还是说部分被改动了,部分还在。

从返回样机查看,NV中的数据都被清掉了,网络信息(信道和PanID)都发生了改变,从读取效果看,跟刚下完程序一个效果。

有没有可能中途出现过复位,然后在复位,启动以后start option有改动过了,导致重新擦除参数启动。

你们程序里面有没有改动这个start option的地方,另外你们的节点如果重新加网的话,会自动把之前保存的应用相关的参数擦除掉吗?

出现复位是有可能的,改动start option的地方也是有的,为了防止出现您说的这种情况,我们在程序中做了限制,start option需要配合和外部按键一起才能触发这种参数恢复默认值的操作,我们在应用的过程中对修改start option的操作做了记录,如果有类似的操作,只要不重新下载程序,都会有记录可查的,但从返回的问题样机根本看不出一点记录;另外节点如果重新加网的话,协调器中的参数也不会擦除掉。

如果有部分数据丢失的话,有可能是在运行过程中,在对部分数据进行读写的时候,导致出错。

如果数据全部都擦除的话,一定是软件的操作导致的。

你们现场协调器和节点都出现NV数据被擦除的情况吗?

我看到在协议栈中的main()函数里zgInit()函数之前有一个osal_nv_init()函数,能解释一下osal_nv_init()函数的工作过程吗?我这里出现数据丢失的问题现象都很一致,nv中的数据都被重置了,包括在zgInit()函数中没有进行过复位操作的几个NV Item,从现象上来看就是跟刚下完程序一个效果,所以我现在还是比较怀疑在zgInit()之外还有其他的地方出现了问题,请帮忙分析一下,谢谢支持!

您可以在IAR内追踪该函数,osal_nv_init 主要是调用了(void)initNV(); 

/*********************************************************************
* @fn osal_nv_init
*
* @brief Initialize NV service.
*
* @param p - Not used.
*
* @return none
*/
void osal_nv_init( void *p )
{
(void)p; // Suppress Lint warning.
(void)initNV(); // Always returns TRUE after pages have been erased.
}

而(void)initNV(); 的定义可以在OSAL_Nv.c查找到

/*********************************************************************
* @fn initNV
*
* @brief Initialize the NV flash pages.
*
* @param none
*
* @return TRUE
*/
static uint8 initNV( void )
{
osalNvPgHdr_t pgHdr;
uint8 oldPg = OSAL_NV_PAGE_NULL;
uint8 findDups = FALSE;
uint8 pg;

pgRes = OSAL_NV_PAGE_NULL;

for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
{
HalFlashRead(pg, OSAL_NV_PAGE_HDR_OFFSET, (uint8 *)(&pgHdr), OSAL_NV_HDR_SIZE);

if ( pgHdr.active == OSAL_NV_ERASED_ID )
{
if ( pgRes == OSAL_NV_PAGE_NULL )
{
pgRes = pg;
}
else
{
setPageUse( pg, TRUE );
}
}
// An Xfer from this page was in progress.
else if ( pgHdr.xfer != OSAL_NV_ERASED_ID )
{
oldPg = pg;
}
}

// If a page compaction was interrupted before the old page was erased.
if ( oldPg != OSAL_NV_PAGE_NULL )
{
/* Interrupted compaction before the target of compaction was put in use;
* so erase the target of compaction and start again.
*/
if ( pgRes != OSAL_NV_PAGE_NULL )
{
erasePage( pgRes );
(void)compactPage( oldPg, OSAL_NV_ITEM_NULL );
}
/* Interrupted compaction after the target of compaction was put in use,
* but before the old page was erased; so erase it now and create a new reserve page.
*/
else
{
erasePage( oldPg );
pgRes = oldPg;
}
}
else if ( pgRes != OSAL_NV_PAGE_NULL )
{
erasePage( pgRes ); // The last page erase could have been interrupted by a power-cycle.
}
/* else if there is no reserve page, COMPACT_PAGE_CLEANUP() must have succeeded to put the old
* reserve page (i.e. the target of the compacted items) into use but got interrupted by a reset
* while trying to erase the page to be compacted. Such a page should only contain duplicate items
* (i.e. all items will be marked 'Xfer') and thus should have the lost count equal to the page
* size less the page header.
*/

for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
{
// Calculate page offset and lost bytes - any "old" item triggers an N^2 re-scan from start.
if ( initPage( pg, OSAL_NV_ITEM_NULL, findDups ) != OSAL_NV_ITEM_NULL )
{
findDups = TRUE;
pg = (OSAL_NV_PAGE_BEG - 1); // Pre-decrement so that loop increment will start over at zero.
continue;
}
}

if (findDups)
{
// Final pass to calculate page lost after invalidating duplicate items.
for ( pg = OSAL_NV_PAGE_BEG; pg <= OSAL_NV_PAGE_END; pg++ )
{
(void)initPage( pg, OSAL_NV_ITEM_NULL, FALSE );
}
}

if ( pgRes == OSAL_NV_PAGE_NULL )
{
uint8 idx, mostLost = 0;

for ( idx = 0; idx < OSAL_NV_PAGES_USED; idx++ )
{
// Is this the page that was compacted?
if (pgLost[idx] == (OSAL_NV_PAGE_SIZE - OSAL_NV_PAGE_HDR_SIZE))
{
mostLost = idx;
break;
}
/* This check is not expected to be necessary because the above test should always succeed
* with an early loop exit.
*/
else if (pgLost[idx] > pgLost[mostLost])
{
mostLost = idx;
}
}

pgRes = mostLost + OSAL_NV_PAGE_BEG;
erasePage( pgRes ); // The last page erase had been interrupted by a power-cycle.
}

return TRUE;
}

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

网站地图

Top