硬汉嵌入式论坛

 找回密码
 立即注册
查看: 988|回复: 13
收起左侧

[Flash] [求助]stm32H563 IAP后 CRC检查卡死

  [复制链接]

0

主题

7

回帖

7

积分

新手上路

积分
7
发表于 2024-8-6 05:28:24 | 显示全部楼层 |阅读模式
本帖最后由 zexalistic 于 2024-8-6 05:39 编辑

用的芯片是stm32h563MIY,在FreeRTOS里做一个简单的AB image的IAP升级,代码是在flash里跑。跑的是image A, 升级的是image B,两个image分别放在不同的flash bank里所以不会影响中断。

IAR前半部分把新的imageB写入flash的部分都成功了,在最后结束的时候想对新的image做一下CRC检验, 然后程序就会卡死。把CRC 校验那部分代码注释掉就可以顺利运行结束。

卡死后重启, bootloader还是能回到image A,并且把image B对应区域的flash读了一下发现image B其实都写进去了。

在我程序一开始的时候,会先对当前image的crc做校验,所以crc校验函数本身应该没有溢出等问题。

因为硬件连接的关系,这个问题没办法用stlink直接去看有没有hardfault,但是猜测大概率是跑飞了。

之前在用stm32h563MIY的时候也出现过类似CRC卡死的情况,当时用stlink看的是程序在做CRC的时候跑飞越界了。后来也都是莫名其妙地解决了(当时对问题理解不深,尝试写过flash control register),一旦解决后这块芯片就再也不会出现flash读卡死的情况了。可是同样的代码换到新的芯片上大概率还是会出问题。

CRC 采用的是软件crc16的做法,核心就是通过这个函数配合着查表。


// CRC16-ARC
unsigned short do_crc_table(unsigned char *ptr, int len)
{
    unsigned short crc = 0x0000;

    while(len--)
    {
        crc = (crc >> 8) ^ crc_table[(crc ^ *ptr++) & 0xff];
    }

    return (crc);
}

就很像是因为前面的flash写操作没弄好造成了flash状态机异常,flash被锁住了所以读不了。但是想不清楚为啥会造成异常。

不知道有没有大腿在用H系列的flash的时候也遇到过类似的问题。。着实是百思不得其解






回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-6 12:47:41 | 显示全部楼层
计算软件CRC异常,确实诡异。可以这样排查,让这个软件CRC计算别的地方存储的数据,看看是否异常,如果没有,应该是更新的IMAGE B有问题。建议IAP操作的所有返回值都判断下
回复

使用道具 举报

3

主题

295

回帖

304

积分

高级会员

积分
304
发表于 2024-8-6 13:58:47 | 显示全部楼层
把写flash的函数注释掉,上电只计算另一个bank的CRC试试,连不了stlink就尝试把flash相关的寄存器值给打印出来,看不写flash和写flash的寄存器区别在哪,我估计是寄存器哪里有错误标志没清除,所以读会出问题
回复

使用道具 举报

0

主题

39

回帖

39

积分

新手上路

积分
39
发表于 2024-8-6 14:47:02 | 显示全部楼层
这个你要查你的FLASH的手册,是不是带ECC校验的,如果有,在每次操作前都要清理状态。。。
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2024-8-7 08:40:18 | 显示全部楼层
今天又debug了一下差不多找到原因了。

1. 在升级完image B后,对image A做CRC是可以的
2. 对image A做完CRC以后跳转,程序卡死
3. 之后重新swd烧写bootloader,image A启动也会卡死

最后我想起了之前一次修flash问题的经验,在keil里用swd把整个flash都擦除了一下,然后重新load bootloader,然后IAP就顺利工作了。

所以我问题的关键在于,我的bootloader里头只有image A和bootloader头,没有Image B。

所以看起来很像是stm32h563在出厂的时候对flash有保护。SWD烧写的时候,烧写器会自动把相关部分的flash保护打开。可是如果IAP写了其他区域的话,因为那部分flash保护还在,就会让状态机乱掉。
而swd擦除整片flash的副作用就是把保护位顺手都擦掉了,所以就不会再出现那个情况。

后面我再找块新的开发板试一试这个想法,看看如果bootloader里如果包含imageA+imageB是不是不需要整片擦除也不会有这个问题。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-7 09:17:52 | 显示全部楼层
zexalistic 发表于 2024-8-7 08:40
今天又debug了一下差不多找到原因了。

