STM32G431RBT6移植FreeRTOS

引言: 本文专门为参加了蓝桥杯嵌入式赛道的同学准备, 大家可能会有这样一个问题, 比完赛之后, 对于像继续使用STM32G431RBT6学习FreeRTOS的, 发现网上的教程使用的板子基本上都是F1和F4的, 其实呢, 随便移植一下就能在我们自己的板子上面运行FreeTROS了。如果大家有ARM Linux的学习经历, 比如系统移植的基础, 那再来学这个FreeRTOS就比较容易了。

目录

一、FreeRTOS简介

二、什么是移植

三、移植实验开始

1.源码下载

2.源码目录结构简单分析

3.创建工程

4.开始移植

5.各种报错开始

四、创建几个任务看看移植效果

五、FreeRTOS为什么能进行裁剪

六、总结

七、FreeRTOS学习资源


一、FreeRTOS简介

        首先看一下FreeRTOS 的名字,可以分为两部分:“Free”和“RTOS”,“F ree”就是免费的、自由的、不受约束的意思,“RTOSRTOS”全称是R eal Time Operating System System,中文名就是实时操作系统,要注意的是,RTOS 并不是值某一特定的操作系统,而是指一类操作系统,例如,µ C/OS OS,FreeRTOSFreeRTOS,RTXRTX,RT T hread 等这些都是RTOS 类的操作系统。因此,从FreeRTOS 的名字中就能看出,F reeROTS 是一款免费的实时操作系统。
        操作系统是允许多个任务“同时运行”的,操作系统的这个特性被称为多任务。然而实际上,一个CPU 核心在某一时刻只能运行一个任务,而操作系统中任务调度器的责任就是决定在某一时刻CPU 究竟要运行哪一个任务,任务调度器使得CPU 在各个任务之间来回切换并处理任务,由于切换处理任务的速度非常快,因此就给人造成了一种同一时刻有多个任务同时运行的错觉。
        操作系统的分类方式可以由任务调度器的工作方式决定,比如有的操作系统给每个任务分配同样的运行时间,时间到了就切换到下一个任务,Unix 操作系统就是这样的。RTOS 的任务调度器被设计为可预测的,而这正是嵌入式实时操作系统所需要的。在实时环境中,要求操作系统必须实时地对某一个事件做出响应,因此任务调度器的行为必须是可预测的。像F reeRTOS这种传统的RTOS 类操作系统是由用户给每个任务分配一个任务优先级,任务调度器就可以根据此优先级来决定下一刻应该运行哪个任务。
        FreeRTOS 是众多RTOS 类操作系统中的一种,F reeRTOS 十分的小巧,可以在资源有限的微控制器中运行,当然了,F reeRTOS 也不仅仅局限于在微控制器中使用。就单从文件数量上来看F reeRTOS 要比µ C/OS 少得多。

国内外常见的几种物联网操作系统: 

题外话: Linux和物联网操作系统的区别

Linux是一个通用的操作系统内核,最初由Linus Torvalds创建,用于各种计算设备,从个人电脑到服务器再到嵌入式系统。Linux内核是一个开放源代码项目,因此可以根据需要进行定制和修改。物联网操作系统则是专门为连接到互联网的物联网设备设计的操作系统,通常具有以下特点:

1. 资源受限性:物联网设备通常具有有限的处理能力、内存和存储空间,因此物联网操作系统需要具备轻量级和高效能的特性。

2. 实时性:物联网应用中的某些任务可能对时间敏感,需要在特定时间内完成。因此,一些物联网操作系统提供实时性能,以确保任务的及时执行。

3. 低功耗:许多物联网设备需要长时间运行,因此物联网操作系统需要优化能源消耗,以延长设备的电池寿命或降低能源成本。

4. 通信支持:物联网操作系统通常需要支持各种通信协议,如Wi-Fi、蓝牙、LoRa等,以便设备能够与其他设备或云平台进行通信。

5. 安全性: 物联网设备可能面临各种安全威胁,因此物联网操作系统需要提供安全功能,如数据加密。

上面这张图是基于LInux内核开发的几款操作系统。

二、什么是移植

