IAR9202 编译优化问题
遇到一个IAR编译优化的问题:
本想在profile中write callback中做特征值的有效性检查,却发现编译优化“high”和"medium"导致代码流程错误,如下:
#define CONST_DEF 16
//printf("xxxx\n");
if (pValue[0] > CONST_DEF) {
// do sth
} else {
// do sth
}
其中pValue[0]为channel数据,当优化选项为"high"时,pValue[0]为17时走的却是else分支,优化选项改为"medium",代码流程就没问题了。
另外在if之前添加一行printf,即便优化选项为"high"也没问题。通过C代码看不出问题。(IAR is cracked,stack is 1.4.1)
还想请问INIT_HEAD_LEN最小设为多大能够保证协议栈稳定运行,因为我需要1.5KB左右的buffer。
你在//do sth 处 加点代码试试看(有用处的代码,比如给一个会用到的全局变量复制等)。协议栈的优化选项默认是High,不要改。
INIT_HEAD_LEN 是什么?
Hi TY:
应该是INIT_HEAP_LEN默认的堆大小。
#define CONST_DEF 16
//printf("xxxx\n");
if (pValue[0] > CONST_DEF) {
// do sth1
} else {
// do sth2
printf("pValue[0]=%d, CONST_DEF=%d\n", pValue[0], CONST_DEF);
}
当pValue[0]为十进制17时,上面的打印信息为: "pValue[0]=17, CONST_DEF=16"
当pValue[0]为十进制18时,上面的的判断就没问题。
为什么优化只能是"High"?
谢谢。
你使用的是协议栈,包含Lib,代码是看不到的, 而在编译lib时,我们只能假设他用的优化等级就是high.
我认为是完全没必要去尝试改成另一个优化等级可能存在的问题的。
你的 pvalue是全局变量吗?
我不确定你是在什么代码里实验的,我把你的代码copy到例子代码里,判断完全没有问题。
pValue[0]=15;
while(pValue[0]++)
{
if (pValue[0] > CONST_DEF) {
PRINTF("pValue[0] > 16");
} else {
PRINTF("pValue[0] < 16");
}
}
另外,对应的stack用指定的IAR. 我碰到过使用新版本IAR编译没问题,但运行出未知问题的情况。
关于IAR版本比stack指定的版本新,运行出问题,那就是编译器的问题,我现在用的版本比1.4.1推荐的9.10要新。
pValue[0]代码在profile的写回调里面:
static bStatus_t xxx_WriteAttrCB(uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset, uint8 method)
****************
代码用于判断数据有效性,现在这种情况API是有问题的。
上面加的打印就是为了排除在判断时内存被篡改,现在可以排除。
所以怀疑编译器的问题,所以才先修改优化选项。Lib是什么优化等级对于最终的linker应该没影响,最终只是静态连接在一起,解决为定义符号。
Hi, TY:
我在官方的SimpleBLEPeripheral测试,问题依然,在SimpleGATTprofile.c中在以下位置添加测试代码:
static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
uint8 *pValue, uint8 len, uint16 offset,
uint8 method )
{
bStatus_t status = SUCCESS;
uint8 notifyApp = 0xFF;
// If attribute permissions require authorization to write, return error
if ( gattPermitAuthorWrite( pAttr->permissions ) )
{
// Insufficient authorization
return ( ATT_ERR_INSUFFICIENT_AUTHOR );
}
if ( pAttr->type.len == ATT_BT_UUID_SIZE )
{
// 16-bit UUID
uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
switch ( uuid )
{
case SIMPLEPROFILE_CHAR1_UUID:
case SIMPLEPROFILE_CHAR3_UUID:
//Validate the value
// Make sure it's not a blob oper
if ( offset == 0 )
{
if ( len != 1 )
{
status = ATT_ERR_INVALID_VALUE_SIZE;
}
}
else
{
status = ATT_ERR_ATTR_NOT_LONG;
}
//Write the value
if ( status == SUCCESS )
{
checkValue(pValue); <---------------------------------------------测试代码!
#if 0
uint8 *pCurValue = (uint8 *)pAttr->pValue;
*pCurValue = pValue[0];
if( pAttr->pValue == &simpleProfileChar1 )
{
notifyApp = SIMPLEPROFILE_CHAR1;
}
else
{
notifyApp = SIMPLEPROFILE_CHAR3;
}
#endif
}
其中checkValue(uint8* pValue)定义如下:
#define CONST_DEF 16
static bool checkValue(uint8* pValue) {
uint8 value = pValue[0];
if (value > CONST_DEF) {
printf("Invalid value: %d\n", value);
return FALSE;
} else {
printf("value=%d, CONST_DEF=%d\n", value, CONST_DEF);
}
return TRUE;
}
结果向Char1写入0x11,打印为“value=17, CONST_DEF=16”
编译优化改为“meduim”就可以了。
请指教。谢谢
建议用9.10.3的版本尝试看看,我也不清楚编译器具体做了什么优化处理。.
非常感谢TY的耐心解答。
我用的是9.20,如果改为9.10.3会有编译问题,请问除了重新建立工程,有什么快速修改工程的办法可以兼容低版本的IAR吗?
还有cc2540协议栈稳定运行需要多大内存,如果将INIT_HEAP_LEN堆大小设为2048会影响到协议栈的稳定性吗?
谢谢。
老实讲,没有所谓的快速修复方法,我之前碰到过类似的问题,这个是协议栈和IAR的版本有一定的关联。你只能认为,1.4.1的版本TI只在IAR的9.10.3上做过测试。
最快的方法反而是,你使用IAR9.10.3, 使用STACK的例子,然后把你的程序仔细的挪过来。
INIT_HEAP_LEN是堆,可以动态分配和释放的,你可以考虑改小. 同样要注意的是,协议栈底层也使用了这个堆的(我们也看不到代码,不能确定是怎么使用?用了多少),既然你减小了这个,你的应用就尽量少用或者及时释放。
额,我想知道的就是协议栈Lib会大概能用到多少内存。
不过还是要感谢你的解答,谢谢。
这个问题,可以到e2e去问下. lib里的东西那里可能有人知道。
https://e2e.ti.com/support/wireless_connectivity/
谢谢!
Hi, TY:
刚刚更换了IAR9.10.3,问题仍然存在,有时候编译出的代码没问题,有时候编译出的还是有问题啊。
你们没有遇到过吗?