嵌入式实时操作系统笔记2:UCOS基础知识_UC/OS-III移植(STM32F4)_编写简单的UC/OS-III任务例程(失败.....)

news2024/9/21 14:29:06

 今日学习嵌入式实时操作系统RTOS:UC/OS-III实时操作系统

本文只是个人学习笔记备忘用,附图、描述等 部分都是对网上资料的整合......

文章主要研究如何将UC/OS-III 移植到 STM32 F407VET6上,提供测试工程下载

 (2024.5.21 文章未写完,测试有问题,以后再说)

 (2024.5.22 系统移植失败,测试有问题,以后再说)

 附言:网络上的资料真是参差不齐,整整浪费我一天时间......

目录

UCOS基础知识:

任务的五种状态:

 任务五种状态转换图:

UCOS-III的三大列表:

UCOS-III系统配置文件说明:

UC/OS-III移植(STM32F4):

添加 UC/OS-III 源码部分:

修改system_stm32f4xx.s启动文件代码:

修改/确定 系统时钟(SysTick)内核:

修改CONFIG/app_cfg.h:

修改CONFIG/includes.h :

尝试编写简单的 UC/OS-III 任务例程:

先引用头文件:

定义任务栈大小/优先级:

定义任务控制块TCB:

定义任务栈:

定义任务主体函数:

创建任务TASK1-2-3:

CPU_SR_ALLOC();  

OS_CRITICAL_ENTER();  

OS_CRITICAL_EXIT();

启动UCOS III 系统函数:

主函数调用情况展示:

测试效果展示:

整体测试工程下载:

网上学习资料网址贴出:


UCOS基础知识:

任务的五种状态:

 任务五种状态转换图:

1、被创建的任务,初始状态均为就绪态
2、被删除的任务,会转为休眠态
3、仅就绪态和中断态可转变成运行态
4、其他状态的任务想运行,必须先转变成就绪

UCOS-III的三大列表:

UCOS-川主要有三大类列表用来跟踪任务状态:


就绪列表  准备运行的任务将放在就绪列表:OSRdyList[x],其中x代表任务优先级数值
Tick列表   正在等待延时超时或挂起的对象超时的任务,将放在OSTickList
挂起列表   当任务等待信号量、事件时,任务将放置在挂起列表PendList

UCOS-III系统配置文件说明:

以下就是我们接下来需要移植的 部分文件,他们的作用大致各自如下:

UC/OS-III移植(STM32F4):

本次尝试移植UC/OS-III 于立创梁山派天空星开发板上,芯片型号是STM32F407VET6

其中UC/OS-III 的源码可以在整体工程下载中的压缩包内找到

注意:这里的源码是被我阉割过的,削除了官方文件中不必要的文件与目录

其次就是网络上那些所谓提供UC/OS源码或者教程的,如果没有移植成功的工程供下载的案例,基本都是垃圾!浪费时间!不是缺少文件,就是解释不详细,缺步漏步!

本人也是在艰难的学习中掉进太多移植源码方面的坑里了.........

添加 UC/OS-III 源码部分

在工程中新建几个分组:

uC-OS3/CPU

uC-OS3/LIB

uC-OS3/PORT

uC-OS3/SOURCE

uC-OS3/CONFIG
 

点击uC-OS3/CPU–>Add Files

UC-OSIII/CPU添加以下文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/CPU–>Add Files

UCOSIII\bsp添加以下文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/LIB–>Add Files

UCOSIII\uC-LIB添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/PORT–>Add Files

UCOSIII\uCOS-III\Ports添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/SOURCE–>Add Files

UCOSIII\uCOS-III\Source添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

uC-OS3/CONFIG添加文件:

UCOSIII\config添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

最后别忘记在魔棒中添加各个文件路径:

补:补充添加一条bsp的路径,之前忘记添加了,导致报错......

添加结束,编译看看有无报错缺漏:

这里也是完美无报错的典范了哈哈哈......

修改system_stm32f4xx.s启动文件代码:

打开工程自带的 system_stm32f4xx.s启动文件(这是启动文件,不是UC/OS源码!)

