踩坑记 BSS段的初始化


title: 踩坑记 BSS段的初始化
category_bar: true
categories:

  • blog
    tags:
  • embedded
    date: 2023-10-20 19:23:05

前言

接手一个项目,调试全靠串口日志,测试同事测试产品的时候无法拿到日志,刚好产品RAM够大,且刚好有SD卡。所以就诞生了将日志缓存在RAM上,在特定条件下将它写到SD卡上的想法。
.
.
.
开工。
.
.
.
写完代码之后发现机器偶尔会无法启动,无法开机,无任何日志。
.
有的时候是烧录完成代码后重启无法启动,有些情况下是烧录完成代码后运行正常,放置一段时间后无法启动
.
有时候有些无法启动的机器放置一段时间又成功启动
.
.
.
一段一段代码,屏蔽,编译,验证,发现一个非常无法理解的事,TFCardLogBufferPut函数注释后设备可以正常启动。
.
.
.
看代码:

#define TF_CARD_LOG_BUFFER_SIZE     (64*1024ul)
uint8_t tfCardLogBuffer[TF_CARD_LOG_BUFFER_SIZE] = {0};
uint32_t tfCardLogBufferIndex = 0;

void TFCardLogBufferPut(uint8_t data) {
    tfCardLogBuffer[tfCardLogBufferIndex] = data;
    tfCardLogBufferIndex++;
    if( tfCardLogBufferIndex>=(sizeof(tfCardLogBuffer)/sizeof(tfCardLogBuffer[0]))-1 ) {
        tfCardLogBufferIndex = 0;
    }
}

.
.
.
我实在无法理解,这段代码是如何导致设备无法启动的,后面搁置了一段时间,遂归结于小众芯片不完善导致。
.
.
.
但是后面这个需求实在是过于旺盛,遂重新开始验证代码。

当时代码是这样的:

// main.c
int main(int argc, char **argv) {
    
    hal_uartInit();
    ax32xx_uart0SendByte('a');
    ax32xx_uart0SendByte('b');
    hal_uartSendData('1');
    hal_uartSendData('2');
    ax32xx_uart0SendByte('c');
    
    hal_sysInit();
    
    //.... some code here
}

// uart.c
void hal_uartSendData(u8 data)
{
    ax32xx_uart0SendByte(data);
    
    TFCardLogBufferPut(data);
}

void ax32xx_uart0SendByte(u8 data)
{
    R_UART_DATA0 = data;
    while((R_UART_PEND0 & 0x2)==0);
    R_UART_PEND0 |= 1;
}

#define TF_CARD_LOG_BUFFER_SIZE     (64*1024ul)
uint8_t tfCardLogBuffer[TF_CARD_LOG_BUFFER_SIZE] = {0};
uint32_t tfCardLogBufferIndex = 0;

void TFCardLogBufferPut(uint8_t data) {
    tfCardLogBuffer[tfCardLogBufferIndex] = data;
    tfCardLogBufferIndex = (tfCardLogBufferIndex>=(sizeof(tfCardLogBuffer)/sizeof(tfCardLogBuffer[0]))-1) ? 0 : tfCardLogBufferIndex+1;
}

运行后日志是这样的:

# 正常运行 的日志
ab12c ...

# 无法启动 的日志
ab1

.
.
.
后面我就猜想了很多:

  • 这个soc不能支持这么大的数值 64KB
  • 这个位置的内存被改写了
  • 和冷启动热启动有关
  • 芯片异常

.
.
.

后面我猜想,试试把TFCardLogBufferPut函数里面的tfCardLogBufferIndex的数值和data数值输出出来看看。
.
.

这一看不得了,越界了!

代码:
代码

输出日志:

ab1z31m00327300

.
.
.

这个tfCardLogBufferIndex越界了啊!而且初始化赋0并没有成功!这就非常坑爹了!
.
.
.
后面尝试在调用这个函数之前再次赋0,发现程序运行正常,设备也正常启动。

查看map文件这个数组和变量也是存放在BSS段的,这就非常令人费解了。
.
.
.
.
.
看到这里我直接就怀疑,就是这个芯片的锅。

但是别急这还不是让人最震惊的!后面还有让人更加鼻血飙升的。
.
.
.
.
.
.
.
.
.
.
.
.
.

最后找FAE排查问题很久,最后发现BSS段在hal_sysInit函数内初始化。

看代码:

void ax32xx_sysInit(u32 *saddr,u32 *eaddr)
{
	debg("sys init\n");			// 这个debg会调用 hal_uartSendData 函数输出日志
    
    //...
    
	ax32xx_wdtClear();

//-----cache set
	ax32xx_sysIcacheInit();
	ax32xx_sysDcacheInit();	
//-----bss clear
	ax32xx_sysBSSClear();
    
    // ...
}

.
.
.

实在是震惊,无法理解这个RAM的初始化为什么放在main函数里面,实在无法理解进入main函数了,c语言环境都没有OK。

最烦的就是这种xx芯片,总是会有一些让人血压飙升的操作。

.
.
.
.
.

教训

在对数组进行访问的时候一定要先检查范围。

// 原函数
void TFCardLogBufferPut(uint8_t data) {
    tfCardLogBuffer[tfCardLogBufferIndex] = data;
    tfCardLogBufferIndex = (tfCardLogBufferIndex>=(sizeof(tfCardLogBuffer)/sizeof(tfCardLogBuffer[0]))-1) ? 0 : tfCardLogBufferIndex+1;
}

// 改后
void TFCardLogBufferPut(uint8_t data) {
    if( tfCardLogBufferIndex>=(sizeof(tfCardLogBuffer)/sizeof(tfCardLogBuffer[0]))-1 ) {
        tfCardLogBufferIndex = 0;
    }
    tfCardLogBuffer[tfCardLogBufferIndex] = data;
    tfCardLogBufferIndex++;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值