当在嵌入式系统中从一个硬件平台或操作系统移植软件时,我们称之为移植(Porting)。移植意味着将软件(通常是操作系统、驱动程序或应用程序)从一个平台或环境移植到另一个平台或环境,使其能够在目标平台上运行。 移植通常涉及以下几个方面:

硬件适配:目标平台通常具有不同的处理器架构、外设、存储器和输入/输出接口等硬件特性。因此,移植过程需要对软件进行适配,以确保其能够与目标硬件兼容并正确运行。这可能涉及修改驱动程序或底层硬件抽象层(HAL)。

操作系统适配: 如果软件依赖于特定的操作系统,那么在将其移植到新平台时,需要确保目标平台上有相应的操作系统支持。如果目标平台上没有现成的操作系统支持,可能需要移植一个新的操作系统或调整现有操作系统以适应目标平台。

编译和链接: 移植软件可能需要调整编译器、链接器和构建工具链以适应目标平台的体系结构和工具集。

性能优化:在移植软件时,通常需要对性能进行优化,以确保在目标平台上能够达到合理的性能水平。这可能涉及调整算法、数据结构或代码结构,以充分利用目标平台的硬件资源。

功能兼容性:移植软件时需要确保其功能在目标平台上能够正常运行,并且与原始平台上的行为保持一致。

总的来说,移植是将软件从一个环境移植到另一个环境的过程,涉及到对硬件、操作系统、编译工具链和性能进行适配和优化,以确保软件能够在目标平台上正确运行。想象成人类的器官移植, 在移植之前是不是得适配才能正常的工作。

三、移植实验开始

        移植实验开始之前相信大家肯定都是有裸机开发的基础的, 提前说一下我对操作系统的理解, 没有装操作系统之前, 我们下载到单片机中运行的程序都叫做裸机程序, 那么, 操作系统又是什么呢, 其实操作系统就是第一个裸机程序, 它的作用是为应用程序的执行提供运行环境。如果在有人问题操作系统是什么, 你就可以说操作系统其实就是一个裸机程序, 为应用程序的运行提供运行的环境。对于Linux这样的通用型操作系统内核来说, 它的作用和上面一样, 但是还需要加上这几句话, 向上提供接口, 向下控制硬件, 它的几大功能模块分别是内存管理, 进程管理、文件系统、设备驱动、网络协议栈。

上面这张图就展示了Linux整体框架构图。

1.源码下载

官网: www.freertos.org

下载可能有些慢, 嫌慢的兄弟可以去码云下载。

2.源码目录结构简单分析

3.创建工程

这里使用cubeMx创建工程我就大致掠过了, 相信大家都是会的。

打开Keil工程

编译一下

接着去到源码目录下, 准备一个存放BSP相关代码的地方

头文件的地方我们也来一个

4.开始移植

去到FreeRTOS源码位置, 将内存管理, 和M4相关的代码拿到我们创建号的工程目录下

继续, 把下面的代码移植过去先

接着把FreeRTOS的头文件拿过来

其实这些步骤大家可以自己按照自己的习惯来,这些都不是关键的地方。

修改一下调试器相关的内容

到此我们先编译一下, 说找不到这个配置文件, 这个文件很重要, 稍后做出解释。

这个文件有几种办法获取, 第一自己编写, 需要对整个FreeRTOS的源码非常的熟悉, 不推荐, 第二去源码中找示例, 推荐。

将其拷贝到我们的工程目录的头文件路径下面去

又报错了, 头文件找不到

下问题, 找一下

这个位置, 存放cpu代码的目录下面有一个头文件, 加一下

5.各种报错开始

这个错误出现的原因是因为FreeRTOS的源码中因为需要匹配各种架构的cpu和板卡, 使用了大量的条件编译, 以达到根据条件编译的定义内容编译不同的架构的代码。

方便大家复制

#if defined (__ICCARM__) || defined (__CC_ARM__) || defined (__GNUC__)
	#include <stdint.h>
	extern uint32_t SystemCoreClock;
#endif

继续报错

把FreeRTOSConfig.h文件包含在port.c文件中, 这样就能找到了

再次编译