我们需要对其进行一些修改:

1

第80行框出代码修改:

                DCD     OS_CPU_PendSVHandler             ; PendSV Handler
                DCD     OS_CPU_SysTickHandler            ; SysTick Handler

第220行框出代码修改:

OS_CPU_PendSVHandler\
                PROC
                EXPORT  OS_CPU_PendSVHandler       [WEAK]
                B       .
                ENDP
OS_CPU_SysTickHandler\
                PROC
                EXPORT  OS_CPU_SysTickHandler      [WEAK]
                B       .
                ENDP

最后编译检查无问题:

修改/确定 系统时钟(SysTick)内核:

这里我还特意出去学习了一下系统内核时钟的初始化等知识:并附文:

STM32F407VET6 学习笔记3:内核定时器SystemTick(SysTick)初始化中断-CSDN博客

/**
 * This function will initial stm32 board.
 */
void board_init(void)
{
    /* NVIC Configuration */
#define NVIC_VTOR_MASK              0x3FFFFF80
#ifdef  VECT_TAB_RAM
    /* Set the Vector Table base location at 0x10000000 */
    SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
#else  /* VECT_TAB_FLASH  */
    /* Set the Vector Table base location at 0x08000000 */
    SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);
#endif

	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //Systick 时钟源频率168M
	
	  // 计算SysTick重装载值(SystemCoreClock为168MHz,希望SysTick中断频率为1ms(1000 Hz))
		//SysTick_LOAD = (SystemCoreClock / TickRate) - 1
    uint32_t reload = SystemCoreClock / 1000 - 1; // 1ms中断频率  
    SysTick->LOAD = reload;  

    // 清除SysTick当前值并启动SysTick,同时使能中断
    SysTick->VAL  = 0; // 清空当前值  
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;  

    /* 设置NVIC优先级分组 */  
    // 4位抢占优先级和0位子优先级  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);   
    /* 设置SysTick中断的优先级 */  
    // 设置SysTick的抢占优先级为3(最低),没有子优先级(因为分组4没有子优先级位)  
    NVIC_SetPriority(SysTick_IRQn, 3); // 注意:优先级值根据分组设置可能有所不同 
		
}
// 声明SysTick中断处理函数  
void SysTick_Handler(void)
{
	  OSIntEnter();		      //进入中断
    OSTimeTick();       //调用ucos的时钟服务程序               
    OSIntExit();        //触发任务切换软中断
}

修改CONFIG/app_cfg.h:

#define APP_CFG_SERIAL_EN        DEF_ENABLED ------>

#define APP_CFG_SERIAL_EN        DEF_DISABLED

改后如下:

#define APP_TRACE BSP_Ser_Printf --------> #define APP_TRACE (void)

修改CONFIG/includes.h :

尝试编写简单的 UC/OS-III 任务例程:

先引用头文件:

/*****************UC/OS头文件***************/
#include "os.h"
#include "os_cpu_bsp.h"
#include <app_cfg.h>
#include <cpu_core.h>
#include <os_app_hooks.h>
#include <cpu.h>
/* USER CODE END Includes */

定义任务栈大小/优先级:


//任务栈大小定义
#define  START_STK_SIZE                     128
#define  TASK1_STK_SIZE                     128
#define  TASK2_STK_SIZE                     128
#define  TASK3_STK_SIZE                     128
//任务优先级定义
#define  APP_TASK_START_PRIO                     4
#define  APP_TASK_1_PRIO                         5
#define  APP_TASK_2_PRIO                         6
#define  APP_TASK_3_PRIO                         7

定义任务控制块TCB:

//创建任务控制块
static OS_TCB Start_Task_TCB;
static OS_TCB Task1_TCB;
static OS_TCB Task2_TCB;
static OS_TCB Task3_TCB;

定义任务栈:

//任务堆栈	
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
CPU_STK TASK3_TASK_STK[TASK3_STK_SIZE];

定义任务主体函数:

这个放置在主函数下面吧就:

