0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Ulog使用硬件RTC时间戳信号量锁死分析

冬至子 ? 来源:Code_Monkey ? 作者:Code_Monkey ? 2023-08-10 17:00 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、现象描述
在使能硬件RTC,初始化阶段未设置时间的情况下【测试环境为4.1.0版本Env创建的Keil工程】
如果开启Ulog时间戳,打印日志导致线程锁死

根本原因为打印时间戳日志的过程中由于未设置时间,导致再次调用日志打印,在以下函数中挂起线程

/* drv_rtc.c 文件 /
if (HAL_RTCEx_BKUPRead(&RTC_Handler, RTC_BKP_DR1) != BKUP_REG_DATA)
{
LOG_I("RTC hasn't been configured, please use command to config.");
/
其他代码省略 */
}
在LOG_I()中再次运行LOG_I()导致output_lock上锁两次
output_lock上锁本质为接收信号量ulog.output_locker
ulog初始化的信号量为1
第一次上锁信号量减一
再次调用LOG_I导致第二次上锁
第一次的锁还没有解开
第二次上锁导致锁死现象,直接挂起线程
Ulog无法输出任何信息

二、对比分析
由于之前使用RT-Studio的4.0.3版本可以正常输出提示

所以将4.1.0与4.0.3对比分析并排查问题

硬件平台:STM32F407 正点原子探索者开发板

以下表格是在进入主线程之前为未设置时间的RTC初始化流程对比

1.jpg

三、临时解决方案
方案一:避开初始化未设置时间的提示,增加RTC初始化函数,在进入主线程之前设置时间

缺点:如果真的忘记设置时间,导致死锁又要踩坑,花时间排查原因,影响开发进度

方案二:保留始化未设置时间的提示,避开第二次上锁,将 LOG_I 修改为 rt_kprintf

缺点:无论是否开启Ulog,依旧会有提示,其实影响不是很大,甚至在未开启Ulog也会有提示

? 【前提条件是开启了串口或者其他控制台输出,如果没开启控制台输出不知道会发生什么】

方案三:直接将未设置时间的提示注释掉,由于不会第二次上锁,所以日志打印正常

缺点:未设置时间不会提示

方案四:使用4.0.3版本

方案五:Ulog不使用时间戳格式

四、场景复现
理论上只要是STM32的单片机都会有这个问题,其他厂家的未测试过

以下测试平台以正点原子的探索者开发板为参考,场景复现大同小异

据说该开发板的启动电路的串口设置为控制台打印会有一些冲突

如果发现不能正常打印最好换一个串口或者使用RTT作为控制台输出

(1)锁死环境复现
打开 ···rt-threadbspstm32stm32f407-atk-explorer

右键打开Env 输入scons —dist

打开dist文件夹中新生成的bsp工程

右键打开Env 输入menuconfig

进入 RT-Thread Kernel -> Kernel Device Object 修改可以使用的控制台设备【如:uart1,jlinkRtt】

RT-Thread Comonents -> Device Drivers Using RTC device drivers

RT-Thread Comonents -> Utilities Enable ulog

log format -> Enbale timestamp format for time

Hardware Drivers Config -> On-chip Peripheral Drivers EnableRTC RTC_USING_LSE

Esc 然后选择Yes保存配置

打开 ···boardCubeMX_Config文件夹,配置CubeMX

打开Keil,复制生成的时钟配置,注释掉msp文件的Error_Handler()已防止后续编译错误

复制一下内容到 main.c 仅供参考

#include
#include
#include
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include
/* defined the LED0 pin: PF9 /
#define LED0_PIN GET_PIN(F, 9)
int main(void)
{
/
set LED0 pin mode to output */
rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
while (1)
{
rt_pin_write(LED0_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED0_PIN, PIN_LOW);
rt_thread_mdelay(500);
LOG_D("Hello RT-Thread!");
}
}
编译代码并下载到芯片,发现日志打印失败,灯不闪烁,此时 main线程已经挂起

(2)对比环境复现
测试平台为RT-Studio 2.2.1【其实和Studio版本关系不大】

基于芯片创建的RT-Thread工程

本文就不详细说明Studio的配置步骤了

以下图片为Ulog配置

复制上面的main函数,一切运行正常,并有未设置时间的提示

1.jpg

五、Ulog及RTC其它问题的吐槽
(1)部分设备注册的日志信息无法打印
主要原因是初始化顺序不可控,使用 INIT_BOARD_EXPORT(ulog_init);

不能保证在设备注册之前初始化

使初始化阶段部分打印之间 return

void ulog_voutput(······)
{
/* ······ /
if (!ulog.init_ok)
{
return;
}
/
······ */
}
例如以下打印在我的测试环境下就是直接 return

LOG_I("I2C bus [%s] registered", bus_name);
(2)STM32的LSE和LSI不能同时开启
为什么需要同时开启?

因为独立看门狗的时钟源是LSI

1.jpg

当使用LSE作为RTC的时钟源

如果关闭LSI是否会导致独立看门狗工作异常?【实际情况未测试,可能和初始化顺序有关】

