使用 ST-LINK 实用程序将 RTC 配置为当前时间

电器工程 stm32 实时时钟
2022-01-08 07:31:45

我在做什么

我正在使用 STM32 微控制器,对于我的项目,我需要能够在一天中的特定时间(例如,上午 11 点和下午 2 点)发送数据。在我能做到这一点之前,微控制器需要知道现在是什么时间。不幸的是,我只有单向通信,因此我无法从网络中请求当前时间。

因此,我想在完成编程后直接设置当前时间。我知道我可以使用 ST-LINK Utility 命令行界面 (ST-LINK_CLI) 使用以下命令将数据写入闪存:

ST-LINK_CLI.exe -w32 <Address> <data> -Rst

我编写了一个简单的测试脚本,将 Unix 时间戳写入代码当前未使用的某个地址。

我正要编写一个函数来读取时间戳并使用它来设置 RTC 时间。直到我在ST-LINK 实用程序用户手册中阅读以下内容:

-w32 支持写入闪存、OTP、SRAM 和 R/W 寄存器。

当手册说它支持写入 R/W 寄存器时,这是否意味着我可以直接访问 RTC 寄存器并设置它们?我试过了,但我似乎无法写入这些寄存器。

如果确实如此,我更愿意使用这种方法,因为我不再需要编写特定的函数来在微控制器上处理它。这意味着我可以设置我们当前使用的任何微控制器的 RTC 时间,而无需更新它们的代码。


我打算做什么

要设置 RTC 寄存器,我尝试执行以下步骤,如STM 参考手册中所述:

  • 在 PWR_CR 寄存器中设置 DPB 位
  • 将 0xCA 写入 RTC_WPR 寄存器
  • 将 0x53 写入 RTC_WPR 寄存器
  • 通过设置 RTC_ISR 寄存器中的 INIT 位来停止 RTC
  • 通过写入 RTC_PRER 寄存器选择 1Hz 时钟
  • 通过写入 RTC_TR 寄存器加载当前时间
  • 通过写入 RTC_DR 寄存器加载当前日期
  • 通过复位 RTC_ISR 寄存器中的 INIT 位启动 RTC

为了访问寄存器,我使用了以下地址:

  • PWR_CR:0x4000 7000
  • RTC_WPR:0x4000 2824
  • RTC_ISR:0x4000 280C
  • RTC_PRER:0x4000 2810
  • RTC_TR: 0x4000 2800
  • RTC_DR: 0x4000 2804

什么地方出了错

我无法写入这些寄存器中的任何一个。使用 ST-LINK 实用程序,我收到以下消息:

写入内存时出错!

使用 ST-LINK_CLI:

在 0x40007000 处写入 0x00000100...错误!

读取这些寄存器没有问题,但我无法使用 ST-LINK 实用程序或其命令行界面写入它们。


问题

如何使用 ST-LINK 实用程序写入 R/W 寄存器?

是否有某种写保护允许写入我忽略的 RTC 寄存器?

3个回答

某些寄存器仅对特定访问宽度合法(即 -w32 可能不正确),或者可能无法读回写入的值,这可能会导致验证出现问题。

访问事物也可能存在顺序或状态限制。

一个可以解决大多数可以想象的问题的选项是制作一个小程序来完成与在 RAM 中运行相关的工作。您可以在计算出偏移量后将数据替换为其二进制文件,上传修改后的版本并运行它。或者,您可以让程序从文件范围之外的 RAM 区域获取值,您将在运行之前设置该值。通过对 stlink 进行更细粒度的控制,您还可以在 CPU 寄存器中传递值,尽管您可能(?)需要备用开源命令行程序而不是 ST 来做到这一点(RAM 方法中的这个小例程顺便说一句,该程序是如何完成写入的闪烁)

因此,正如 Chris Stratton 指出的那样,问题之一是:

某些寄存器 .. 可能无法读回写入的值,这可能会导致验证出现问题。

这意味着验证失败,导致错误显示,即使写操作实际上成功了。

下面是我在读取 PWR_ISR 寄存器、设置 INIT 位、然后再次读取寄存器时得到的响应:

0x4000280C:00000027

在 0x4000280C 处写入 0x00000080 ...错误!

0x4000280C:000000A7

ST-LINK Utility 的验证检查写入地址和从地址读取的值是否匹配。在这种情况下,写入操作是成功的,即使两个值不匹配,因为现在设置了 INIT 位。

另一个问题是我没有注意到写操作的效果。当连接到微控制器时,它被 ST-LINK 保持在复位状态(称为“复位连接”)。我需要使用 HOTPLUG 连接选项,它连接到微控制器而无需停止或重置。

“connect under reset”选项允许在执行任何指令之前连接到目标。这在许多情况下很有用,例如当目标包含禁用 JTAG/SWD 引脚的代码时。

“HotPlug”选项允许在不停止或重置的情况下连接到目标。这对于在应用程序运行时更新 RAM 地址或 IP 寄存器很有用

批处理文件完全按照我的意愿工作!该命令现在看起来像这样:

ST-LINK_CLI.exe -c HOTPLUG -w32 <Address> <data> -w32 <Address> <data> ...

我认为正在发生的事情是在写入之后,执行了验证读取。如果同一寄存器在读取时返回当前时间,尽管您成功更新了 RTC,但调试器不会意识到这一点。这不太可能解释电源寄存器的问题(除非调试器也在后台访问该寄存器)。手动检查读取值。如果存在更严重的问题,则此读取也可能会失败。另外,尝试列表中的其他寄存器。