硬汉嵌入式论坛

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

[STM32H7] H723复位后发现两个应该相等的变量居然差1,脑袋已经想破了

[复制链接]

7

主题

24

回帖

50

积分

初级会员

积分
50
发表于 2025-1-16 14:32:47 | 显示全部楼层 |阅读模式
本帖最后由 regsofweb 于 2025-1-16 14:40 编辑

在ld中,定义了数据段
MEMORY
{
  BOOTFLAG (rw)        : ORIGIN = 0x00000000,   LENGTH = 32
  RAM_NOLOAD (xrw)     : ORIGIN = 0x00000020,   LENGTH = 4064
  ITCMRAM (xrw)        : ORIGIN = 0x00001000,   LENGTH = 60K
  DTCMRAM (xrw)        : ORIGIN = 0x20000000,   LENGTH = 128K
  FLASH    (rx)        : ORIGIN = 0x08000000,   LENGTH = 1024K
  RAM_D1  (xrw)        : ORIGIN = 0x24000000,   LENGTH = 320K
  RAM_D2  (xrw)        : ORIGIN = 0x30000000,   LENGTH = 32K
  RAM_D3  (xrw)        : ORIGIN = 0x38000000,   LENGTH = 16K
}

  ._ram_bootflag (NOLOAD) : /* Space before ':' is critical */
  {
    . = ALIGN(4);
  } >BOOTFLAG
  
ITCMRAM一共有64K,但是从0x00000000开始的32字节定义为一个段,存放复位标志和运行时间,设置为NOLOAD,避免编译器对其清零。


代码的部分:


//定义一个大数组,占用这32字节的空间
#define BOOTFLAG_UINT32_CNT 8


volatile uint32_t boot_flags[BOOTFLAG_UINT32_CNT] __attribute__((section("._ram_bootflag")));

extern __IO uint32_t uwTick;
// uwTickFreq is 1
// extern HAL_TickFreqTypeDef uwTickFreq;
volatile runningTime_t runningTime;
volatile time_t *psRunningSec = NULL;
#define RUNNING_MAGIC_NUMBER 0x1234567855aa33cc
// 覆盖原来的tick函数

void HAL_IncTick(void)
{
    // uwTick += uwTickFreq;
    uwTick++;
    if (++runningTime.tv_ms == 1000)
    {// 每秒更新
        runningTime.tv_ms = 0;
        runningTime.tv_sec++;
        if (psRunningSec != NULL)
        {// psRunningSec已经初始化过了
            psRunningSec[0] = runningTime.tv_sec; // 运行时间存入
            psRunningSec[1] = runningTime.tv_sec;
        }
    }
}



// 初始化时加载BOOTFLAG_RUNNING_SEC
void RunningInit(uint16_t cnt)
{
    ENTER_CRITICAL_pri();
    psRunningSec = &boot_flags[BOOTFLAG_RUNNING_SEC];
    runningTime.tv_sec = (psRunningSec[0] != psRunningSec[1] ||
                          psRunningSec[2] != RUNNING_MAGIC_NUMBER ||
                          psRunningSec[0] < EPOCH_2000 || psRunningSec[0] > EPOCH_2099)
                             ? EPOCH_2000
                             : psRunningSec[0];
    runningTime.boot_cnt = cnt + 1;
    psRunningSec[2] = RUNNING_MAGIC_NUMBER;
    EXIT_CRITICAL_pri();
}


现象:
系统启动,先运行BOOTFLAG_RUNNING_SEC是否合规。如果正确就加载,如果不正确就从EPOCH_2000开始。
系统运行的时候,在boot_flags[BOOTFLAG_RUNNING_SEC]的位置,有3个变量:
【0】runningTime.tv_sec
【1】runningTime.tv_sec
【2】RUNNING_MAGIC_NUMBER
在tick里面每秒更新运行的秒数

我使用仿真器运行,在任何地方暂停程序,可以看到【0】和【1】是相同的两个数


1.png

让程序继续运行,然后复位,无论是软复位,拉低nRST还是使用debug菜单里面的复位。在main的开始处设置断点,可以看到【1】比【0】要小1

2.png

这个很是怪异。

如果更改写的顺序:



            psRunningSec[1] = runningTime.tv_sec; // 运行时间存入
            psRunningSec[0] = runningTime.tv_sec;


就会出现【0】比【1】小1的情况

好像是第二行的写入被复位打断了。


我也试过不同的MPU的配置,无论设成write-through,noncache,device或strongly-ordered都一样

无法理解是哪里出了问题
回复

使用道具 举报

7

主题