又又报错了, 这次的原因是因为这几个异常的ISR定义重复了, 为什么会重复呢, 是因为在FreeRTOS的任务调度代码中就是利用了这几个异常的机制, 实现的任务每隔一个时间片调度依次任务。就是FreeRTOS定义了。

请看上图, 在FreeRTOS的配置文件中定义了, 所谓的配置文件, 没办法因为咱们嵌入式开发是没有啥子精美的界面的, 又不可能搞一个很漂亮的界面给我们自己根据cpu的架构, 板卡的资源信息自行选配, 所以就是用了大量的宏开关, 简单来说就是编译器在编译整个项目源码的时候, 会根据这些宏开关,或者说是符号的定义轻快选择不同的代码编译。

回到这几个ISR符号重复定义的问题, 解决办法是去到我们的xxx_it.c中注释掉这几个符号

再次编译

又又又报错了, 说这几个函数没有定义,是因为我们的配置文件选上了这些配置, 解决办法是去到配置文件中将相应的宏开关关闭, 这样在编译的使用就不编译这几个函数了。

修改前

修改后

其实还可以我们自己定义这些钩子函数, 其实就是回调函数, 是官方留给我们的接口, 可以自己定义在出现这些错误的时候, 做一些出错处理

再次编译

0error 0warning, nice, 恭喜, 大家马上接近成功了。为什么这样说呢, 是因为咱们的这个栈空间的设置是有问题的, 一会再最后给大家演示。

这个是因为我们再创建工程的时候没有用到adc uart timer等, 所以Mx没有拷贝对应的定以到工程中。我们自己添加一下

打开咱们使用到的

如果大家有移植的是由栈空间不够了,教大家怎么修改

但还是要基于我们的硬件来改。

内存布局:

四、创建几个任务看看移植效果

http://www.freertos.org

可以去FreeRTOS的官网查看API示例, 还是非常简单的这些函数

#include "main.h"
#include "bsp_led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "bsp_uart.h"
#include <stdio.h>
#include "FreeRTOSConfig.h"
#include "lcd.h"

TaskHandle_t start_handle;
void start_task(void *arg);
void FreeRTOS_Entry(void);

int main(void)
{
	
	
	HAL_Init();
	SystemClock_Config();

	Led_Init();
	Uart_Init();
	
	FreeRTOS_Entry();
}
     



void FreeRTOS_Entry(void)
{
	BaseType_t retval;
	printf("1\r\n");
	 retval = xTaskCreate(      start_task,
								(const char *) " start_task",
								128,
								NULL,
								1,
								(TaskHandle_t *)&start_handle
                         );
	
	if(retval != pdPASS ) {
		Error_Handler();
	}
	printf("2\r\n");
	
	
	vTaskStartScheduler();
	printf("3\r\n");
	
	
}

void start_task(void *arg)
{
	
	while(1) {
		printf("task running\r\n");
	
		Led_Control(LED_ON, 1);
		Led_Control(LED_TOGGLE, 1);
		Led_Control(LED_TOGGLE, 3);
		Led_Control(LED_TOGGLE, 5);
		Led_Control(LED_TOGGLE, 7);
		
		vTaskDelay(1000);
	}
	
}

五、FreeRTOS为什么能进行裁剪

就是因为freeRtos根据不同的不同的硬件情况、包括不同的PCU架构, 不同的Flash SRAM大小, 

FreeRTOS还提供不同的内存分配算法。

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/* 头文件 */
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include <stdint.h>

extern uint32_t SystemCoreClock;

