rtthread

article/2025/8/25 22:05:18

链表

初始化双向链表

rt_inline void rt_list_init(rt_list_t *l)
{l->next = l->prev = l;
}

插入

rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{l->next->prev = n;n->next = l->next;l->next = n;n->prev = l;
}

在这里插入图片描述
NODE1后面插入节点n,可以理解为:NODE3的前一个结点为n,n的后一个节点为NODE3,NODE3l->next

删除

rt_inline void rt_list_remove(rt_list_t *n)
{n->next->prev = n->prev;n->prev->next = n->next;n->next = n->prev = n;
}

在这里插入图片描述

就绪列表

就是一个rt_list_t类型的数组。

/* 线程就绪列表 */
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

每个线程控制块都有一个成员tlist,类型为rt_list_t.我们将线程插入到就绪列表里面,就是通过将线程控制块的 tlist 这个节点插入到就绪列表中来实现的。

/* 初始化线程 */
rt_thread_init( &rt_flag1_thread,                 /* 线程控制块 */flag1_thread_entry,               /* 线程入口地址 */RT_NULL,                          /* 线程形参 */&rt_flag1_thread_stack[0],        /* 线程栈起始地址 */sizeof(rt_flag1_thread_stack) );  /* 线程栈大小,单位为字节 */
/* 将线程插入到就绪列表 */
rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );

系统调度初始化

/*** @ingroup SystemInit* This function will initialize the system scheduler*/
void rt_system_scheduler_init(void)
{register rt_base_t offset;/* 线程就绪列表初始化 */for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++){rt_list_init(&rt_thread_priority_table[offset]);}/* 初始化当前线程控制块指针 */rt_current_thread = RT_NULL;
}

此时的链表为空
在这里插入图片描述

启动调度器

/*** @ingroup SystemInit* This function will startup scheduler. It will select one thread* with the highest priority level, then switch to it.*/
void rt_system_scheduler_start(void)
{register struct rt_thread *to_thread;register rt_ubase_t highest_ready_priority;#if RT_THREAD_PRIORITY_MAX > 32register rt_ubase_t number;number = __rt_ffs(rt_thread_ready_priority_group) - 1;highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1;
#elsehighest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;
#endif/* get switch to thread */to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);rt_current_thread = to_thread;/* switch to new thread */rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);/* never come back */
}

临界段保护

PRIMASK寄存器

这个寄存器只有一个位,置1后,将关闭所有可屏蔽中断的异常,只剩NMI和硬fault,默认值为0

;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable    PROCEXPORT  rt_hw_interrupt_disableMRS     r0, PRIMASKCPSID   IBX      LRENDP;/*
; * void rt_hw_interrupt_enable(rt_base_t level);
; */
rt_hw_interrupt_enable    PROCEXPORT  rt_hw_interrupt_enableMSR     PRIMASK, r0BX      LRENDP

为什么不直接这样写?

;/*
; * void rt_hw_interrupt_disable();
; */
rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable
CPSID I
BX LR
ENDP;/*
; * void rt_hw_interrupt_enable(void);
; */
rt_hw_interrupt_enable PROC
EXPORT rt_hw_interrupt_enable
CPSIE I
BX LR
ENDP

避免在嵌套的临界段失效,如下所示

