STM32G473VET6 在 Keil MDK 下手动移植 FreeRTOS 指南
下面将详细介绍如何在 Keil MDK 环境下将 FreeRTOS 手动移植到 STM32G473VET6 微控制器上。内容涵盖工程创建、获取源码、文件组织、移植层适配、测试任务编写以及编译调试等步骤。
1. 工程搭建(Keil 项目创建)
- 创建基础工程:首先准备一个基础的 STM32G473VET6 工程(例如一个点灯工程)。可以使用 STM32CubeMX 生成 Keil uVision 工程,勾选需要的外设驱动和初始化代码(如 HAL 库)以简化后续开发。确保工程包含 STM32G4的启动文件(如
startup_stm32g473xx.s)和系统时钟配置代码(SystemInit()或 HAL 的SystemClock_Config())。 - 配置 Keil 工程选项:在 Keil 中选择正确的器件和编译器。对于 Cortex-M4F 内核,启用硬件 FPU 支持。使用 ARM Compiler 5 可以直接使用 FreeRTOS 提供的 RVDS 移植代码;如果使用 ARM Compiler 6,需要确保使用对应的移植代码或兼容设置。
- 包含 HAL 库(可选):如果使用 STM32CubeMX 生成的工程并选择了 HAL 驱动,则工程已包含 HAL 库和CMSIS设备支持。HAL 库的使用是可选的,但如果使用HAL,需要注意其与 FreeRTOS 的时间基准(SysTick)的配合。
完成上述基础工程搭建后,确保一个简单的裸机程序(如LED闪烁)可以编译运行,以此作为移植 FreeRTOS 的起点。
2. 获取 FreeRTOS 源码
- 下载最新 FreeRTOS 内核:从 FreeRTOS 官方网站获取最新版本的内核源码压缩包。解压后,会看到包含
FreeRTOS/Source源码目录以及各类 Demo 示例等。我们主要关注FreeRTOS/Source下的文件。 - 整理所需源码文件:FreeRTOS 提供了很多可选组件,我们在移植时只保留必要的内核源文件。将以下文件从
FreeRTOS/Source复制到工程目录(建议放入Middlewares/FreeRTOS/Source):- 内核核心:
tasks.c(任务调度与管理)、queue.c(队列和信号量实现)、list.c(内核链表)、timers.c(软件定时器,可选)、event_groups.c(事件标志组,可选)、croutine.c(协程,可选,根据需要)等。这些文件实现了任务管理、调度器、队列、软件定时器、事件组等核心功能。 - 头文件:复制
FreeRTOS/Source/include目录下的所有头文件到工程的FreeRTOS/Source/include(或指定一个包含路径)。这些头文件定义了FreeRTOS API和配置项。
- 内核核心:
- 移植层与内存管理:在
FreeRTOS/Source/portable目录下,根据使用的内核架构和编译器选择正确的移植层代码:- 针对 STM32G473 (Cortex-M4F 内核) 和 Keil MDK 编译器,使用路径
portable/RVDS/ARM_CM4F下的文件。这通常包含port.c和portmacro.h,实现与 Cortex-M4F 内核相关的上下文切换和中断处理代码。将ARM_CM4F文件夹复制到工程的FreeRTOS/Source/portable下。 - 内存管理方面,FreeRTOS 提供多种堆管理实现。在
portable/MemMang目录下选择一款堆实现源码文件,例如常用的 heap_4.c(最佳适应算法,支持分配和释放)或 heap_5.c(支持多内存区)。复制所选的heap_x.c文件到FreeRTOS/Source/portable/MemMang并加入工程。其余未用的portable子目录和堆实现文件可不添加,以减少干扰。
- 针对 STM32G473 (Cortex-M4F 内核) 和 Keil MDK 编译器,使用路径
- 添加到 Keil 工程:在 Keil 中,为 FreeRTOS 创建分组并添加上述源文件。例如,新建 “FreeRTOS_CORE” 分组添加内核
.c文件(tasks.c、queue.c 等),新建 “FreeRTOS_PORT” 分组添加移植层和堆文件(如port.c、heap_4.c等)。同时,在工程的 C/C++ Include 路径中增加 FreeRTOS 的头文件目录(例如Middlewares\FreeRTOS\Source\include以及Middlewares\FreeRTOS\Source\portable\RVDS\ARM_CM4F),以便编译器能够找到FreeRTOS.h、portmacro.h等头文件。 - 获取或创建 FreeRTOSConfig.h:
FreeRTOSConfig.h是用于配置 FreeRTOS 内核的头文件,不包含在上述源码中。我们需要为 STM32G4 创建该文件并根据需求进行配置。可以参考 FreeRTOS 提供的示例配置(例如在 FreeRTOS/Demo 或 STM32 的示例中查找类似 STM32 的配置),复制并修改后加入工程的 Inc 或 FreeRTOS/include 目录。确保在编译选项的包含路径中能找到该文件。下面将在下一节详细说明关键配置项。
3. 文件结构整理与 FreeRTOSConfig 配置
- 工程目录组织:按照惯例,可将 FreeRTOS 源码放置在工程目录下的
Middlewares/FreeRTOS文件夹中,并划分子目录:Middlewares/FreeRTOS/Source:放置 FreeRTOS内核.c源文件和include头文件。Middlewares/FreeRTOS/Source/portable:放置移植层相关文件。其中portable/RVDS/ARM_CM4F存放 Cortex-M4F + Keil 移植代码,portable/MemMang存放所选择的堆管理实现。- (如果使用 CubeMX 自动生成中间件结构,可直接将文件对号入座到对应文件夹。)
- FreeRTOSConfig.h 关键配置:打开新建的
FreeRTOSConfig.h,根据 STM32G473VET6 的硬件参数和应用需求设置各项宏定义。以下是常用配置项:- 系统频率:
configCPU_CLOCK_HZ定义CPU时钟频率(Hz)。可设置为系统时钟频率数值或使用SystemCoreClock变量。例如:#define configCPU_CLOCK_HZ (SystemCoreClock)
- 系统频率:
确保这个值与系统实际运行频率匹配。
- Tick 定时频率:
configTICK_RATE_HZ定义RTOS滴答时钟频率,即系统节拍中断频率。常用设为1000Hz(1ms周期)。需与 SysTick 配置匹配。 - 最大优先级数:
configMAX_PRIORITIES定义系统可用的任务优先级数量(优先级从0到configMAX_PRIORITIES-1)。根据应用需要设置一个合适值,比如5或以上。注意至少要大于等于使用的优先级数,Idle任务优先级为0。 - 最小空闲任务栈:
configMINIMAL_STACK_SIZE定义空闲任务的栈深度(以字为单位)。Cortex-M4上一般设置为128(即512字节)或根据需求调整。 - 总堆大小:
configTOTAL_HEAP_SIZE定义FreeRTOS可用的堆内存总字节数(仅对heap_1.c, heap_2.c, heap_4.c, heap_5.c等有效)。根据创建的任务、队列等数量估算所需内存并设置。例如设为(10*1024)表示10KB,用于容纳所有动态分配对象。 - 内核特性开关:根据需要启用或禁用内核功能宏:
configUSE_PREEMPTION设置为1启用抢占式调度(常用),为0则为协作式调度。configUSE_TIME_SLICING为1则同优先级任务时间片轮转。configUSE_IDLE_HOOK/configUSE_TICK_HOOK设置是否使用空闲任务和Tick中断的钩子函数(如不需要可设0)。configUSE_MUTEXES、configUSE_COUNTING_SEMAPHORES等设为1启用互斥信号量和计数信号量。configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS可用于启用运行时统计(如 uxTaskGetSystemState)。configGENERATE_RUN_TIME_STATS如需启用运行时间统计(需要提供时钟源)。- 其他比如
configCHECK_FOR_STACK_OVERFLOW(栈溢出检查),configUSE_MALLOC_FAILED_HOOK(内存分配失败钩子)可按需设置。
- 软件定时器和事件组:如果使用软件定时器和事件标志组:
- 设置
configUSE_TIMERS为1,并配置configTIMER_TASK_PRIORITY(定时器服务任务优先级,一般高于普通任务),configTIMER_QUEUE_LENGTH(定时器命令队列长度),configTIMER_TASK_STACK_DEPTH(定时器任务栈深度)。 - 设置
configUSE_EVENT_GROUPS为1 以启用事件组机制。
- 设置
- 中断优先级配置:针对 Cortex-M 内核,以下配置 极为重要,必须正确设置中断优先级相关宏,以确保 FreeRTOS 安全运行:
configPRIO_BITS:NVIC 可用优先级位数。STM32G4 系列有 4 位优先级(0-15级),因此configPRIO_BITS应定义为4(如果CMSIS的__NVIC_PRIO_BITS已定义则可用它)。configLIBRARY_LOWEST_INTERRUPT_PRIORITY:应用可设置的最低中断优先级数值。STM32优先级数值越大优先级越低,一般设为15(表示最低优先级)。configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY:使用FreeRTOS系统调用的最高中断优先级数值。建议选择一个较高的优先级等级,例如5(表示任何优先级数值<=5的中断服务例程 不应调用FreeRTOS API)。configKERNEL_INTERRUPT_PRIORITY:内核所使用的中断优先级(用于PendSV和SysTick)。通常定义为configLIBRARY_LOWEST_INTERRUPT_PRIORITY左移适当位数,使其成为最低优先级。例如:
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
若优先级位4位,上式计算结果为 15 << 4 = 240 (0xF0),对应 NVIC 优先级15。这确保RTOS内核的中断(PendSV/SysTick)设为最低优先级。
configMAX_SYSCALL_INTERRUPT_PRIORITY:可调用系统API的最高中断优先级(临界值)。定义为configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY左移 (8 -configPRIO_BITS) 位。例如优先级5则计算为5 << 4 = 80(0x50),对应 NVIC 优先级5- 设置上述优先级配置后,务必在应用中确保所有使用 FreeRTOS API的中断的NVIC优先级数值大于等于
configMAX_SYSCALL_INTERRUPT_PRIORITY(例如设为5或更大,即优先级不高于5级),否则会触发优先级嵌套错误。 - 。这意味着优先级数值小于5的中断(更高优先级的中断)不应调用FreeRTOS安全API。
配置完成后,保存 FreeRTOSConfig.h。经过以上设置,FreeRTOS内核行为就根据目标硬件和应用需求进行了调整。
4. 移植层适配(中断向量与启动文件调整)
在将 FreeRTOS 集成到 STM32G4 时,需要确保 Cortex-M 内核的几个特殊中断(SVC、PendSV、SysTick)正确地连接到 FreeRTOS 的调度机制。这涉及移植层代码和启动文件的适配:
-
重定向内核中断处理函数:FreeRTOS 的 Cortex-M 移植在
port.c中实现了 SVC、PendSV 和 SysTick 中断处理逻辑。但我们需要把这些处理例程挂接到实际的中断向量。常用方法有两种:-
宏定义映射法:在
FreeRTOSConfig.h中添加宏,将 FreeRTOS 移植层的中断处理函数名映射为标准中断名。例如:#define vPortSVCHandler SVC_Handler #define xPortPendSVHandler PendSV_Handler #define xPortSysTickHandler SysTick_Handler这样,编译器在编译移植层代码时会将实现函数名替换为对应的中断名,从而覆盖启动文件中的默认中断处理。STM32CubeMX 生成的FreeRTOS配置常用此方法,其中将 SysTick 的映射宏默认注释是因为 HAL 自带 SysTick handler(如果我们希望RTOS接管SysTick,需要启用该宏)。通过这种方式,FreeRTOS 的
vPortSVCHandler()实际编译为SVC_Handler,xPortPendSVHandler()编译为PendSV_Handler,xPortSysTickHandler()编译为SysTick_Handler,从而自动替换掉弱定义的默认 handlers。 -
启动文件重定向法:直接修改启动文件
startup_stm32g473xx.s,将向量表中相应中断的入口指向 FreeRTOS 提供的函数。具体做法是在启动文件中声明移植层函数为外部符号,并将中断入口替换为跳转。例如,在启动文件的中断向量表区域,找到PendSV_Handler、SysTick_Handler和SVC_Handler的默认实现,替换为:EXTERN vPortSVCHandler EXTERN xPortPendSVHandler EXTERN xPortSysTickHandler SVC_Handler B vPortSVCHandler ; 跳转到FreeRTOS的SVC处理 PendSV_Handler B xPortPendSVHandler ; 跳转到FreeRTOS的PendSV处理 SysTick_Handler B xPortSysTickHandler ; 跳转到FreeRTOS的SysTick处理如此修改后,这三个中断会触发 FreeRTOS 对应的服务例程,实现上下文切换和心跳节拍。
-
注意:采用上述两种方法之一即可,通常推荐使用第一种映射宏的方法,修改少且清晰。如果使用HAL库且其SysTick作为时基,默认HAL会定义自己的
SysTick_Handler,这时更需要使用映射或修改启动文件,确保RTOS的SysTick处理生效而HAL的时基不中断系统滴答(可选择在FreeRTOS的滴答钩子中调用HAL_IncTick()以保持HAL时基)。
-
SysTick 定时器设置:FreeRTOS利用 SysTick 产生固定频率的节拍中断用于任务调度。需要保证 SysTick 定时中断按照
configTICK_RATE_HZ配置的频率触发:- 如果基础工程使用了 HAL,
HAL_Init()默认将 SysTick 配置为1ms中断(1000Hz)。若configTICK_RATE_HZ也是1000,则默认配置可用,但要确保 SysTick 中断由 FreeRTOS接管。如上所述,可以在 FreeRTOS的 SysTick_Handler 中调用xPortSysTickHandler()实现RTOS心跳,同时也可调用HAL_IncTick()保持HAL的时基计数。 - 如果未使用 HAL 或需手动配置:可以在系统初始化时配置 SysTick 寄存器。计算加载值:
reload = SystemCoreClock / configTICK_RATE_HZ,然后设置 SysTick:SysTick->LOAD = reload - 1; // 装载值 SysTick->VAL = 0; // 清零计数器 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // 使能SysTick中断 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 启动SysTick同时选择合适的时钟源(如使用外部HCLK)。这样SysTick每
1/configTICK_RATE_HZ秒产生一次中断。在 SysTick 中断服务函数中,应调用 FreeRTOS 的心跳处理函数。例如:void SysTick_Handler(void) { if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); } }述实现确保只有在调度器启动后才调用 RTOS 的滴答处理(在调度器启动前 SysTick 中断也许已经开启,此时不应调用RTOS API)。
- 如果基础工程使用了 HAL,
- PendSV 和 SVC 中断:PendSV 用于触发上下文切换,应设置为最低优先级,以免打断高优先级中断。SVC(Supervisor Call)在 FreeRTOS 中用于启动第一个任务,之后不再使用。通常无需手动配置其优先级(默认即可),PendSV 和 SysTick 优先级会在 FreeRTOS启动时根据
configKERNEL_INTERRUPT_PRIORITY设置。在移植过程中,只需确保上述映射正确,FreeRTOS 会将 PendSV/SysTick 设置为最低优先级。 - NVIC 中断优先级分组:STM32 默认优先级分组通常将全部4位用于抢占优先级(无子优先级)。确保保持这种配置(一般无需额外修改SCB->AIRCR)。这保证了
configMAX_SYSCALL_INTERRUPT_PRIORITY规定的优先级阈值正确生效。
完成移植层适配后,FreeRTOS 核心应能正确接管 SVC、PendSV、SysTick 中断,实现其调度功能。可以编译工程,确保链接阶段没有未定义引用(尤其是 vPortSVCHandler 等应已映射或定义)。
5. 编写测试任务
移植完成后,在 main.c 中创建示例任务以验证 RTOS 调度运行是否正常:
-
初始化:在创建任务之前,执行必要的硬件初始化。例如调用
HAL_Init()和SystemClock_Config()(若使用HAL);初始化用于测试的外设,如配置GPIO用于控制LED,初始化UART用于串口打印等。确认此时不要调用会引起延时阻塞的函数(如HAL_Delay()),以免在RTOS启动前产生不确定延时。 -
创建任务:使用 FreeRTOS 提供的 API 创建至少两个任务进行演示:
- LED 闪烁任务:例如创建一个周期性闪烁板上 LED 的任务。任务函数中反复切换 LED 引脚状态并调用
vTaskDelay()延时一定 Tick 数(如500ms),以测试定时调度功能。 - 串口打印任务:创建另一个任务,周期性地通过串口打印消息(比如每1秒打印一行文本或计数值)。这可以测试多个任务并行运行,以及任务间的独立性。如使用HAL UART发送,可在任务中调用
HAL_UART_Transmit()发送字符串(注意需确保串口初始化在RTOS启动前完成,或使用互斥确保线程安全)。
使用
xTaskCreate()创建任务时,需要提供任务入口函数、任务名、栈大小、任务参数、优先级和任务句柄等参数。例如:xTaskCreate(LED_Task, "LEDTask", 128, NULL, 2, NULL); xTaskCreate(UART_Task, "UARTTask", 256, NULL, 2, NULL);上述示例创建了LED_Task和UART_Task,分别指定了栈深度(128和256字,具体值视功能需求而定)和优先级(这里都为2,同优先级将时间片轮转执行)。可以根据需要调整优先级以验证优先级调度效果(优先级数值越大,优先级越高)。
- LED 闪烁任务:例如创建一个周期性闪烁板上 LED 的任务。任务函数中反复切换 LED 引脚状态并调用
-
启动调度器:所有任务创建完成后,调用
vTaskStartScheduler()启动FreeRTOS调度。该函数调用后,RTOS 接管CPU控制权,开始根据优先级和时间片调度任务。注意:vTaskStartScheduler()若返回则意味着调度启动失败(通常是因为堆内存不足无法创建Idle任务),这种情况下可以在main函数中添加错误处理,例如进入死循环或触发断言,以便调试发现问题。正常情况下该调用不会返回。 -
任务函数示例:下面给出简要的任务函数代码片段示例:
void LED_Task(void *argument) {for(;;) {HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); // 切换LED引脚状态vTaskDelay(pdMS_TO_TICKS(500)); // 延时500ms (pdMS_TO_TICKS宏将毫秒转换为节拍数)} }void UART_Task(void *argument) {const char *msg = "Hello from FreeRTOS!\r\n";for(;;) {HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);vTaskDelay(1000); // 延时1000ms} } -
在上述代码中,LED任务每0.5秒翻转一次LED状态,UART任务每1秒通过串口发送一条消息。两个任务的死循环中都使用了
vTaskDelay或等效宏进行阻塞延时,让出CPU给其他任务。 -
注意 HAL 与 RTOS 的配合:如果使用了HAL库,在RTOS启动后不要使用
HAL_Delay()进行延时,因为HAL_Delay依赖于SysTick全局变量的中断更新。在FreeRTOS接管SysTick后,默认HAL的滴答不再增长(除非在SysTick_Handler中继续调用HAL_IncTick)。应改用vTaskDelay等RTOS延时机制来替代阻塞延时。此外,如果串口中断等外设中断需要调用FreeRTOS API(如xQueueSendFromISR),务必确保这些中断优先级符合前述configMAX_SYSCALL_INTERRUPT_PRIORITY限制。
完成上述移植和任务创建后,进行编译、下载并调试,重点关注以下方面:
-
系统滴答验证:调试时,可以在 SysTick_Handler 中打断点,或读取
xTaskGetTickCount()返回值,确认滴答计数在持续增长,频率符合预期的configTICK_RATE_HZ。例如,可在UART打印任务中定期打印xTaskGetTickCount()值来观察。 -
任务调度检查:观察板上 LED 是否按设计频率闪烁,串口打印是否按周期输出。如果只有一个任务运行、另一个任务饿死,可能是优先级配置不当或某任务陷入死循环未调用阻塞API。确保每个任务在适当位置会阻塞或延时,以让出CPU。还可以使用Keil的调试器查看FreeRTOS线程列表(如果安装了FreeRTOS调试插件)以确认多个任务都处于就绪/阻塞状态并被调度。
-
中断优先级问题:如果程序跑一段时间后出现HardFault或异常,常见原因是中断优先级配置不正确导致违反了FreeRTOS的中断安全策略。检查 FreeRTOSConfig.h 中
configMAX_SYSCALL_INTERRUPT_PRIORITY的设置以及有无中断使用了过高的优先级调用了RTOS API。如有需要,可在 FreeRTOSConfig.h 中定义configASSERT()钩子,以捕获运行时的优先级违规等错误。 -
堆内存使用:使用
xPortGetFreeHeapSize()查询剩余堆内存。该函数返回当前未被分配的堆空间大小,有助于判断configTOTAL_HEAP_SIZE设置是否合理。示例:在所有任务创建后调用xPortGetFreeHeapSize(),如果返回值很小(接近0),说明堆几乎耗尽,需要增大 configTOTAL_HEAP_SIZE;如果返回值远大于实际需要,可以优化减小 configTOTAL_HEAP_SIZE 以节省RAM。FreeRTOS还提供xPortGetMinimumEverFreeHeapSize()可查询历史最低剩余堆空间,用于评估最糟情况内存占用。 -
其他调试技巧:可开启
configCHECK_FOR_STACK_OVERFLOW(并实现vApplicationStackOverflowHook)来捕获任务栈溢出;开启configUSE_MALLOC_FAILED_HOOK(并实现vApplicationMallocFailedHook)来捕获内存分配失败。这些钩子在调试阶段很有帮助。一旦系统运行正常,可以选择关闭或保留这些检查。
经过以上步骤,如果 LED 按预期闪烁且串口输出正常,就表明 FreeRTOS 在 STM32G473VET6 上已成功移植并运行。由此可以进一步开发应用,比如创建更多任务,利用队列、信号量等进行任务间通信。在实际项目中,按照上述指南配置 FreeRTOS,可确保系统稳定运行于 Keil MDK 环境下。
相关文章:
STM32G473VET6 在 Keil MDK 下手动移植 FreeRTOS 指南
下面将详细介绍如何在 Keil MDK 环境下将 FreeRTOS 手动移植到 STM32G473VET6 微控制器上。内容涵盖工程创建、获取源码、文件组织、移植层适配、测试任务编写以及编译调试等步骤。 1. 工程搭建(Keil 项目创建) 创建基础工程:首先准备一个基…...
WPF中对滚动条进行平滑滚动
有时候我们在动态添加内容时,需要将滚动条滚动到指定内容处。 一般我们会调用ScrollViewer的ScrollToVerticalOffset(垂直方向)函数和ScrollToHorizontalOffset(水平方向)函数来控制滚动条滚动到指定位置。 正常滚动效…...
API,URL,Token,XML,JSON是干嘛的
API,URL,Token,XML,JSON是干嘛的 API的作用 API(Application Programming Interface,应用程序编程接口)是一组定义和协议,用于构建和交互软件应用程序。API允许不同的软件系统之间…...
Threejs 解析几何体提取顶点数据流程
目录 前言 原生WebGL 整体解析过程简介 顶点颜色属性Geometry.colors Geometry转化为BufferGeometry 相关函数 WebGLAttributes.js WebGLGeometries.js WebGLObjects.js WebGLRenderer.js WebGLRenderer.js 前言 解析几何体对象,提取顶点数据…...
浮动与清除浮动
浮动(float)是CSS中用于布局的重要属性,它使元素脱离正常的文档流,并向左或向右移动,直到碰到另一个浮动元素或父元素的边界。 浮动的定义和作用 定义:浮动是通过设置 float 属性使元素脱离正常的文档流&a…...
YOLOv5 + SE注意力机制:提升目标检测性能的实践
一、引言 目标检测是计算机视觉领域的一个重要任务,广泛应用于自动驾驶、安防监控、工业检测等领域。YOLOv5作为YOLO系列的最新版本,以其高效性和准确性在实际应用中表现出色。然而,随着应用场景的复杂化,传统的卷积神经网络在处…...
极简Redis速成学习
redis是什么? 是一种以键值对形式存储的数据库,特点是基于内存存储,读写快,性能高,常用于缓存、消息队列等应用情境 redis的五种数据类型是什么? 分别是String、Hash、List、Set和Zset(操作命…...
教育培训APP开发全攻略:从网校系统源码搭建到功能优化的技术方案
本篇文章,笔者将从网校系统源码搭建到功能优化的角度,全面解析教育培训APP的开发技术方案,帮助企业和开发者更好地理解如何提升在线教育平台的性能与用户体验。 一、教育培训APP开发的核心架构 教育培训APP的架构设计是其能否顺利运行和扩展…...
网络安全与认知安全的区别 网络和安全的关系
前言 说说信息安全 与网络安全 的关系 一、包含和被包含的关系 信息安全包括网络安全,信息安全还包括操作系统安全,数据库安全 ,硬件设备和设施安全,物理安全,人员安全,软件开发,应用安全等。…...
16.1 LangChain 表达式语言(LCEL)深度解析:构建灵活高效的大模型应用流水线
LangChain 表达式语言(LCEL)深度解析:构建灵活高效的大模型应用流水线 关键词:LangChain 表达式语言、LCEL 编程范式、大模型应用编排、流式处理优化、生产级链式开发 1. LCEL 设计哲学与核心优势 1.1 为何需要 LCEL? #mermaid-svg-pIEGtObTES1T3LgF {font-family:"…...
介绍微信小程序中页面的生命周期函数和组件的生命周期函数
1.1 页面生命周期函数 这些函数主要用于管理页面的显示和隐藏。 onLoad(options): 页面加载时触发,options 是页面路由参数,可以在这里初始化数据。每当用户进入该页面时都会调用这个函数。 onShow(): 页面显示时触发。每当页面从后台切换到前台时都会…...
arm | lrzsz移植记录
1 我的使用场景 开发板无网络, 无奈只得用U盘拷贝文件 文件不大, 每次都插拔U盘, 很繁琐 原来的环境不支持rz等命令 就需要移植这个命令来使用 下载地址 https://ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz 2 编译脚本 # 主要内容在这里 configure_for_arm(){mkdir -p $PA…...
智能机器人加速进化:AI大模型与传感器的双重buff加成
Deepseek不仅可以在手机里为你解答现在的困惑、占卜未来的可能,也将成为你的贴心生活帮手! 2月21日,追觅科技旗下Dreamehome APP正式接入DeepSeek-R1大模型,2月24日发布的追觅S50系列扫地机器人也成为市面上首批搭载DeepSeek-R1的…...
Qt:day1
一、作业 写1个Widget窗口,窗口里面放1个按钮,按钮随便叫什么; 创建2个Widget对象: Widget w1, w2; w1.show(); w2不管; 要求: 点击 w1.btn,w1隐藏,w2显示; 点击 w2.btn&…...
端口映射/内网穿透方式及问题解决:warning: remote port forwarding failed for listen port
文章目录 需求:A机器是内网机器,B机器是公网服务器,想要从公网,访问A机器的端口方式:端口映射,内网穿透,使用ssh打洞端口:遇到问题:命令执行成功,但是端口转发…...
Java从根上理解 ConcurrentHashMap:缓存机制与性能优化
目录 一、ConcurrentHashMap 的核心原理1. 数据结构2. 锁机制3. 扩容机制二、ConcurrentHashMap 的缓存机制1. 缓存的实现2. 缓存的更新策略三、ConcurrentHashMap 的性能优化1. 减少锁竞争2. 优化数据结构3. 合理设置容量和负载因子四、具体代码示例1. 创建 ConcurrentHashMap…...
通过百度构建一个智能体
通过百度构建一个智能体 直接可用,我不吝啬算力 首先部署一个模型,我们选用deepseek14 构建智能体思考步骤,甚至多智能体; from openai import OpenAIclass Agent:def __init__(self, api_key, base_url, model...
【MySQL】(1) 数据库基础
一、什么是数据库 数据库自行选择了合适的数据结构来组织数据,方便用户写入(存储介质,如硬盘,机器断电不会丢失数据)和查询数据。在数据结构部分,我们讲到的 ArrayList、HashMap 集合类对象也能存储数据&am…...
DeepSeek后训练:监督微调和强化学习
注:此文章内容均节选自充电了么创始人,CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》(人工智能科学与技术丛书)【陈敬雷编著】【清华大学出版社】 文章目录 DeepSeek大模型技术系列十二DeepSeek大模型技术系列十二》DeepS…...
基于 MetaGPT 自部署一个类似 MGX 的多智能体协作框架
MGX(由 MetaGPT 团队开发的 mgx.dev)是一个收费的多智能体编程平台,提供从需求分析到代码生成、测试和修复的全流程自动化功能。虽然 MGX 本身需要付费,但您可以通过免费服务和开源项目搭建一个类似的功能。以下是一个分步骤的实现…...
三个小时学完vue3 —— 简单案例(二)
三个小时学完vue3(二) 图片轮播案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...
数字人技术再超越,TANGO 可生成与音频匹配的全身手势视频
TANGO 是由东京大学与 CyberAgent AI Lab 于 2024 年共同研发的开源框架,专注于声音驱动的全身数字人生成。该技术能够根据目标语音音频生成与之同步的全身手势视频,突破了传统数字人技术仅支持面部或上半身动作的局限性。TANGO 的工作原理利用隐式分层音…...
释放微软bing的力量:深度剖析其主要功能
在浩瀚无垠的互联网海洋中,搜索引擎就如同指南针,引领我们找到所需要的信息。微软必应凭借其一系列强大功能,在搜索引擎领域脱颖而出,成为极具竞争力的一员。在这篇博客文章中,我们将深入探讨微软必应的主要功能,这些功能使其独具特色,成为全球用户的得力工具。 1. 智能…...
DeepSeek 开源周(2025/0224-0228)进度全分析:技术亮点、调用与编程及潜在影响
DeepSeek 技术开源周期间所有开放下载资源的目录及简要说明: 1. FlashMLA 描述:针对 Hopper GPU 优化的高效 MLA 解码内核,专为处理可变长度序列设计,显著提升大语言模型(LLM)的解码效率。性能:内存受限配置下可达 3000 GB/s 带宽,计算受限配置下可达 580 TFLOPS 算力(…...
let、const【ES6】
“我唯一知道的就是我一无所知。” - 苏格拉底 目录 块级作用域:var、let、const的对比:Object.freeze(): 块级作用域: 块级作用域指由 {} 包围的代码块(如 if、for、while、单独代码块等)形成的独立作用…...
PySpark中mapPartitionsWithIndex等map类算子生成器函数问题 - return\yield
PySpark中mapPartitionsWithIndex等map类算子生成器函数问题 - return\yield 顾名思义,本文讲述了map算子生成器函数的相关问题——return 和 yield的使用。 首先先讲结论,在使用map等迭代生成的算子时最好使用yield。 1、问题产生 在写代码的过程中&…...
网络原理 初识[Java EE]
目录 网络发展史 独立模式 网络互联 局域网 LAN 1. 基于网络直连 2. 基于集线器(Hub)组建 3. 基于交换机(Switch)组建 4. 基于交换机和路由器(Router)组建 广域网 WAN 网络通信基础 IP 地址 1. 概念 2. 格式 端口号 1. 概念 2.格式 认识协议 1. 概念 2. 作用…...
Redis Stream基本使用及应用场景
一、概念 Redis Streams是Redis5.0提供的一种消息队列机制,支持多播的可持久化的消息队列,用户实现发布订阅的功能,借鉴了kafka设计。 二、常用命令 命令名称描述XADD key ID field value [field value ...]添加一条消息 key:St…...
amcl :odometry 到global frame 的转换
amcl - ROS Wiki amcl - ROS Wiki...
Ollama下载安装+本地部署DeepSeek+UI可视化+搭建个人知识库——详解!(Windows版本)
目录 1️⃣下载和安装Ollama 1. 🥇官网下载安装包 2. 🥈安装Ollama 3.🥉配置Ollama环境变量 4、🎉验证Ollama 2️⃣本地部署DeepSeek 1. 选择模型并下载 2. 验证和使用DeepSeek 3️⃣使用可视化工具 1. Chrome插件-Page …...
