#include <stddef.h>
#include <stdint.h>
#include "stm32h5xx_ll_rcc.h"
#include "stm32h5xx.h"
#include "tydefine.h"
#define isTAMPER1EN(x) isTAMPERPin1(x)
#define isTAMPERPin1(port, pin) (((port) == GPIOC) && ((pin) == 13))
#define isTAMPER2EN(x) isTAMPERPin2(x)
#define isTAMPERPin2(port, pin) (((port) == GPIOA) && ((pin) == 0))
#define isTAMPER4EN(x) isTAMPERPin4(x)
#define isTAMPERPin4(port, pin) (((port) == GPIOA) && ((pin) == 2))
#define isTAMPER5EN(x) isTAMPERPin5(x)
#define isTAMPERPin5(port, pin) (((port) == GPIOA) && ((pin) == 1))
// 定义获取 Tamper 值的宏
#define GET_TAMPER_VALUE(port, pin) \
(isTAMPERPin1(port, pin) ? 1 : \
(isTAMPERPin2(port, pin) ? 2 : \
(isTAMPERPin4(port, pin) ? 3 : \
(isTAMPERPin5(port, pin) ? 4 : 0))))
#define PIN_TAMPER1 GPIOC,13
#define PIN_TAMPER2 GPIOA,1
#define TAMPER1_SWT_RISE_DET TRUE
#define TAMPER2_SWT_RISE_DET FALSE
typedef struct {
uint32_t tamperConfig;
uint32_t tamperTrigger;
uint32_t edgeDetect;
} TamperConfig_t;
// Tamper 配置的二维数组
static const TamperConfig_t tamperConfigs[2][4] = {
{ // Tamper1 Configurations
{TAMP_CR1_TAMP1E, TAMP_CR2_TAMP1TRG, TAMPER1_SWT_RISE_DET},
{TAMP_CR1_TAMP2E, TAMP_CR2_TAMP2TRG, TAMPER1_SWT_RISE_DET},
{TAMP_CR1_TAMP4E, TAMP_CR2_TAMP4TRG, TAMPER1_SWT_RISE_DET},
{TAMP_CR1_TAMP5E, TAMP_CR2_TAMP5TRG, TAMPER1_SWT_RISE_DET}
},
{ // Tamper2 Configurations
{TAMP_CR1_TAMP1E, TAMP_CR2_TAMP1TRG, TAMPER2_SWT_RISE_DET},
{TAMP_CR1_TAMP2E, TAMP_CR2_TAMP2TRG, TAMPER2_SWT_RISE_DET},
{TAMP_CR1_TAMP4E, TAMP_CR2_TAMP4TRG, TAMPER2_SWT_RISE_DET},
{TAMP_CR1_TAMP5E, TAMP_CR2_TAMP5TRG, TAMPER2_SWT_RISE_DET}
}
};
/**
* @func halRtcCfgTamper
* @brief 侵入检测配置函数,启用RTC时间戳功能,默认边沿检测,如需更改为电平检测,修改为滤波模式
* @param TamperEnableBit: Tamper检测脚 TAMP_CR1_TAMPxE Vbat模式下(x=1,2,4,5)
* @param TamperTrgBit: 设置 Tamper检测脚边沿 TAMP_CR2_TAMPxTRG Vbat模式下(x=1,2,4,5)
* @param SwicthRiseEdgeTrg: Tamper检测触发边沿选择 FALSE - 下降沿触发, TRUE - 上升沿触发
* @retval None
*/
static void halRtcCfgTamper(uint32_t TamperEnableBit, uint32_t TamperTrgBit, bool SwitchRiseEdgeTrg)
{
// 不使用滤波,进行边沿检测
LL_RTC_TAMPER_SetFilterCount(RTC, LL_RTC_TAMPER_FILTER_DISABLE);
// 禁用上拉电阻
LL_RTC_TAMPER_DisablePullUp(RTC);
// 根据需要设置Tamper检测的触发边沿
if (SwitchRiseEdgeTrg)
{
// 上升沿产生Tamper事件
LL_RTC_TAMPER_DisableActiveLevel(RTC, TamperTrgBit); // 注意这里应该是 DisableActiveLevel 对应上升沿
LL_RTC_TS_SetActiveEdge(RTC, LL_RTC_TIMESTAMP_EDGE_RISING); // 设置TimeStamp检测边沿为上升沿
}
else
{
// 下降沿产生Tamper事件
LL_RTC_TAMPER_EnableActiveLevel(RTC, TamperTrgBit); // 注意这里应该是 EnableActiveLevel 对应下降沿
LL_RTC_TS_SetActiveEdge(RTC, LL_RTC_TIMESTAMP_EDGE_FALLING); // 设置TimeStamp检测边沿为下降沿
}
// TimeStamp功能使能
LL_RTC_TS_Enable(RTC);
// RTC Tamper-TimeStamp功能使能
LL_RTC_TS_EnableOnTamper(RTC);
// Tamper检测脚使能
LL_RTC_TAMPER_Enable(RTC, TamperEnableBit);
}
/**
* @func halRtcTamperInit
* @brief 侵入检测初始化函数
* 使用时需要在头文件中定义PIN_TAMPERx和TAMPERx_SWT_RISE_DET等宏
* @param None
* @retval None
*/
static void halRtcTamperInit(void)
{
// 获取 PIN_TAMPER1 和 PIN_TAMPER2 的 Tamper 值
uint32_t tamper1Value = GET_TAMPER_VALUE(PIN_TAMPER1);
uint32_t tamper2Value = GET_TAMPER_VALUE(PIN_TAMPER2);
// 配置 Tamper1
if (tamper1Value > 0 && tamper1Value <= 4) {
// 安全获取和配置
halRtcCfgTamper(tamperConfigs[0][tamper1Value - 1].tamperConfig,
tamperConfigs[0][tamper1Value - 1].tamperTrigger,
tamperConfigs[0][tamper1Value - 1].edgeDetect);
}
// 配置 Tamper2
if (tamper2Value > 0 && tamper2Value <= 4) {
// 安全获取和配置
halRtcCfgTamper(tamperConfigs[1][tamper2Value - 1].tamperConfig,
tamperConfigs[1][tamper2Value - 1].tamperTrigger,
tamperConfigs[1][tamper2Value - 1].edgeDetect);
}
}
/**
* @func halRtcTamperTimeGet
* @brief 获取掉电下侵入事件触发的时间,STM32H5只有一个TimeStamp,只能记录侵入事件最先发生的时间
* @param TamperType: 侵入事件类型; 0-侵入事件1; 1-侵入事件2;
* @param tCalendar: 日期时间 (STM32H5无年份记录)
* @retval FALSE-无侵入事件; TRUE-有侵入事件
*/
bool halRtcTamperTimeGet(uint8_t TamperType, tCalendar* calendar)
{
switch (TamperType)
{
/* 事件1检测 */
case 0:
{
if (LL_RTC_IsActiveFlag_TAMP1(RTC) && LL_RTC_IsActiveFlag_TS(RTC)) // 事件1
{
halRtcReadTimeStamp(calendar); // 读取RTC_TimeStamp
LL_RTC_ClearFlag_TAMP1(RTC); // 清除Tamper1事件标志位
/* 事件2未处理时不清除TimeStamp, 防止读事件2时间为0 */
if (1U == LL_RTC_IsActiveFlag_TAMP2(RTC))
{
return TRUE;
}
else
{
LL_RTC_ClearFlag_TS(RTC); // 清除TimeStamp标志位, 当该位被清除时, RTC_TSDR和RTC_TSTR寄存器都被重置
return TRUE;
}
}
else
{
return FALSE;
}
}
/* 事件2检测 */
case 1:
{
if (LL_RTC_IsActiveFlag_TAMP2(RTC) && LL_RTC_IsActiveFlag_TS(RTC)) // 事件2
{
halRtcReadTimeStamp(calendar); // 读取RTC_TimeStamp
LL_RTC_ClearFlag_TAMP2(RTC); // 清除Tamper1事件1标志位
/* 事件1未处理时不清除TimeStamp, 防止读事件1时间为0 */
if (1U == LL_RTC_IsActiveFlag_TAMP1(RTC))
{
return TRUE;
}
else
{
LL_RTC_ClearFlag_TS(RTC); // 清除TimeStamp标志位, 当该位被清除时, RTC_TSDR和RTC_TSTR寄存器都被重置
return TRUE;
}
}
else
{
return FALSE;
}
}
/* 可以添加其他case处理 */
default:
return FALSE; // 如果没有匹配的case,返回FALSE
}
}
- 通过一系列宏定义,代码实现了对不同 TAMPER 引脚的识别。在这里,开发者定义了一些宏来简化 TAMPER 引脚的启用和检测。
TamperConfig_t
结构体用来存储有关每个 TAMPER 的配置信息,包括使能位、触发位、引脚编号及边沿检测类型。tamperConfigs
数组定义了一组 TAMPER 配置,便于集中管理和初始化。每个结构体实例包含一个 TAMPER 的配置。- 函数
halRtcCfgTamper
此函数用于配置 TAMPER 功能,包括设置滤波器、使能上拉电阻以及根据选择的触发边沿(上升或下降)配置 TAMPER 检测。它采用三个参数:使能位、触发位以及边沿触发开关。 configureTamper
函数的目的是按配置启用或禁用相应的 TAMPER。它调用 isTamperEnabled
检测指定引脚是否启用,然后调用 halRtcCfgTamper
函数进行配置。- 该函数用于初始化所有 TAMPER 配置,它会循环遍历
tamperConfigs
数组,为每个 TAMPER 调用 configureTamper
进行配置。 - 此函数用于获取由 TAMPER 事件触发的时间戳,函数接受一个事件类型参数并读取 RTC 时间戳。如果发生特定的 TAMPER 事件并且时间戳有效,则返回
TRUE
,并将读取到的时间存入提供的 calendar
结构体。 - 整体而言,该代码用于配置和管理 STM32H5 MCU 的 TAMPER 相关功能,以提供防篡改保护机制。其功能包括对 TAMPER 引脚的检测与配置、事件时间记录等,适用于嵌入式系统中需要增强安全性与可靠性的应用场景。