gd32f103,定时器10ms一中断,让一变量自增,其他函数里根据这个变量计数100次后置位1秒标值。main函数主循环里判断该标志位是否置位,是1的话,让led反转,并清该标志位。
mdk工程,之前是-o3优化等级,运行后正常。硬件仿真时,我改成了-o1优化,发现运行大概20秒后,led就不正常反转了。
-o3优化:led每秒反转,正常;
-o2优化,前20秒led能每秒反转,然后就变成很快的频率闪烁了;
-o1优化,前20秒led能每秒反转,然后就变成很快的频率闪烁了;
-o0优化,前20秒led能每秒反转,然后就变成很快常亮了;
程序比较大,有modbus数据区,占几k字节。编译后也比较占资源。
-o3:
Program Size: Code=31348 RO-data=1104 RW-data=504 ZI-data=24368
-o2:
Program Size: Code=31408 RO-data=1104 RW-data=504 ZI-data=24368
-o1:
Program Size: Code=33712 RO-data=1204 RW-data=504 ZI-data=24368
-o0:
Program Size: Code=41236 RO-data=1204 RW-data=536 ZI-data=28656
看了下-o3和-o2,应该是rom只差1k左右。
芯片是gd32f105vc,我查gd32f103vc是48k ram, 256k rom.
10ms定时器中断里自增的变量是volatile类型的,该变量整除100时置位的bool类型变量,也是声明成volatile类型的。
最近编辑记录 Gentlepig (2023-10-20 17:41:19)
离线
硬件仿真,对比-o1情况下定时器的寄存器情况,前20面正常时和后来狂闪时,发现定时器的重载定时器和控制器寄存器1没有变化。
-o0情况下,程序运行20秒后卡死,发现尽到了HardFault_Handler()。
根据https://blog.csdn.net/electrocrazy/article/details/78173558
定位到是spi_flash_write()函数。
挨个注释main主循环里的函数,发现注释掉保存数据到spiflash这个函数后,程序正常运行。那么,问题应该就是出在spi_ flash_ write这个函数了,但是我看网上大部分教程,原子、野火,大都是这么写的:
void SPI_FLASH_Write ( u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite )
{
u32 secpos;
u16 secoff;
u16 secremain;
u16 i;
secpos = WriteAddr / 4096;
secoff = WriteAddr % 4096;
secremain = 4096 - secoff;
if ( NumByteToWrite <= secremain )
secremain = NumByteToWrite;
while ( 1 )
{
SPI_FLASH_BufferRead ( spiFlashBuff, secpos * 4096, 4096 );
for ( i = 0; i < secremain; i++ )
{
if ( spiFlashBuff[secoff+i] != 0xFF )
break;
}
if ( i < secremain )
{
SPI_FLASH_SectorErase ( secpos * 4096 );
for ( i = 0; i < secremain; i++ )
spiFlashBuff[i+secoff] = pBuffer[i];
SPI_FLASH_BufferWrite ( spiFlashBuff, secpos * 4096, 4096 );
}
else
SPI_FLASH_BufferWrite ( pBuffer, WriteAddr, secremain );
if ( NumByteToWrite == secremain )
break;
else
{
secpos++;
secoff = 0;
pBuffer += secremain;
NumByteToWrite -= secremain;
if ( NumByteToWrite > 4096 )
secremain = 4096;
else
secremain = NumByteToWrite;
}
}
}
而且,为何优化等级不同,结果却不同?
离线
有群友说,spi flash擦写比较耗时,然后我定时器中断比较频繁,我是用的10ms定时器。spi_flash_write()执行时,频繁中断耗尽了堆空间。
不过我还是不太明白...
离线
优化等级会改变程序行为,除了性能以外,多半是是用了未定义行为。
离线
问题找到了,在一个函数中,给某个数组赋值时,访问越界,比如int arr[8],结果我给arr[9]赋值了,于是进入hardfault_handler了。
更详细一点就是,本来NUMBER定义的比较小,这次我改大了,没注意到有个数组赋值时用到了这个宏定义。
//#define NUMBER 16
#define NUMBER 32
uint8_t arr[32];
for(u8 i = 0; i < 16+i+NUMBER; i++)
{
arr[i] = 1;
}
而这个函数里,还调用了spi_flash_write(),于是我就以为是spi_flash操作引起了错误。
这能解释-o0会进入hardfault_hander(),但是为什么-o3优化能正常运行?
-o1,o2 led狂闪?
最近编辑记录 Gentlepig (2023-10-21 16:01:47)
离线
@Gentlepig
有可能 -O3 把你这段优化成了上电直接初始化内存值,不用循环访问。
离线