/* 基础配置项 */
#define configUSE_PREEMPTION                            1                       /* 1: 抢占式调度器, 0: 协程式调度器, 无默认需定义 */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION         1                       /* 1: 使用硬件计算下一个要运行的任务, 0: 使用软件算法计算下一个要运行的任务, 默认: 0 */
#define configUSE_TICKLESS_IDLE                         0                       /* 1: 使能tickless低功耗模式, 默认: 0 */
#define configCPU_CLOCK_HZ                              SystemCoreClock         /* 定义CPU主频, 单位: Hz, 无默认需定义 */
//#define configSYSTICK_CLOCK_HZ                          (configCPU_CLOCK_HZ / 8)/* 定义SysTick时钟频率,当SysTick时钟频率与内核时钟频率不同时才可以定义, 单位: Hz, 默认: 不定义 */
#define configTICK_RATE_HZ                              1000                    /* 定义系统时钟节拍频率, 单位: Hz, 无默认需定义 */
#define configMAX_PRIORITIES                            32                      /* 定义最大优先级数, 最大优先级=configMAX_PRIORITIES-1, 无默认需定义 */
#define configMINIMAL_STACK_SIZE                        128                     /* 定义空闲任务的栈空间大小, 单位: Word, 无默认需定义 */
#define configMAX_TASK_NAME_LEN                         16                      /* 定义任务名最大字符数, 默认: 16 */
#define configUSE_16_BIT_TICKS                          0                       /* 1: 定义系统时钟节拍计数器的数据类型为16位无符号数, 无默认需定义 */
#define configIDLE_SHOULD_YIELD                         1                       /* 1: 使能在抢占式调度下,同优先级的任务能抢占空闲任务, 默认: 1 */
#define configUSE_TASK_NOTIFICATIONS                    1                       /* 1: 使能任务间直接的消息传递,包括信号量、事件标志组和消息邮箱, 默认: 1 */
#define configTASK_NOTIFICATION_ARRAY_ENTRIES           1                       /* 定义任务通知数组的大小, 默认: 1 */
#define configUSE_MUTEXES                               1                       /* 1: 使能互斥信号量, 默认: 0 */
#define configUSE_RECURSIVE_MUTEXES                     1                       /* 1: 使能递归互斥信号量, 默认: 0 */
#define configUSE_COUNTING_SEMAPHORES                   1                       /* 1: 使能计数信号量, 默认: 0 */
#define configUSE_ALTERNATIVE_API                       0                       /* 已弃用!!! */
#define configQUEUE_REGISTRY_SIZE                       8                       /* 定义可以注册的信号量和消息队列的个数, 默认: 0 */
#define configUSE_QUEUE_SETS                            1                       /* 1: 使能队列集, 默认: 0 */
#define configUSE_TIME_SLICING                          1                       /* 1: 使能时间片调度, 默认: 1 */
#define configUSE_NEWLIB_REENTRANT                      0                       /* 1: 任务创建时分配Newlib的重入结构体, 默认: 0 */
#define configENABLE_BACKWARD_COMPATIBILITY             0                       /* 1: 使能兼容老版本, 默认: 1 */
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS         0                       /* 定义线程本地存储指针的个数, 默认: 0 */
#define configSTACK_DEPTH_TYPE                          uint16_t                /* 定义任务堆栈深度的数据类型, 默认: uint16_t */
#define configMESSAGE_BUFFER_LENGTH_TYPE                size_t                  /* 定义消息缓冲区中消息长度的数据类型, 默认: size_t */

/* 内存分配相关定义 */
#define configSUPPORT_STATIC_ALLOCATION                 0                       /* 1: 支持静态申请内存, 默认: 0 */
#define configSUPPORT_DYNAMIC_ALLOCATION                1                       /* 1: 支持动态申请内存, 默认: 1 */
#define configTOTAL_HEAP_SIZE                           ((size_t)(10 * 1024))   /* FreeRTOS堆中可用的RAM总量, 单位: Byte, 无默认需定义 */
#define configAPPLICATION_ALLOCATED_HEAP                0                       /* 1: 用户手动分配FreeRTOS内存堆(ucHeap), 默认: 0 */
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP       0                       /* 1: 用户自行实现任务创建时使用的内存申请与释放函数, 默认: 0 */

/* 钩子函数相关定义 */
#define configUSE_IDLE_HOOK                             0                       /* 1: 使能空闲任务钩子函数, 无默认需定义  */
#define configUSE_TICK_HOOK                             0                       /* 1: 使能系统时钟节拍中断钩子函数, 无默认需定义 */
#define configCHECK_FOR_STACK_OVERFLOW                  0                       /* 1: 使能栈溢出检测方法1, 2: 使能栈溢出检测方法2, 默认: 0 */
#define configUSE_MALLOC_FAILED_HOOK                    0                       /* 1: 使能动态内存申请失败钩子函数, 默认: 0 */
#define configUSE_DAEMON_TASK_STARTUP_HOOK              0                       /* 1: 使能定时器服务任务首次执行前的钩子函数, 默认: 0 */