任务里面一定要有阻塞延时,如果这个任务的优先级最高且没有阻塞延时,那么操作系统就只会执行这一个任务,其他的任务就得不到执行。

注意:这里的    OSTimeDly ( 2000, OS_OPT_TIME_DLY, & err ); 对应的延时 不仅与 内传的参数 有关 还与 内核定时器SystemTick 有关:

创建任务TASK1-2-3:

各个TASK的任务如下描述:

//TASK_1 报告自己执行次数(2s),并在执行8次后删除 TASK_2

//TASK_2 串口报告自己执行的次数 (4s)

//这里的 TASK_3 会每隔 17S 恢复TASK_2 (全新的开始)
/*
    创建一个全新的任务实例,而不是简单地“恢复”一个已经被删除的任务。
  这意味着新的任务实例将拥有自己独立的堆栈(stack)和其他资源,而原来的任务实例(如果已经被删除)的资源将被释放
*/

//TASK_1 报告自己执行次数(2s),并在执行8次后删除 TASK_2
void TASK_1(void)
{
	OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型
	int TASK1_num=0;  //记录任务TASK_1执行次数

	
	//在某些嵌入式系统中,进入和退出关键区域可能需要禁用中断,以防止在关键代码执行过程中被中断打断。	
  CPU_SR_ALLOC();   //为保存和恢复CPU的状态寄存器(Status Register)或中断状态做准备工作。
	OS_CRITICAL_ENTER();
	/* 此处添加不希望被打断的硬件初始化代码等......*/
	OS_CRITICAL_EXIT();
	
	while(1)
	{
		TASK1_num++;	//任务TASK_1执行次数加1
		
		if(TASK1_num%8==0)
		{
			OSTaskDel((OS_TCB*)&Task2_TCB,&err);	        //任务1每执行8次后(即16s时) 删除掉任务2
			printf("TASK_1 has Deleted the TASK_2 !\r\n");//打印报告	任务1 删除了 任务2
		}
	  UsartPrintf(USART1,"TASK_1 has Carred out %d times! \r\n",TASK1_num);	//打印测试字符串(并报告TASK_1执行次数)
		OSTimeDly ( 2000, OS_OPT_TIME_DLY, & err ); //使当前任务延迟指定的时间(2s):  (让当前任务放弃CPU一段时间,CPU让给其余任务)
	}
}

//TASK_2 串口报告自己执行的次数 (4s)
void TASK_2(void)
{
	OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型
	int TASK2_num=0;  //记录任务TASK_2执行次数
		
	while(1)
	{
	  UsartPrintf(USART1,"TASK_2 has Carred out %d times! \r\n",TASK2_num);	//打印测试字符串(并报告TASK_2执行次数)
		OSTimeDly ( 4000, OS_OPT_TIME_DLY, & err );//使当前任务延迟指定的时间(4S):  (让当前任务放弃CPU一段时间,CPU让给其余任务) 
	}
}

//这里的 TASK_3 会每隔 17S 恢复TASK_2 (全新的开始)
/*
	创建一个全新的任务实例,而不是简单地“恢复”一个已经被删除的任务。
  这意味着新的任务实例将拥有自己独立的堆栈(stack)和其他资源,而原来的任务实例(如果已经被删除)的资源将被释放
*/
void TASK_3(void)
{
	OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型
	int TASK3_num=0;  //记录任务TASK_3执行次数
	CPU_SR_ALLOC();
	
	OS_CRITICAL_ENTER();	//进入临界区			 
	 //重新创建TASK2任务
			OSTaskCreate((OS_TCB 	* )&Task2_TCB,		
				 (CPU_CHAR	* )"TASK_2", 		
                 (OS_TASK_PTR )TASK_2, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK2_PRIO,     	
                 (CPU_STK   * )&TASK2_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK2_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK2_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);	
	OS_CRITICAL_EXIT();	//退出临界区	 		
								 
	while(1)
	{
	    UsartPrintf(USART1,"TASK_3 has Resume the TASK_2 %d times! \r\n",TASK3_num);	//打印测试字符串(并报告TASK_3执行次数)							 
			OSTimeDly ( 17000, OS_OPT_TIME_DLY, & err );//使当前任务延迟指定的时间(17S):  (让当前任务放弃CPU一段时间,CPU让给其余任务) 
		
	}
}