24

回帖

50

积分

初级会员

积分
50
 楼主| 发表于 2025-1-16 15:24:55 | 显示全部楼层
把这32字节换了个位置,放在D1RAM的末端
MEMORY
{
  RAM_NOLOAD (xrw)     : ORIGIN = 0x00000000,   LENGTH = 4K
  ITCMRAM (xrw)        : ORIGIN = 0x00001000,   LENGTH = 60K
  DTCMRAM (xrw)        : ORIGIN = 0x20000000,   LENGTH = 128K
  FLASH    (rx)        : ORIGIN = 0x08000000,   LENGTH = 768K
  RAM_D1  (xrw)        : ORIGIN = 0x24000000,   LENGTH = 327648
  BOOTFLAG (xrw)       : ORIGIN = 0x2404FFE0,   LENGTH = 32
  RAM_D2  (xrw)        : ORIGIN = 0x30000000,   LENGTH = 32K
  RAM_D3  (xrw)        : ORIGIN = 0x38000000,   LENGTH = 16K
}

MPU里面设置0x2404FFE0的32字节为Write-through

居然TMD工作了,无论怎么复位,都可以正确读回。

看来ITCMRAM需要点骚操作才能玩啊
回复

使用道具 举报

4

主题

25

回帖

37

积分

新手上路

积分
37
发表于 2025-1-16 16:53:47 | 显示全部楼层
是每次都不一样还是偶尔
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2025-1-16 17:01:22 | 显示全部楼层
看了下楼主的描述,大意是不是设置了no init的变量,软件复位后,这个变量的值变了,是这样不
回复

使用道具 举报

0

主题

40

回帖

40

积分

新手上路

积分
40
发表于 2025-1-16 17:32:22 | 显示全部楼层
好像不能这么做,这个区域的电,要使能的,不是上电默认开启的
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2025-1-17 06:13:50 | 显示全部楼层
regsofweb 发表于 2025-1-16 15:24
把这32字节换了个位置,放在D1RAM的末端
MEMORY
{

是的,要设置的,我这个之前做了个整理

STM32H7软件复位NVIC_SystemReset后,各个RAM继续保持原有数据的问题总结(2019-10-03)
https://forum.anfulai.cn/forum.p ... 5217&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

7

主题

24

回帖

50

积分

初级会员

积分
50
 楼主| 发表于 2025-1-17 06:38:31 | 显示全部楼层
a13421364618 发表于 2025-1-16 17:32
好像不能这么做,这个区域的电,要使能的,不是上电默认开启的

使用的是ITCMRAM和D1RAM,不是D2
D2区需要使能
回复

使用道具 举报

7

主题

24

回帖

50

积分

初级会员

积分
50
 楼主| 发表于 2025-1-17 06:46:29 | 显示全部楼层
eric2013 发表于 2025-1-17 06:13
是的,要设置的,我这个之前做了个整理

STM32H7软件复位NVIC_SystemReset后,各个RAM继续保持原有数据 ...

这个贴我仔细看过,完全符合
当把bootflag放在ITCMRAM的0x00000000开始的32字节块里,
            psRunningSec[0] = runningTime.tv_sec; // 运行时间存入
            psRunningSec[1] = runningTime.tv_sec;
这个psRunningSec是uint64_t*,实际地址是在0x00000008。主要是为了保证数据完整性,所以把tv_sec存了两份。
苦恼在于,如果在仿真状态下暂停,可以看到【0】=【1】,表示【0】和【1】都写入了相同的值。但是如果发生复位,【1】就比【0】小1,好像只有【0】被写入,而【1】没有写入,还是上次的值。
回复

使用道具 举报

25

主题

233

回帖

308

积分

高级会员

积分
308
QQ
发表于 2025-1-17 09:07:59 | 显示全部楼层
time_t 是 64 位吗?
回复

使用道具 举报

7

主题

24

回帖

50

积分

初级会员

积分
50
 楼主| 发表于 2025-1-17 20:08:30 来自手机 | 显示全部楼层
yono 发表于 2025-1-17 09:07
time_t 是 64 位吗?

是的
为了避免2038的问题,在程序里判断sizeof(time_t)是不是8,如果是4,就输出错误
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117546
QQ
发表于 2025-1-18 08:47:12 | 显示全部楼层
regsofweb 发表于 2025-1-17 06:46
这个贴我仔细看过,完全符合
当把bootflag放在ITCMRAM的0x00000000开始的32字节块里,
            psR ...

MDK下,我整理的用法,确定是没问题的。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-14 03:08 , Processed in 0.047783 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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