/* 运行时间和任务状态统计相关定义 */
#define configGENERATE_RUN_TIME_STATS                   0                       /* 1: 使能任务运行时间统计功能, 默认: 0 */
#if configGENERATE_RUN_TIME_STATS
#include "./BSP/TIMER/btim.h"
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()        ConfigureTimeForRunTimeStats()
extern uint32_t FreeRTOSRunTimeTicks;
#define portGET_RUN_TIME_COUNTER_VALUE()                FreeRTOSRunTimeTicks
#endif
#define configUSE_TRACE_FACILITY                        1                       /* 1: 使能可视化跟踪调试, 默认: 0 */
#define configUSE_STATS_FORMATTING_FUNCTIONS            1                       /* 1: configUSE_TRACE_FACILITY为1时,会编译vTaskList()和vTaskGetRunTimeStats()函数, 默认: 0 */

/* 协程相关定义 */
#define configUSE_CO_ROUTINES                           0                       /* 1: 启用协程, 默认: 0 */
#define configMAX_CO_ROUTINE_PRIORITIES                 2                       /* 定义协程的最大优先级, 最大优先级=configMAX_CO_ROUTINE_PRIORITIES-1, 无默认configUSE_CO_ROUTINES为1时需定义 */

/* 软件定时器相关定义 */
#define configUSE_TIMERS                                1                               /* 1: 使能软件定时器, 默认: 0 */
#define configTIMER_TASK_PRIORITY                       ( configMAX_PRIORITIES - 1 )    /* 定义软件定时器任务的优先级, 无默认configUSE_TIMERS为1时需定义 */
#define configTIMER_QUEUE_LENGTH                        5                               /* 定义软件定时器命令队列的长度, 无默认configUSE_TIMERS为1时需定义 */
#define configTIMER_TASK_STACK_DEPTH                    ( configMINIMAL_STACK_SIZE * 2) /* 定义软件定时器任务的栈空间大小, 无默认configUSE_TIMERS为1时需定义 */

/* 可选函数, 1: 使能 */
#define INCLUDE_vTaskPrioritySet                        1                       /* 设置任务优先级 */
#define INCLUDE_uxTaskPriorityGet                       1                       /* 获取任务优先级 */
#define INCLUDE_vTaskDelete                             1                       /* 删除任务 */
#define INCLUDE_vTaskSuspend                            1                       /* 挂起任务 */
#define INCLUDE_xResumeFromISR                          1                       /* 恢复在中断中挂起的任务 */
#define INCLUDE_vTaskDelayUntil                         1                       /* 任务绝对延时 */
#define INCLUDE_vTaskDelay                              1                       /* 任务延时 */
#define INCLUDE_xTaskGetSchedulerState                  1                       /* 获取任务调度器状态 */
#define INCLUDE_xTaskGetCurrentTaskHandle               1                       /* 获取当前任务的任务句柄 */
#define INCLUDE_uxTaskGetStackHighWaterMark             1                       /* 获取任务堆栈历史剩余最小值 */
#define INCLUDE_xTaskGetIdleTaskHandle                  1                       /* 获取空闲任务的任务句柄 */
#define INCLUDE_eTaskGetState                           1                       /* 获取任务状态 */
#define INCLUDE_xEventGroupSetBitFromISR                1                       /* 在中断中设置事件标志位 */
#define INCLUDE_xTimerPendFunctionCall                  1                       /* 将函数的执行挂到定时器服务任务 */
#define INCLUDE_xTaskAbortDelay                         1                       /* 中断任务延时 */
#define INCLUDE_xTaskGetHandle                          1                       /* 通过任务名获取任务句柄 */
#define INCLUDE_xTaskResumeFromISR                      1                       /* 恢复在中断中挂起的任务 */

/* 中断嵌套行为配置 */
#ifdef __NVIC_PRIO_BITS
    #define configPRIO_BITS __NVIC_PRIO_BITS
#else
    #define configPRIO_BITS 4