//开始任务任务函数
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;

	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
  OSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间
  CPU_IntDisMeasMaxCurReset();	
#endif
	
#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	
	
	OS_CRITICAL_ENTER();	//进入临界区
	//创建TASK1任务
	OSTaskCreate((OS_TCB 	* )&Task1_TCB,				          //任务控制块
				 (CPU_CHAR	* )"TASK_1", 	 		                  //任务名字	
                 (OS_TASK_PTR )TASK_1, 			            //任务函数
                 (void		* )0,					                //传递给任务函数的参数					
                 (OS_PRIO	  )TASK1_PRIO,     
                 (CPU_STK   * )&TASK1_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK1_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);				
				 
	//创建TASK2任务
	OSTaskCreate((OS_TCB 	* )&Task2_TCB,		
				 (CPU_CHAR	* )"TASK_2", 		
                 (OS_TASK_PTR )TASK_2, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK2_PRIO,     	
                 (CPU_STK   * )&TASK2_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK2_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK2_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);		

	//创建TASK3任务
	OSTaskCreate((OS_TCB 	* )&Task3_TCB,		
				 (CPU_CHAR	* )"TASK_3", 		
                 (OS_TASK_PTR )TASK_3, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK3_PRIO,     	
                 (CPU_STK   * )&TASK3_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK3_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK3_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);	
								 
	OS_CRITICAL_EXIT();	//退出临界区
	OSTaskDel((OS_TCB*)0,&err);	//删除start_task任务自身
}

CPU_SR_ALLOC();  

OS_CRITICAL_ENTER();  

OS_CRITICAL_EXIT();

	//在某些嵌入式系统中,进入和退出关键区域可能需要禁用中断,以防止在关键代码执行过程中被中断打断。	
  CPU_SR_ALLOC();   //为保存和恢复CPU的状态寄存器(Status Register)或中断状态做准备工作。
	
	/*
		OS_CRITICAL_ENTER();
    这个函数通常用于进入一个关键区域。在进入关键区域之前,
		它可能会禁用中断(如果之前通过CPU_SR_ALLOC();已经做了相关准备),
	  或者通过其他机制(如锁)来确保没有其他线程或中断可以访问当前线程正在使用的共享资源。
    通过禁用中断或获得锁,OS_CRITICAL_ENTER();
	  确保了代码的关键部分在执行时不会被其他任务或中断打断,
	  从而保证了数据的一致性和操作的原子性。

	*/
	OS_CRITICAL_ENTER();
	/*
		OS_CRITICAL_EXIT();
		这个函数用于退出之前由OS_CRITICAL_ENTER();进入的关键区域。
		在退出关键区域时,它可能会重新启用之前被禁用的中断,或者释放之前获得的锁。
		这样做允许其他任务或中断再次访问之前被保护的共享资源
	*/
	OS_CRITICAL_EXIT();

启动UCOS III 系统函数:

//启动UCOS III 系统 !
void UCOS_III_init(void)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	
	OSInit(&err);		      //初始化UCOSIII
	OS_CRITICAL_ENTER();	//进入临界区			 
	//创建开始任务
	OSTaskCreate((OS_TCB 	* )&Start_Task_TCB,		      //任务控制块
				 (CPU_CHAR	* )"start_task", 		            //任务名字
                 (OS_TASK_PTR )start_task, 			    //任务函数
                 (void		* )0,					            //传递给任务函数的参数
                 (OS_PRIO	  )START_TASK_PRIO,       //任务优先级
                 (CPU_STK   * )&START_TASK_STK[0],	//任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,	  //任务堆栈深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,		  //任务堆栈大小
                 (OS_MSG_QTY  )0,				//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                 (OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,
                 (void   	* )0,					//用户补充的存储区
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
                 (OS_ERR 	* )&err);			//存放该函数错误时的返回值
	OS_CRITICAL_EXIT();	//退出临界区	 
	OSStart(&err);      //开启UCOSIII	 
}

