STM32G431RBT6移植FreeRTOS

news2024/11/26 4:26:56

引言: 本文专门为参加了蓝桥杯嵌入式赛道的同学准备, 大家可能会有这样一个问题, 比完赛之后, 对于像继续使用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站教程

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

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

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

相关文章

多系统源代码暴露在互联网,超四百万公民个人信息存在泄露的风险

#哈尔滨等保# 一 安全事件阐述 截至2024年3月&#xff0c;绿盟科技创新研究院监测到上万个互联网中暴露的DevOps资产存在未授权访问情况。其中&#xff0c;源代码仓库成为未授权访问的“重灾区”。这些允许未授权访问的源代码仓库暴露了境内多家机构的重要系统源代码&#x…

html公众号页面实现点击按钮跳转到导航

实现效果&#xff1a; 点击导航自动跳转到&#xff1a; html页面代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>跳转导航</title><meta name"keywords" conten…

【AR开发示例】实现AR管线巡检

写在前面的话 这是一篇旧文档&#xff0c;代码仓库见 https://gitee.com/tanyunxiu/AR-pipe 本文档是基于超图移动端SDK的AR模块开发的示例&#xff0c;仅供参考&#xff0c;SDK在持续迭代中&#xff0c;相关描述可能有变化。 示例介绍 这是一个使用AR查看墙内管线的基础示…

uniapp 如何区分目前运行环境(app、web、mp-weixin)

platform 区分 iOS、Android uniplatform 区分 app、web、mp-weixin ....

fatal error LNK1120: xxxx unresolved externals

场景&#xff1a; A项目Library&#xff0c;编译环境VS2008DDKWarizd, 编译平台WIN7XP; B项目驱动, 编译环境VS2008&#xff0c;编译平台Rlease32位&#xff0c;DDK版本相同,都是7.0 在B项目集成A项目的32位LIB库时&#xff0c;出现此错误&#xff0c;看错误很常见的找不到符号…

Linux【实战】—— LAMP环境搭建 部署网站

目录 一、介绍 1.1什么是LAMP&#xff1f; 1.2LAMP的作用 二、部署静态网站 2.1 虚拟主机&#xff1a;一台服务器上部署多个网站 2.1.1 安装Apache服务 2.1.2 防火墙配置 2.1.3 准备网站目录 2.1.4 创建网站的配置文件 2.1.5 检查配置文件是否正确 2.1.6 Linux客户端…

润石科技(RUNIC)汽车电子应用方案和物料选型

一、润石科技&#xff08;RUNIC&#xff09;简介 江苏润石科技有限公司是一家专注于高性能、高品质模拟/混合信号集成电路研发和销售的高科技半导体设计公司。公司主要产品线分为两类&#xff1a;信号链和电源管理&#xff0c;其中信号链包含运算放大器、比较器、模拟开关、数…

Mac 部署 GPT-2 预训练模型 gpt2-chinese-cluecorpussmall

文章目录 下载 GPT-2 模型快速开始 GPT-2 下载 GPT-2 模型 https://huggingface.co/uer/gpt2-chinese-cluecorpussmall git clone https://huggingface.co/uer/gpt2-chinese-cluecorpussmall # 或单独下载 LFS GIT_LFS_SKIP_SMUDGE1 git clone https://huggingface.co/uer/gpt…

基于Spring Boot+Vue的校园网上店铺,开启便捷购物新模式

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

递归 python

↵一、简单理解 解决问题的一种方法&#xff0c;它将问题不断的分成更小的子问题&#xff0c;直到子问题可以用普通的方法解决。通常情况下&#xff0c;递归会使用一个不停调用自己的函数。 【注】&#xff1a;每一次递归调用都是在解决一个更小的问题&#xff0c;如此进行下…

Leetcode - 128双周赛

目录 一&#xff0c;3110. 字符串的分数 二&#xff0c;3111. 覆盖所有点的最少矩形数目 三&#xff0c;3112. 访问消失节点的最少时间​编辑 写法一&#xff1a;朴素 Dijkstra&#xff08;适用于稠密图&#xff0c;即边比较多的图&#xff09; 写法二&#xff1a;堆优化 …

⑤【Shiro】SpringBoot整合Shiro,实现登录认证

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ ⑤【Shiro】SpringBoot整合Shiro&#xff0c;实…

作为Boss,还在写代码。what?赶紧改掉这个坏毛病

有些创业中的老板&#xff0c;经常或者偶尔也要写代码&#xff0c;我听了很震惊呀&#xff0c;这叫创业吗&#xff1f;这不是给员工打工吗&#xff1f;其他重要的事情谁来干&#xff0c;这个毛病一定要改。 一、比起写代码&#xff0c;你还有更重要的事情要做 作为BOSS和创业…

.NET 爬虫从入门到入狱

目录 前言 1.&#x1f4a1;使用HttpClient爬取数据 2.&#x1f680;模拟User-Agent 3.&#x1f935;使用HTML解析库 3.&#x1f44c;前端Price显示 4.&#x1f331;运行实例 获取金价Au 5.&#x1f9fe;使用正则表达式解析 6.&#x1f4ab;获取BTC价格 7.✨获取CSDN热点…

【网站项目】书籍销售系统小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【云计算】安全组和网络ACL的区别

安全组和网络ACL的区别 ACL&#xff08;Access Control List&#xff09;和 安全组&#xff08;Security Group&#xff09;是两种不同的网络安全控制机制&#xff0c;通常用于管理云计算平台中的网络访问权限。它们在功能和实现上有一些显著的区别&#xff1a; 辨析 范围不同&…

大数据------额外插件及技术------Git(完整知识点汇总)

Git 定义 它是分布式版本控制工具&#xff0c;主要用于管理开发过程中的源代码文件&#xff08;如&#xff1a;Java类、xml文件、html页面等&#xff09;&#xff0c;在软件开发过程中被广泛应用 作用 代码回溯&#xff1a;快速回到某一代码历史版本版本切换&#xff1a;同一个…

【深度学习】Attention、Self-Attention、Multi-Head Attention

一、Attention 在CV领域&#xff0c;注意力机制通常分为通道注意力和空间注意力或者两者结合。 一张图像经backbone得到的特征通常包括多个通道&#xff0c;每个通道是一个像素矩阵&#xff0c;每个通道对任务的贡献不尽相同&#xff0c;单个通道的特征图中每个像素对任务的贡…

户外旅行摄影手册,旅游摄影完全攻略

一、资料前言 本套旅游摄影资料&#xff0c;大小295.47M&#xff0c;共有9个文件。 二、资料目录 《川藏线旅游摄影》杨桦.彩印版.pdf 《户外摄影指南》(Essential.Guide.to.Outdoor.photography.amateur)影印版.pdf 《旅行摄影大师班》(英)科尼什.扫描版.PDF 《旅行摄影…

Java垃圾回收1

1.对象什么时候可以被垃圾器回收 1.垃圾回收的概念 为了让程序员更专注于代码的实现&#xff0c;而不用过多的考虑内存释放的问题&#xff0c;所以&#xff0c; 在Java语言中&#xff0c;有了自动的垃圾回收机制&#xff0c;也就是我们熟悉的GC(Garbage Collection)。 有了垃圾…