/* 临界段代码 */
{/* 临界段 1 开始 */rt_hw_interrupt_disable(); /* 关中断,PRIMASK = 1 */{/* 临界段 2 */rt_hw_interrupt_disable(); /* 关中断,PRIMASK = 1 */{}rt_hw_interrupt_enable(); /* 开中断,PRIMASK = 0 */ //(注意)}/* 这里已经开启了中断,而临界段1还未结束 *//* 临界段 1 结束 */rt_hw_interrupt_enable(); /* 开中断,PRIMASK = 0 */
}

正确做法如下:

PRIMASK = 0; /* PRIMASK 初始值为 0,表示没有关中断 */ 
rt_base_t level1;
rt_base_t level2;/* 临界段代码 */
{/* 临界段 1 开始 */level1 = rt_hw_interrupt_disable(); /* 关中断,level1=0,PRIMASK=1 */{/* 临界段 2 */level2 = rt_hw_interrupt_disable(); /* 关中断,level2=1,PRIMASK=1 */ {}rt_hw_interrupt_enable(level2); /* 开中断,level2=1,PRIMASK=1 */}/* 临界段 1 结束 */rt_hw_interrupt_enable(level1); /* 开中断,level1=0,PRIMASK=0 */ 
}

对象

软件定时器





http://chatgpt.dhexx.cn/article/GJ8mEJN0.shtml

相关文章

RT Thread根据开发板制作BSP方法

之前一直不懂怎么使用RT Thread的软件包&#xff0c;感谢网上的大神&#xff0c;看了你们的博客后大概了解一些&#xff0c;在此做下记录。用RT Thread软件包需要RT Thread的系统&#xff0c;但是RT Thread和RT Thread nano不一样&#xff0c;具体区别见 RT Thread官网&#xf…

rtthread开关中断

1 rtthread开关中断函数(cortex-m) /** rt_base_t rt_hw_interrupt_disable();*/ .global rt_hw_interrupt_disable .type rt_hw_interrupt_disable, %function rt_hw_interrupt_disable:MRS r0, PRIMASKCPSID IBX LR/** void rt_hw_interrupt_enable(rt_base_t le…

RTThread入门

RT-Thread入门 1.初识RT-Thread 嵌入式系统是一种完全嵌入在装置或设备内部&#xff0c;为满足特定需求而设计的计算机系统&#xff0c;譬如生活中常见的嵌入式系统就有&#xff1a;电视机顶盒、路由器、电冰箱、微波炉与移动电话等。 嵌入式操作系统是应用于嵌入式系统的软…

什么是RT-Thread?

一、RT-Thread的定义 RT-Thread&#xff0c;全称是 Real Time-Thread&#xff0c; 是一款主要由中国开源社区主导开发的开源实时操作系统&#xff08;许可证GPLv2&#xff09;&#xff0c;包含了实时、嵌入式系统相关的各个组件&#xff1a;TCP/IP协议栈、图形用户界面等。 相…

Redis启动失败的原因及解决方法

跑了近半年的Redis,今天早上来开启电脑运行程序的时候发现提示无法连接redis,暗想自己明明设置了开机自启的阿,以前也一直没问提,今天怎么就连不上了重启了下redis就提示如下错误 网上搜了好久都没找到解决办法,后来想起来去查看了下redis的日志文件 发现提示当前版本的redis无…

redis启动、获取密码及修改密码

一、启动redis服务的两种方式 查看密码是以redis服务已启动的前提下进行的&#xff0c;可直接在服务中右键启动redis或者安装根目录运行cmd输入《redis-server.exe》(不推荐不推荐不推荐&#xff0c;说三遍&#xff0c;命令行启动好像有bug&#xff0c;启动后redis能用&#x…

CentOS安装Redis及redis启动与关闭、配置(详细)

在项目使用redis过程中&#xff0c;在centos7上部署redis&#xff0c;查找相关资料并总结、记录&#xff0c;以备后续查看。 目录 一、Redis介绍 二、在CentOS上部署Redis 1、Redis安装包可以从官网上下载或者直接命令下载 升级到gcc 9.3&#xff1a; 3、Redis配置文件…

Redis启动和连接

一&#xff09;Redis简介 Redis不是简单的键值存储&#xff0c;它实际上是一个数据结构服务器&#xff0c;支持不同类型的值。 备注&#xff1a;由于我电脑是32位操作系统&#xff0c;所有就不提供redis软件下载地址了&#xff0c;请到官网下载使用。 软件解压之后&#xff0…

windows下Redis启动闪退问题解决经验汇总

最近使用Redis又遇到启动闪退的问题&#xff0c;之前记录的解决办法也失败了&#xff0c;一番研究后总算得到解决&#xff0c;感觉已经遇到了网上常见的各种问题&#xff0c;下面总结下。 我下载的是免安装版&#xff0c;解压便可使用。 官网下载传送门&#xff1a;Releases …

Windows下redis启动那些事儿

本文章主要描述我遇到的Windows下redis启动成功但Java项目无法连接问题 1.使用redis可视化工具可以连接&#xff0c;但是到Java项目中就报错连接失败 经过我的多方琢磨&#xff0c;还是密码没有配置正确&#xff0c;虽然是在redis.windows.conf配置文件中配置了 requirepass 密…

redis启动失败问题完美解决

1.输入启动命令redis-server.exe redis.windows.conf启动redis&#xff0c;发现启动失败报错&#xff1a;[8072] 07 May 09:28:52.241 # Creating Server TCP listening socket 127.0.0.1:6379: bind: No error D:\a\Main\redis> redis-server.exe redis.windows.conf[8072]…

windows redis启动

下载好redis后&#xff0c;只需解压。 然后打开dos窗口 进入redis解压目录 cd D:softwareRedis-x64-3.2.100运行下面命令启动 redis-server.exe redis.windows.conf成功启动 还可以把redis加入都开机自启动 redis-server --service-install redis.windows-service.conf …

redis启动和简单使用

redis启动和简单使用 1.redis启动 1.1 找到redis解压的位置,在里面输入cmd回车 1.2 输入redis-server redis.conf指令,然后回车,出现如下界面 注意&#xff1a;该界面不能关闭了 1.3 再进入一次redis解压的位置 输入cmd回车 1.4 输入redis-cli指令后的结果 1.5 补充 当出现…

Redis的启动方式三种

Redis的启动方式三种 启动一个 &#xff0c;进入到redis中的src目录下 在控制台输入指令&#xff1a;redis-server &#xff08;注意&#xff1a;这样启动默认端口是 6379 &#xff09; 进入客户端输入&#xff1a;redis-cli 查看进程&#xff0c;杀死进程 指定端口启动redi…

Redis的启动方法

一、Windows下 D: cd Redis //我的redis安装路径为D:\Redis redis-server.exe redis.windows.conf **如果报错creating server tcp listening socket 127.0.0.1:6379: bind No error D:\Redis>redis-cli.exe 127.0.0.1:6379> shutdown not connected> exit redi…

常见的配置中心:Apollo(二)-接入Apollo

1 配置 Apollo作为大型互联网系统生产级别的配置中心&#xff0c;在开发的积累当中构建了自己的配置维度体系。 1.1 配置四层维度 (1)Application(项目应用) 维度中的最顶层&#xff0c;在实际开发中我们一般以项目来作为最外层配置的区分维度。 (2)Environment(开发环境) …

apollo问题之 无法连接apollo配置中心

1.问题描述 1.1.现状场景 1.apollo的配置中心config-server 通过域名 http://demo-applo.wrok.com负载了两台机器10.10.10.02和 10.10.10.01 2.当前应用机器 可以访问并ping通 demo-applo.wrok.com域名 但是无法访问负载的机器1.2.报错信息 [demol-core-server:10.166.101.…

Apollo分布式配置中心(一)

目录 什么是配置&#xff1f; 什么是配置中心&#xff1f; 配置中心需要满足条件 什么是Apollo&#xff1f; Apollo特性 Apollo执行流程 Apollo安装 Git地址&#xff1a; 用户手册&#xff1a; 环境准备&#xff1a; 使用idea 的git clone 拉取源码 修改Apollo\scripts…

Apollo配置中心-手把手教你搭建Apollo配置中心运行环境

1、预置环境信息 运行环境 JDK > 1.8 具体安装及环境及环境变量配置这里不再赘述&#xff0c; 可自行查找资料。 2、下载程序包 演示版本使用的是apollo-1.9.2版本&#xff08;就是几个springboot的项目&#xff09; 应用包下载地址&#xff1a;https://github.com/apo…

Apollo 配置详解

Apollo的总体架构 Apollo的使用架构 Apollo的不同维度的配置分类 下面按照生效顺序 Application 在springboot的application.property定义appid这个key的value&#xff0c;标识该类型的应用。 Environment DEV&#xff08;开发环境&#xff09;FAT&#xff08;功能测试&#…