#endif

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         15                  /* 中断最低优先级 */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                   /* FreeRTOS可管理的最高中断优先级 */
#define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY            ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_API_CALL_INTERRUPT_PRIORITY           configMAX_SYSCALL_INTERRUPT_PRIORITY

/* FreeRTOS中断服务函数相关定义 */
#define xPortPendSVHandler                              PendSV_Handler
#define vPortSVCHandler                                 SVC_Handler

/* 断言 */
#define vAssertCalled(char, int) printf("Error: %s, %d\r\n", char, int)
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

/* FreeRTOS MPU 特殊定义 */
//#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
//#define configTOTAL_MPU_REGIONS                                8
//#define configTEX_S_C_B_FLASH                                  0x07UL
//#define configTEX_S_C_B_SRAM                                   0x07UL
//#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY            1
//#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS             1

/* ARMv8-M 安全侧端口相关定义。 */
//#define secureconfigMAX_SECURE_CONTEXTS         5

#endif /* FREERTOS_CONFIG_H */

 

六、总结

上述实验中虽然实现了将FreeRTOS移植到了比赛指定的板子上面, 但是由于SRAM的大小有限, 当代码量很大的时候就会出现硬件异常。所以咱们比赛使用的板子还是不适合移植FreeRTOS。

七、FreeRTOS学习资源

正点原子资料下载: 正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档

B站教程

在这里对正点原子背后的工作人员、授课老师致以崇高的敬意。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《八》QSplitter拆分器以及QDockWidget窗口详解

QSplitter简介 QSplitter拆分器允许用户通过拖动子部件之间的边界来控制它们的大小。 单个拆分器可以控制任意数量的小部件。QSplitter的典型用法是创建几个小部件&#xff0c;并使用insertWidget()或addWidget()添加它们。 常用方法 默认情况下&#xff0c;QSplitter会动态…

甘特图是什么?如何利用其优化项目管理流程?

甘特图是项目管理软件中十分常见的功能&#xff0c;可以说每一个项目经理都要学会使用甘特图才能更好的交付项目。什么是甘特图&#xff1f;甘特图用来做什么&#xff1f;简单来说一种将项目任务与时间关系直观表示的图表&#xff0c;直观地展示了任务进度和持续时间。 一、甘特…

【k8s】:kubectl 命令设置简写启用自动补全功能

【k8s】&#xff1a;kubectl 命令设置简写&启用自动补全功能 1、设置kubectl命令简写2、启用kubectl自动补全功能 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Kubernetes&#xff08;K8s&#xff09;是一个强大的容器编排平台&#…

【话题】程序员如何搞副业,简单探讨下

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景前提条件打造私域广结朋友平台 技能转化为价值1. 副业途径2. 如何开展3. 未来趋势与建议4. 挑战与策略5. 规划与发展 文章推荐 背景 程序员不仅拥有将抽象概念转化…

极海APM32F003F6U7通过AEC-Q100车规级可靠性认证

行车安全是汽车行业考虑的第一要义&#xff0c;因此汽车电子MCU的可靠性尤为重要&#xff0c;极海APM32F003F6U7车规级MCU遵循AEC-Q100质量标准&#xff0c;确保汽车电子元器件在极端环境下的可靠性和稳定性&#xff0c;并顺利通过了AEC-Q100车规级可靠性认证。 关于AEC-Q100 …

Vitis HLS 学习笔记--ap_int.h / ap_fixed.h(2)-深度探究

目录 1. 前文回顾 1.1 简单背后的复杂 1.2 复杂性的来源 2. 关键代码 2.1 功能概述 2.2 关系梳理 2.3 理解构造函数二 2.4 理解HLS_CONSTEXPR 2.5 理解const volatile 3. 探究ap_int<8> c&#xff1b;经历了什么 4. 在调试中查看 1. 前文回顾 在《Vitis HLS…

基于springboot实现厨艺交流平台系统项目【项目源码+论文说明】

基于SpringBoot实现厨艺交流平台系统演示 摘要 使用旧方法对厨艺交流信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在厨艺交流信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时…

[算法] 动态规划

对这个算法的原有印象就是非常难理解&#xff0c;而且怎么都感觉这个算法名称有些误导&#xff1b;或者是要引申着看&#xff1f;因为里面的动态是怎么个动态&#xff1f; 这里的动态是指每一次的计算结果会影响下一次&#xff0c;或者再次的运算效率&#xff0c;也就是说下一次…

