【BLE】STM32WB55_定时器碎片(九)

文章目录

(一)硬件定时器开启前 停止操作

  1. 初始化定时器,重置参数,开启定时器,运行正常
  • 打了两个断点,看到正常运行通过
  1. 定时器开启后,重复开启定时器,再来一遍操作
  • 看到第二次启动定时器就进入错误中断中
  1. 定时器开启之前 先停止操作
  • 看到第二轮启动通过,不进入错误中断
  • 使用定时器17再验证一下结论,现象相同
  • 为什么会关注这个?因为发现在某项目中在某些用户操作逻辑下会有概率进入错误中断Error_Handler,然后回溯发现定时器启动失败导致的,
  • 结论【定时器开启前,先保护停止操作】

(二)定时器重复启动,为何会失败

  • 官方库函数中-启动的时候直接判断状态非就绪状态就错误
  • 那么对于调用,启动之前一定要是就绪状态
  • 顺便看看停止函数干了什么
  • 直接重置定时器状态为 就绪态

(三)定时器更新参数,常规流程

  1. 停止定时器:通过库函数(如 HAL_TIM_Base_Stop(&htimx) 或直接操作寄存器)禁用定时器计数器。
  2. 更新参数:安全地修改自动重载值(ARR)、预分频器(PSC)、比较/捕获值(CCR)等关键参数。
  3. 重新启动定时器:再次使能定时器计数器,使其从新参数开始运行。

(四)虚拟定时器,启动函数

c 复制代码
//枚举列出-虚拟定时器运行状态
typedef enum
{
  TimerID_Free,
  TimerID_Created,
  TimerID_Running
}TimerIDStatus_t;
c 复制代码
void HW_TS_Start(uint8_t timer_id, uint32_t timeout_ticks)
{
  uint16_t time_elapsed;
  uint8_t localcurrentrunningtimerid;

#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
  uint32_t primask_bit;
#endif
   
  //看看 启动的时候会判断定时器的状态 
  //如果是运行状态 会调用停止函数 停止定时器
  if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
  {
    HW_TS_Stop( timer_id );
  }

#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
#endif

  HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);    /**<  Disable NVIC */

  /* Disable the write protection for RTC registers */
  __HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );

  aTimerContext[timer_id].TimerIDStatus = TimerID_Running;

  aTimerContext[timer_id].CountLeft = timeout_ticks;
  aTimerContext[timer_id].CounterInit = timeout_ticks;

  time_elapsed =  linkTimer(timer_id);

  localcurrentrunningtimerid = CurrentRunningTimerID;

  if(PreviousRunningTimerID != localcurrentrunningtimerid)
  {
    RescheduleTimerList();
  }
  else
  {
    aTimerContext[timer_id].CountLeft -= time_elapsed;
  }

  /* Enable the write protection for RTC registers */
  __HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );

  HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**<  Enable NVIC */

#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
  __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
#endif

  return;
}

(五)IAR DEBUG模式 Call Stack(函数回溯)

  • IAR Call Stack窗口的功能详解

    在IAR的DEBUG模式下,Call Stack窗口为你提供了这个"调用堆栈"的可视化视图。它的核心作用是让你清晰地了解:当前程序执行到断点或暂停时,是经过怎样的函数调用链才到达当前位置的。

    通过菜单 View > Call Stack 可以打开该窗口。它通常显示以下关键信息:

  • 调用链:窗口以列表形式显示从 main 函数开始,到当前暂停位置(如断点处)的所有函数调用。

  • 最上面的一行是当前正在执行的函数,往下则是调用它的父函数,依此类推,直到最底层的 main 函数。

  • 位置信息:每一行通常会显示函数名以及该函数所在的源文件及行号。

  • 使用上面的Error_Handler();测试一下

  • 在Error_Handler中打一个断点,等运行到此处,使用Call Stack 回退到上一个函数

  • 通过黄色的箭头可以看到从哪里进入的,看到上一个函数,如下图所示


(六)STM32复位类型查看

复位类型 触发原因 CSR寄存器标志位 典型场景
上电/掉电复位 电源上电/掉电POR/PDR RCC_CSR_PORRSTF 开机、断电重启
外部复位 NRST引脚低电平(硬件复位) RCC_CSR_PINRSTF 按下复位按钮、外部电路触发
独立看门狗复位 IWDG超时(硬件看门狗) RCC_CSR_IWDGRSTF 程序卡死、看门狗未喂狗
窗口看门狗复位 WWDG超时(窗口看门狗) RCC_CSR_WWDGRSTF 低功耗模式下看门狗超时
软件复位 软件触发(如NVIC_SystemReset() RCC_CSR_SFTRSTF 程序主动复位(如错误处理)
低功耗复位 从待机/停止模式唤醒(LPWR) RCC_CSR_LPWRRSTF 从低功耗模式唤醒后复位
欠压复位 电源电压低于阈值(BOR) RCC_CSR_BORRSTF 电源不稳定、电池电压过低

关键点

所有复位标志位存储在 RCC_CSR寄存器低8位(位0-7)

复位后标志位自动置位,需手动清除(设置RCC_CSR_RMVF位)

SRAM数据:系统复位后可能保留,但不建议依赖此特性

  • 每次调试模式点击复位按钮,用示波器连接芯片复位脚观察到低电平,
  • 说明此复位是硬件引脚复位

  • 测试一下设置看门狗不喂狗,然后在调试模式运行,在看门狗复位中断处打断点,发现进入,
  • 说明看门狗复位已经发生,且获取到看门狗复位标志
c 复制代码
/**
 * @brief 判断并打印当前的系统复位原因

 */
void CheckResetSource(void) 
{
    int reset_count = 0;
    // 选项字节加载器复位
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_OBLRST) == SET) 
    {
        reset_count++;
    }
    // 引脚复位
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) == SET) 
    {
        reset_count++;
    }
    // 欠压复位(BOR)
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) == SET) 
    {
        reset_count++;
    }
    // 软件复位
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST) == SET) 
    {
        reset_count++;
    }
    // 独立看门狗复位
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) == SET) 
    {
        reset_count++;
    }
    // 窗口看门狗复位
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) == SET) 
    {
        reset_count++;
    }
    // 低功耗复位
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST) == SET) 
    {
        reset_count++;
    }

    // 在判断完复位原因后,清除所有标志
    __HAL_RCC_CLEAR_RESET_FLAGS();
}
相关推荐
yu85939584 小时前
STM32 智能红外循迹小车(含码盘测速 + 避障)
stm32·单片机·嵌入式硬件
三品吉他手会点灯4 小时前
STM32 DAP 烧录报错-最终解决方法的原理和操作逻辑
stm32·单片机·嵌入式硬件
fengfuyao9854 小时前
TFT 彩屏 GUI 开发
stm32·嵌入式硬件
yongui478345 小时前
STM32 三相电机FOC驱动方案(三电阻单电阻双模式)
stm32·单片机·嵌入式硬件
WeeJot嵌入式6 小时前
【串口】初始串口-轮询模式
stm32·单片机·嵌入式
LongRunning8 小时前
【BLE】STM32WB55_资料链接(八)
stm32
椰羊~王小美8 小时前
STM32加密
stm32·单片机·嵌入式硬件
Wave8459 小时前
STM32 启动模式与固件更新机制 (底层深度解析)
stm32·单片机·嵌入式硬件
椰羊~王小美10 小时前
STM32 和 51单片机
stm32·嵌入式硬件·51单片机