具体看以下代码

/* drv_rtc.c */
static rt_err_t stm32_rtc_init(void)
{
__HAL_RCC_PWR_CLK_ENABLE();
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
#ifdef BSP_RTC_USING_LSI
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
#else
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
#endif
HAL_RCC_OscConfig(&RCC_OscInitStruct);
if (rt_rtc_config() != RT_EOK)
{
LOG_E("rtc init failed.");
return -RT_ERROR;
}
return RT_EOK;
}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RTC
    RTC
    +关注

    关注

    2

    文章

    624

    浏览量

    69099
  • STM32单片机
    +关注

    关注

    59

    文章

    550

    浏览量

    59675
  • STM32F407
    +关注

    关注

    15

    文章

    188

    浏览量

    30763
  • 独立看门狗
    +关注

    关注

    0

    文章

    25

    浏览量

    4174
  • HAL库
    +关注

    关注

    1

    文章

    121

    浏览量

    7015
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    FreeRTOS信号量使用教程

    信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步, FreeRTOS中信号量又分为二值信号量、 计数型信号量、互斥
    的头像 发表于 12-19 09:22 ?3916次阅读
    FreeRTOS<b class='flag-5'>信号量</b>使用教程

    Linux驱动开发笔记-自旋信号量

    :如果在写代码时,有以上的竞态发生,一定要注意进行互斥访问7.解决竞态的方法:中断屏蔽原子操作自旋信号量如何使用以上4个机制呢?1.中断屏蔽解决哪些情况的竞态:进程和进程的抢占中断和进程中断和中断
    发表于 08-30 18:08

    信号量、互斥、自旋

    信号量、互斥、自旋http://bbs.edu118.com/forum.php?mod=viewthread&tid=488&fromuid=231(出处: 信盈达IT技术社
    发表于 08-29 09:48

    信号量和互斥信号量的相关资料分享

    信号量简介信号量就是一个上锁的机制,代码必须获得钥匙才能执行,一旦获得了信号量,就相当于该代码具有了进入被代码的权限。说白了,就和java多线程中常用的
    发表于 03-02 07:11

    Ulog使用硬件RTC时间信号量的原因及解决方案

    一、现象描述在使能硬件RTC,初始化阶段未设置时间的情况下【测试环境为4.1.0版本Env创建的Keil工程】如果开启Ulog时间
    发表于 03-14 14:28

    ulog里现在默认的时间是从哪里获取的呢?

    我现在用的外部RTC,想在ulog里的时间显示外部RTC时间
    发表于 11-14 14:22

    ulog里用的时间是从哪里取的?

    我现在用的外部RTC,想在ulog里的时间显示外部RTC时间
    发表于 05-11 09:56

    你了解Linux 各类信号量

    内核信号量与用户信号量,用户信号量分为POXIS信号量和SYSTEMV信号量,POXIS信号量
    发表于 05-04 17:19 ?2682次阅读
    你了解Linux 各类<b class='flag-5'>信号量</b>?

    信号量和自旋

    自旋不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。自旋的基本形式如下:??? spin_lock(&mr_lock);
    发表于 04-02 14:43 ?917次阅读

    uCOS信号量源码的详细资料分析

    本文档的主要内容详细介绍的是uCOS信号量源码的详细资料分析信号量相关的函数 创建一个信号量,参数是信号量的初始值,创建成功返回值是
    发表于 06-17 17:38 ?7次下载
    uCOS<b class='flag-5'>信号量</b>源码的详细资料<b class='flag-5'>分析</b>

    Linux信号量(2):POSIX 信号量

    上一章,讲述了 SYSTEM V 信号量,主要运行于进程之间,本章主要介绍 POSIX 信号量:有名信号量、无名信号量。 POSIX 信号量
    的头像 发表于 10-29 17:34 ?976次阅读

    开源硬件信号量在行动

    电子发烧友网站提供《开源硬件信号量在行动.zip》资料免费下载
    发表于 11-16 10:22 ?0次下载
    开源<b class='flag-5'>硬件</b><b class='flag-5'>信号量</b>在行动

    FreeRTOS的二值信号量

    FreeRTOS中的信号量是一种任务间通信的方式,信号量包括:二值信号量、互斥信号量、计数信号量,本次实验只使用二值
    的头像 发表于 02-10 15:07 ?1824次阅读

    Free RTOS的计数型信号量

    上篇讲解了二值信号量,二值信号量只能判断有无,而不能确定事件发生的次数,因此我们为了确定事件的次数引入了计数型信号量
    的头像 发表于 02-10 15:29 ?1359次阅读
    Free RTOS的计数型<b class='flag-5'>信号量</b>

    使用Linux信号量实现互斥点灯

    信号量常用于控制对共享资源的访问,有计数型信号量和二值信号量之分。初始化时信号量值大于1的,就是计数型信号量,计数型
    的头像 发表于 04-13 15:12 ?1099次阅读
    使用Linux<b class='flag-5'>信号量</b>实现互斥点灯