主函数调用情况展示:

网上学习资料网址贴出:

第3讲 UCOS基础知识_哔哩哔哩_bilibili

uCosII移植STM32F407教程_stm32f407 ucos-CSDN博客

基于stm32cubemx移植uC/OS-III操作系统_cubemx ucos-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1696786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

上门服务系统开发|东邻到家系统|上门服务系统开发流程

上门服务小程序的开发流程是一个复杂且精细的过程&#xff0c;涉及到需求分析、设计规划、开发实施、测试验收以及上线运营等多个环节。下面将详细介绍上门服务小程序的开发流程&#xff0c;帮助读者全面了解并掌握其中的关键步骤。 一、需求分析 在开发上门服务小程序之前&am…

北核论文完美复现:自适应t分布与动态边界策略改进的算术优化算法

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原始算术优化算法 改进点1&#xff1a;引入…

Java进阶学习笔记22——泛型方法、通配符和上下限

泛型方法&#xff1a; package cn.ensource.d11_generics_method;public class Test {public static void main(String[] args) {// 泛型方法String res test("Java");System.out.println(res);Dog dog1 test(new Dog());System.out.println(dog1);}// 泛型方法pub…

python考试成绩管理与分析:从列表到方差

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、考试成绩的输入与列表管理 二、成绩的总分与平均成绩计算 三、成绩方差的计算 四、成…

基于Rsoft的Fullwave仿真模块进行双芯波导能量耦合与波分复用

Rsoft中的Fullwave仿真模块可以更精确的仿真微小结构&#xff0c;按照建立模型&#xff0c;设置参数&#xff0c;监测能量&#xff0c;优化结构的思路对其进行仿真。图1是在Fullwave模块中建立的双芯波导仿真模型。在模型中设置好折射率、光源、光路、监测器等便可以进行仿真。…

mysql实战——XtraBackup二进制包安装

1、二进制包下载网站 Software Downloads - Percona 2、安装xtrabackup 解压安装包 tar xvf percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17.tar.gz -C /usr/local 进入目录 cd percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17/ 安装依赖 yum install perl-Dig…

平安养老险陕西分公司:举办“贺司庆·员工橙心面对面”活动

为践行新价值文化与“三省”推广&#xff0c;平安养老险陕西分公司以集团36周年司庆为契机结合“员工聆听计划”指引要求&#xff0c;举办“贺司庆&#xff0c;员工橙心面对面”活动。 活动邀请西北大学公共管理学院高阳教授为分公司员工带来生动有趣的《压力管理新科学》心理课…

gdc2024:Raytracing in Snowdrop技术实现与性能优化策略

在今年的GDC&#xff08;游戏开发者大会&#xff09;的Advanced Graphics Summit上&#xff0c;关于Snowdrop引擎中光线追踪技术的讨论引起了广泛关注。 一、光线追踪全局照明的实现细节 屏幕空间追踪&#xff1a; 屏幕空间追踪从相机出发&#xff0c;对屏幕上的每个像素点生成…

搭建企业级AI应用的流程

搭建企业级AI应用的流程是一个复杂且系统化的工程&#xff0c;它需要从多个维度出发&#xff0c;确保最终的应用既符合企业的业务需求&#xff0c;也具备高效、稳定和可扩展的特性。以下是详细的步骤&#xff1a; 初步接触与需求分析是整个项目的基础。在这一阶段&#xff0c;我…

STM32 DMA配置库函数

单片机学习&#xff01; 目录 1. DMA_DeInit 2. DMA_Init 3. DMA_StructInit 4. DMA_Cmd 5. DMA_ITConfig 6. DMA_SetCurrDataCounter 7. DMA_GetCurrDataCounter 8. 获取/清除函数 8.1 DMA_GetFlagStatus 8.2 DMA_ClearFlag 8.3 DMA_GetITStatus 8.4 DMA_ClearITP…