瀑布流组件(vue2)

文档连接&#xff1a;clz 加载状态、行数 可以自行控制&#xff0c;目前只支持vue2 实现效果&#xff1a;

华为手机无法弹出wifi上网认证页面处理

华为手机无法弹出wifi上网认证页面 连wifi后跳到上图界面卡住&#xff0c;不跳转到单位的上网认证界面。 打开手机的设置应用&#xff0c;点击上面的WLAN选项。 点击上面的更多WLAN设置选项。 关闭WLAN安全检测就可以正常弹出上网认证界面&#xff0c; 正常弹出上网认证界面&a…

【RAR技巧】rar压缩包的三种加密方法

文件压缩成rar压缩包后&#xff0c;想要保护文件内容不被他人随意解压&#xff0c;我们可以给rar压缩包设置加密&#xff0c;今天分享3种方法设置rar文件加密方法。 方法一&#xff1a;加密 最简单的加密方法&#xff0c;就是在加密文件时输入想要设置的密码&#xff0c;完成…

栈和队列-介绍与实现(超级详解-C语言)

栈 栈的介绍 栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈…

Mac中隐私安全性设置-打开任何来源

文章目录 **Mac中隐私安全性设置-打开任何来源**一、目的二、打开方式 Mac中隐私安全性设置-打开任何来源 一、目的 从外部下载的软件频繁打不开&#xff0c;需要从隐私安全性中重新选择一下&#xff1b;默认Mac隐藏了任何来源 二、打开方式 打开终端&#xff0c;输入一下命…

配置BFD

目录 原理概述 实验目的 实验内容 实验拓扑 1.基本配置 2.配置OSPF路由协议 3.配置VRRP协议 4.配置BFD 原理概述 为了减小设备故障对网络业务造成的影响&#xff0c;提高网络的可用性&#xff0c;网络设备需要能够尽快检测到与相邻设备之间的通信故障&#xff0c;以便及…

详解运算符重载——探索运算符重载的应用

前言:运算符重载是面向对象的一个重要的知识点。我们都知道内置类型可以进行一般的运算符的运算。但是如果是一个自定义类型&#xff0c; 这些运算符就无法使用了。那么为了解决这个问题&#xff0c; 我们的祖师爷就在c中添加了运算符重载的概念。 本篇主要通过实例的实现来讲述…

短视频批量采集提取软件|视频下载工具

短视频批量采集提取软件&#xff1a;高效获取视频资源 一、开发背景 在日常业务中&#xff0c;我们经常需要获取大量的短视频资源&#xff0c;以支持各种需求&#xff0c;但传统的获取方式过于繁琐&#xff0c;一一复制链接下载效率低下。基于此需求&#xff0c;我们开发了一…

rocketmq-dashboard打包测试报错

rocketmq-dashboard运行的时候没问题&#xff0c;但是打包执行测试的时候就是报错 这时候跳过测试就可以成功 报错为 There are test failures. Please refer to D:\CodeEn\rocketmq-dashboard\target\surefire-reports for the individual test results. 你只需要跳过测试就…

Wpf 使用 Prism 实战开发Day20

备忘录功能页面完善以及优化 备忘录功能基本跟前一章节的待办事项差不多一至&#xff0c;就不再做过多的笔述了 一.备忘录功能完整页面源码 MemoView.xaml <UserControl x:Class"MyToDo.Views.MemoView"xmlns"http://schemas.microsoft.com/winfx/2006/xam…

用html写一个搜索页面

<!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>搜索框设计</title><link rel"stylesheet" href"./style.css"> </head> <body> <div class"se…

TypeScript基础入门(一、常用类型)

目录 第一章 前言 1.1 介绍TypeScript 1.2 TypeScript相比Js的优势 1.3 使用TypeScript的准备工作 第二章 TypeScript的数据类型 2.1 TypeScript的常用类型 2.1.1 概述 2.1.2 TS使用JS基本数据类型 2.1.2.1 number 2.1.2.2 string 2.1.3.3 boolean 2.1.2.4 null 2…