1. 在升级完image B后,对image A做CRC是可以的

如果你没有让SWD操作选项字节,也就是Flash的读写保护。他是不会去操作这个的。

另外H5的代码有个secure和非secure方式,你的工程代码都用非secure方式创建试试。
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2024-8-7 12:00:22 | 显示全部楼层
eric2013 发表于 2024-8-7 09:17
如果你没有让SWD操作选项字节,也就是Flash的读写保护。他是不会去操作这个的。

另外H5的代码有个secu ...

Umm我一直都是用non secure方式去做的。
理论上确实swd不应该影响这个,但是实践中erase了以后确实就没这个问题了
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2024-8-19 06:02:39 | 显示全部楼层
最后自己找到问题了。。跑飞的原因感觉像是stm32h563自身cache的一个bug,在我计算crc的时候触发了。。我把计算crc的临时变量改成volatile就好了。。。

不知道这种硬件Bug官网有没有有奖征集什么的
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2024-8-20 09:22:47 | 显示全部楼层
zexalistic 发表于 2024-8-19 06:02
最后自己找到问题了。。跑飞的原因感觉像是stm32h563自身cache的一个bug,在我计算crc的时候触发了。。我把 ...

H5没有ICache和DCache,加上volatile解决了,应该是优化问题。
回复

使用道具 举报

8

主题

65

回帖

89

积分

初级会员

积分
89
发表于 2024-8-20 17:07:13 来自手机 | 显示全部楼层
zexalistic 发表于 2024-8-19 06:02
最后自己找到问题了。。跑飞的原因感觉像是stm32h563自身cache的一个bug,在我计算crc的时候触发了。。我把 ...

局部变量加volatile关键字解决了问题,有点神奇。不过我确实看到过有局部变量加这个关键字的源代码。有违常理,一般是全局变量或变量强制类型转换加volatile关键字。
楼主能仔细说说调试过程吗,或者是随便加了这个试试运气解决了。我相信一定用了各种各样调试方法。
回复

使用道具 举报

8

主题

65

回帖

89

积分

初级会员

积分
89
发表于 2024-8-20 17:11:31 来自手机 | 显示全部楼层
volatile static unsigned short crc = 0x0000;容易理解,静态全局变量加这个关键字,常见。volatile unsigned short crc = 0x0000;解决问题了,不常见。
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2024-8-24 01:46:51 | 显示全部楼层
lb1057907736 发表于 2024-8-20 17:07
局部变量加volatile关键字解决了问题,有点神奇。不过我确实看到过有局部变量加这个关键字的源代码。有违 ...

嗯就是首先锁定问题:如果升级的过程中没有crc检查的话,image B->A这个过程是可以正常过并且跳转到image A正常跑。如果带上CRC检查,image B->A就一定会卡在升级结束前的crc检查里头,并且卡在固定位置SPI2_error_handler.可是系统里SPI2当时并没有被enable,所以怀疑是类似野指针这种感觉。然后打开汇编仔细看了一下,感觉唯一能让系统跑飞的也就这句了。
> MOV r0,#0xfe14
> MOVT r0,#0x803
> LDRH r0,[r0, r2, LSL, #1]
然后就想着绕开从flash立即数直接取值,先让数据在寄存器里头绕一圈。然后就加的volatile。
不知道怎么加图片。。st论坛里我也post一个帖子,链接是这个https://community.st.com/t5/stm3 ... /m-p/710508#M258315
那边放了当时assembly的截图
回复

使用道具 举报

8

主题

65

回帖

89

积分

初级会员

积分
89
发表于 2024-8-24 10:08:15 来自手机 | 显示全部楼层
volatile unsigned short crc = 0x0000;与unsigned short crc = 0x0000;没有任何区别。但解决了问题。
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2024-8-28 02:00:40 | 显示全部楼层
lb1057907736 发表于 2024-8-24 10:08
volatile unsigned short crc = 0x0000;与unsigned short crc = 0x0000;没有任何区别。但解决了问题。

assembly层面还是有区别的。一个从flash直接拿,一个从寄存器饶了一圈。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-29 03:06 , Processed in 0.294134 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表