【调试笔记-20240526-Linux-在 OpenWrt-23.05 发行版上安装 cloudreve】

调试笔记-系列文章目录 调试笔记-20240526-Linux-在 OpenWrt-23.05 发行版上安装 cloudreve 文章目录 调试笔记-系列文章目录调试笔记-20240526-Linux-在 OpenWrt-23.05 发行版上安装 cloudreve 前言一、调试环境操作系统&#xff1a;Windows 10 专业版调试环境调试目标 二、调…

Adobe Animate AN v24.0.2 安装教程 (动画特效设计及合成工具)

Adobe系列软件安装目录 一、Adobe Photoshop PS 25.6.0 安装教程 (最流行的图像设计软件) 二、Adobe Media Encoder ME v24.3.0 安装教程 (视频和音频编码渲染工具) 三、Adobe Premiere Pro v24.3.0 安装教程 (领先的视频编辑软件) 四、Adobe After Effects AE v24.3.0 安装…

安卓手机听书的各种免费方案

categories: Tips tags: Tips 写在前面 最近 Tencent 突然给微信读书上限制了, 普通用户一个月内仅能导入 3 本书, 这就让经常在 weread 上面听书入眠的我很无奈了. 折腾一下备选方案吧, 肯定是免费优先咯. 下面主要从支持 tts 的阅读器/ tts 免费中文引擎两个角度来讲. r…

Linux服务升级:Predixy 升级代理 Redis-cluster 集群

目录 一、实验 1.环境 2. 启动Redis服务 3.Predixy 升级代理 Redis-cluster 集群 二、问题 1. Predixy进行set操作报错 2.如何创建脚本启动predixy 3.Redis代理对比 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本节点软件IP备注CentOS7.9Redis…

沁恒CH32V307开发板移植lvgl V9版本图形库

我们在移植lvgl9版本之前也是去网上进行了大量资料的查找&#xff0c;发现关于lvgl的移植大多停留在8版本的基础上&#xff0c;所以我们绝对自己干&#xff0c;并把移植过程中遇到的问题总结出来&#xff0c;这里主要为大家总结一下移植中一些容易踩的坑&#xff0c;以及8版本和…

新建一个STM32的工程

一、SMT32开发方式 1、基于寄存器的方式&#xff1a;和51单片机开发方式一样&#xff0c;是用程序直接配置寄存器&#xff0c;来达到我们想要的功能&#xff0c;这种方式最底层、最直接、效率会更高一些&#xff0c;但是STM32的结构复杂、寄存器太多&#xff0c;所以不推荐基于…

深入理解 Spring 上下文(Context)层次结构

前言 在使用 Spring 框架进行应用程序开发时&#xff0c;Spring 上下文&#xff08;Context&#xff09;是一个非常重要的概念。Spring 上下文提供了一个环境&#xff0c;用于管理应用程序中的对象&#xff08;通常称为 Bean&#xff09;及其之间的依赖关系。在复杂的应用程序…

Nginx代理配置(专业版)

写在前面提醒&#xff1a;使用代理&#xff0c;如果可以&#xff0c;请尽量支持双协议&#xff0c;http、https均要支持哈。 注意&#xff1a;监控系统只是运行代码&#xff0c;是否支持https&#xff0c;需要运维同学在你们的服务器上配置https证书&#xff0c;配置好证书&…

【最新区块链论文录用资讯】CCF A — SP 2024 共17篇

Conference&#xff1a;45th IEEE Symposium onSecurity and Privacy CCF level&#xff1a;CCF A Categories&#xff1a;网络与信息安全 Year&#xff1a;2024 Num&#xff1a;17 Efficient Zero-Knowledge Arguments For Paillier Cryptosystem Paillier 加密系统的有效…

VUE3视频播放器 videojs-player/vue

简介 官网&#xff1a; https://gitcode.com/surmon-china/videojs-player/overviewhttps://github.com/surmon-china/videojs-player?tabreadme-ov-file video-player是一个基于video.js的视频播放器组件&#xff0c;它提供了丰富的功能&#xff0c;包括视频播放、暂停、快…