STM32的 syscalls.c 和 sysmem.c

syscalls.c 是 STM32CubeIDE 自动生成的标准系统调用适配文件,用于裸机环境下支持 newlib 标准库(如 printf, scanf, malloc)的运行。这份文件提供了标准库运行所需的最小系统调用实现。现在我来逐段解析其作用,并补充你可能需要修改或关注的地方。


🧩 主要用途

该文件让 标准C库函数 在没有操作系统的 STM32 环境中可以正常工作。特别是:

  • printf() 调用 _write()(需要重定向到串口)
  • scanf() 调用 _read()(需要接收串口输入)
  • malloc() 依赖 _sbrk()(位于另一个文件 sysmem.c 中)

📄 文件结构解析

🔹 引入的头文件

#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>

用于提供标准类型定义和错误码,支持不同系统调用的原型和实现。


🔹 环境变量(通常忽略)

char *__env[1] = { 0 };
char **environ = __env;

🔹 核心系统调用函数(重点)

1. _write(): 用于 printf
__attribute__((weak)) int _write(int file, char *ptr, int len)
{(void)file;for (int i = 0; i < len; i++)__io_putchar(*ptr++);return len;
}

⚠️ __io_putchar()弱函数(weak),你需要在项目中自己实现这个函数,常用于串口重定向:

int __io_putchar(int ch)
{HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}
2. _read(): 用于 scanf
__attribute__((weak)) int _read(int file, char *ptr, int len)
{for (int i = 0; i < len; i++)*ptr++ = __io_getchar();return len;
}

你也需实现 __io_getchar(),如:

int __io_getchar(void)
{uint8_t ch;HAL_UART_Receive(&huart2, &ch, 1, HAL_MAX_DELAY);return ch;
}

🔹 其他系统调用(通常不使用,但需要实现以避免链接错误)

这些函数都是 dummy 实现(返回错误码),用于满足编译要求:

函数用途/说明
_exit()程序退出,死循环防止退出
_kill()假设无信号机制,返回错误
_getpid()返回 PID 1,占位
_close()文件关闭,占位
_fstat()标识为字符设备
_isatty()判断文件是否为终端,返回1
_lseek()文件定位,占位
_open()打开文件,占位
_unlink()删除文件,占位
_fork()无进程管理,占位
_execve()不支持执行程序
_wait()无子进程支持,占位
_times()占位
_link()占位
_stat()占位

✅ 如何启用 UART 输出功能?

  1. 确保开启 UART(比如 USART2)并启用 HAL_UART_Transmit
  2. 添加以下函数实现(在 main.c 或独立 retarget.c 文件)
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}int __io_getchar(void)
{uint8_t ch;HAL_UART_Receive(&huart2, &ch, 1, HAL_MAX_DELAY);return ch;
}

📝 如果你想改为 fputc() 重定向,也可以用以下方式:

int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}

不过 __io_putchar 更适合与 CubeIDE 生成的 syscalls.c 搭配使用。


🔚 总结

方面内容
是否需要改动?如果你要使用 printf/scanf,是的!
推荐修改点实现 __io_putchar__io_getchar
使用 HAL_UART 示例?是,可用于 STM32 串口输出

你提供的 sysmem.c 是 STM32CubeIDE 自动生成的内存分配支持文件,主要目的是实现标准 C 库 malloc 系列函数所依赖的 _sbrk() 系统调用。

这是嵌入式裸机编程中用于支持动态内存分配的 标准方法


🔍 核心作用:实现 _sbrk()

_sbrk(ptrdiff_t incr) 说明

该函数负责从 RAM 中划出堆空间。

void *_sbrk(ptrdiff_t incr)
  • incr: 要增加的堆大小(单位:字节)
  • 返回值: 成功时返回旧的堆尾地址,失败返回 (void *) -1 并设置 errno = ENOMEM

🧠 工作原理

它通过链接脚本中的符号 _end, _estack, _Min_Stack_Size 来判断内存边界:

 RAM 起始地址 → [.data][.bss][heap → → →] ... [stack] ← ← ← ← ← _estack(RAM末端)↑       ↑_end   _estack
  • __sbrk_heap_end:当前堆的“末尾指针”
  • _end:链接脚本中定义的 静态数据段结束地址(堆的起始)
  • _estack:RAM 顶部(栈的起点)
  • _Min_Stack_Size:为主堆栈指针(MSP)保留的空间,避免栈和堆冲突

⚠️ 如果你用的是默认 STM32CubeIDE 生成的 .ld 链接脚本,这些符号是自动生成的,你无需手动添加。


🧩 链接脚本中通常有以下内容(例如):

  ._user_heap_stack :{. = ALIGN(8);PROVIDE ( end = . );PROVIDE ( _end = . );. = . + _Min_Heap_Size;. = . + _Min_Stack_Size;. = ALIGN(8);} >RAM

⚠️ 如果你使用 malloc() 报错或崩溃…

  1. 确保链接器脚本中定义了 _end, _estack, _Min_Stack_Size

  2. 确保在 sysmem.c_sbrk() 没有超出 max_heap

  3. 调整堆栈大小:STM32CubeIDE 中修改:

    Project -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU Settings
    
    • 增大 Heap size
    • 调整 Stack size

✅ 示例:在 STM32 中使用 malloc()

#include <stdlib.h>char *buf = malloc(100);
if (!buf) {// 分配失败,内存不足
}

该调用会通过 malloc()sbrk() 来从 RAM 中申请空间


📝 总结

项目内容
文件作用支持 malloc 的底层实现
关键函数_sbrk()
内存边界判断依据_end, _estack, _Min_Stack_Size
错误处理堆超出栈保留区时返回 ENOMEM

Makefile 中用于链接(linking)的部分配置,主要用来指导 GCC 如何链接目标文件、库文件和链接脚本。

我们来逐项解释这几行内容。


🔍 内容逐行解析

# libraries
LIBS = -lc -lm -lnosys 
  • -lc:链接标准 C 库(libc)
  • -lm:链接数学库(libm),例如支持 sin, cos, sqrt
  • -lnosys:链接 libnosys.a,这是一个提供最小系统调用桩函数的库(避免链接错误)
LIBDIR = 
  • 没设置额外的库搜索目录
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) \-Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref \-Wl,--gc-sections

这是构造链接参数的完整语句,分解如下:

参数说明
$(MCU)MCU 相关的 GCC 参数(如 -mcpu=cortex-m4 -mthumb
-specs=nano.specs使用轻量级 nano newlib(newlib-nano),适合嵌入式系统
-T$(LDSCRIPT)指定链接脚本路径,例如 stm32f4xx.ld
$(LIBDIR)库目录参数(未定义时留空)
$(LIBS)链接所需的库,如 -lc, -lm, -lnosys
-Wl,-Map=...ld 生成 .map 文件,帮助查看内存布局和符号
--cref.map 文件中启用交叉引用
--gc-sections丢弃未使用的段,减小最终二进制体积

🔧 举例:使用这些参数生成固件

假设你运行 arm-none-eabi-gcc 手动链接:

arm-none-eabi-gcc main.o startup_stm32f4xx.o \-mcpu=cortex-m4 -mthumb \-specs=nano.specs \-Tstm32f4xx.ld \-lc -lm -lnosys \-Wl,-Map=output.map,--cref \-Wl,--gc-sections \-o firmware.elf

✅ 关于 -lnosys 的补充

  • libnosys.anewlib 提供的最小系统调用实现库。
  • 它中断了 exit(), _kill(), _getpid() 等函数的调用链。
  • 通常你会通过 syscalls.c 或自己实现 _write(), _sbrk() 来覆盖它。

✅ 关于 -specs=nano.specs

  • 它会让 gcc 使用 libc_nano.alibg_nano.a
  • 这是为嵌入式优化的版本,更小但功能有限,适用于 STM32、ARM Cortex-M 等资源受限环境。

🧠 提示

如果你想使用 printf() 的浮点功能(在 nano.specs 下默认关闭),你需要额外加:

-Wl,-u,_printf_float

或在 LDFLAGS 中加:

LDFLAGS += -Wl,-u,_printf_float

✅ 总结

用途
-lnosys提供默认的空系统调用,避免链接错误(可被用户定义的 _write 等函数替代)
-specs=nano.specs使用轻量 newlib 版本,适合嵌入式
-T$(LDSCRIPT)指定 .ld 链接脚本路径
-Wl,--gc-sections去掉未用段,减小大小
-Map=...生成 map 文件,调试内存和符号使用情况

USE_NEWLIB_REENTRANT(或在 FreeRTOSConfig.h 中叫 configUSE_NEWLIB_REENTRANT)是一个和 FreeRTOS + newlib 标准 C 库 集成相关的重要配置项,确实需要谨慎使用。


🧠 什么是 USE_NEWLIB_REENTRANT

简单说:

它表示是否为每个 FreeRTOS 任务分配一个 独立的 newlib 重入结构体 struct _reent,以支持 线程安全的标准 C 函数(如 printf, malloc 等)


🔧 背景:newlib 是单线程库

标准的 newlib(ARM GCC 默认使用的 C 标准库)不是线程安全的。比如:

  • 全局变量 errno
  • 全局堆指针
  • malloc() / free()

如果多任务同时调用这些函数,可能发生内存损坏或数据错乱


✅ 设置 configUSE_NEWLIB_REENTRANT = 1 的作用

启用后:

  • FreeRTOS 会为每个任务分配一个独立的 struct _reent
  • 标准库中的函数会使用当前任务的 reent 结构
  • 保证 malloc()errnoprintf() 等的线程安全性

⚠️ 警告与注意事项

❗ 1. 你必须使用 newlib-nanonewlib

启用 configUSE_NEWLIB_REENTRANT = 1 的前提是你项目确实在使用 newlib,否则会报错:

cannot open source file "reent.h"

如果你没有用 -specs=nano.specs-lc 之类的 newlib 库,启用这个配置毫无意义还会出错。


❗ 2. 你必须提供必要的系统调用(_sbrk, _write, 等)

CubeMX 会生成 syscalls.c/sysmem.c,你必须保留它们。

否则 malloc()printf() 就无法工作。


❗ 3. 你可能还需要实现 __malloc_lock()__malloc_unlock()

如果你使用的是 full newlib(不是 nano 版),malloc 默认是非线程安全的,除非你实现:

void __malloc_lock(struct _reent *r) {taskENTER_CRITICAL(); // 或者使用 mutex
}void __malloc_unlock(struct _reent *r) {taskEXIT_CRITICAL();
}

🔍 启用方式

FreeRTOSConfig.h 中加上:

#define configUSE_NEWLIB_REENTRANT 1

然后确保:

  • 编译器链接了 newlib/newlib-nano(一般 -lc -lrdimon -lnosys
  • syscalls.csysmem.c
  • 编译器路径中包含了 reent.h(通常自动包含)

❌ 不建议随意启用的原因

官方警告你很清楚:

⚠️ “FreeRTOS does not use newlib itself. If you enable reentrancy, you are responsible for making it work safely.”

启用后:

  • 系统内存占用增加(每个任务增加 struct _reent
  • 锁管理交给你自己实现
  • 如果你不理解 mallocerrno 的底层行为,很容易出错

✅ 总结

配置项作用
configUSE_NEWLIB_REENTRANT = 1每个任务都有独立 reent 结构,支持线程安全 newlib
启用前需满足说明
使用 newlib 库链接 -lc(默认是)或 -specs=nano.specs
包含 reent.h 头文件通常自动包含于 newlib
提供系统调用(如 _sbrk()用于 malloc
了解线程安全需求特别是 __malloc_lock()

当你在 STM32CubeMX 中启用了 FreeRTOS,它可能会在“Project Report”或生成代码时提示你:

提示:configUSE_NEWLIB_REENTRANT is enabled. You must ensure newlib is thread-safe and syscalls are implemented properly.


这是一个 重要但非致命 的提示,意思是你需要为启用 configUSE_NEWLIB_REENTRANT = 1额外准备工作。下面是详细解释和应对方法:


🔍 提示含义详解

当你在 CubeMX 中启用

Use Newlib reentrant

它就会在生成的 FreeRTOSConfig.h 中添加:

#define configUSE_NEWLIB_REENTRANT 1

并提示你:你必须确保系统环境满足 Newlib 多线程安全运行的条件,否则可能引发运行时错误。


✅ 要做的准备(否则会踩坑)

条件说明
✅ 使用 newlib 标准版 而非 nanonano 是精简版,不完整支持线程安全结构
✅ 正确实现了 syscalls,如 _sbrk(), _write()否则 malloc()printf() 等会失效
✅ 每个任务堆栈空间足够(通常 ≥ 256 字节)否则 newlib 的 _reent 结构体无法分配
heap_3.c 要求线程锁保护 malloc()推荐改用 heap_useNewlib.cheap_4.c

🛠 关键实现步骤

① 项目设置中使用 full newlib

在 STM32CubeIDE 中:

  • Project > Properties > C/C++ Build > Settings
  • 进入 Tool Settings > MCU GCC Linker > Libraries
  • ❌ 取消勾选 Use newlib-nano (--specs=nano.specs)
  • ✔️ 保留或添加 --specs=nosys.specs

② 实现系统调用 syscalls.c(如果还没有)

你需要提供如下函数,至少要包括:

void *_sbrk(ptrdiff_t incr);     // 用于 malloc 内存扩展
int _write(int file, char *ptr, int len);  // 用于 printf 输出

✅ 示例 _sbrk() 实现:

extern char _end; // Defined in linker script
static char *heap_end;void *_sbrk(ptrdiff_t incr) {char *prev_heap_end;if (heap_end == 0)heap_end = &_end;prev_heap_end = heap_end;heap_end += incr;return (void *) prev_heap_end;
}

③ 使用线程安全的 malloc() 方案(可选)

如果你使用 heap_3.c(基于标准 malloc),你需要启用锁支持,否则多个任务调用会冲突。

✅ 更好的方式:

  • 使用 heap_useNewlib.c(基于 Dave Nadler 的线程安全 malloc)
  • 或使用 heap_4.c + pvPortMalloc() 替代系统 malloc

✅ 示例配置(FreeRTOSConfig.h)

#define configUSE_NEWLIB_REENTRANT 1
#define configTOTAL_HEAP_SIZE     (10 * 1024)

✅ 示例任务(带 printf)

void TaskPrint(void *pvParameters) {while (1) {printf("Hello from task %s\n", pcTaskGetName(NULL));vTaskDelay(pdMS_TO_TICKS(1000));}
}

✅ 如何验证配置正确

测试正常现象
printf() 在多个任务中输出没有乱码、不会崩溃
malloc() 在任务中使用分配正常、无崩溃
errno 在任务间隔离每个任务 errno 不冲突

📌 总结

这条提示的真正含义是:

启用了线程安全支持后,你必须确保 newlib 运行环境完整、堆/栈足够、syscalls 正确、malloc 线程安全,否则系统将不可预期。


当启用configUSE_NEWLIB_REENTRANT后,每个任务的栈空间需求会显著增加,因为需要为每个任务分配独立的C库上下文。

栈空间需求

基本推荐值

// 最小栈大小建议
#define configMINIMAL_STACK_SIZE    ((unsigned short)512)  // 2KB (512 * 4字节)// 实际任务栈大小建议
xTaskCreate(TaskFunction, "TaskName", 1024,        // 4KB栈空间NULL, Priority, &TaskHandle);

不同使用场景的栈大小

1. 简单任务(只有基本操作)

#define SIMPLE_TASK_STACK_SIZE    512   // 2KB

2. 使用printf/sprintf的任务

#define PRINTF_TASK_STACK_SIZE    1024  // 4KB

3. 使用malloc/free的任务

#define MALLOC_TASK_STACK_SIZE    1024  // 4KB

4. 使用文件系统操作的任务

#define FILE_TASK_STACK_SIZE      2048  // 8KB

栈空间增加的原因

启用configUSE_NEWLIB_REENTRANT后增加的开销包括:

  1. struct _reent结构体:约400-600字节
  2. I/O缓冲区:printf等函数的缓冲区
  3. malloc堆管理:每个任务的堆状态信息
  4. 错误处理:errno等错误状态

实际测试建议

// 栈使用情况检查
void vTaskStackCheck(void)
{UBaseType_t uxHighWaterMark;// 获取任务剩余栈空间uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);printf("Stack remaining: %d words\n", uxHighWaterMark);
}

优化建议

1. 根据实际需求调整

// 不同任务使用不同栈大小
xTaskCreate(SimpleTask, "Simple", 512, NULL, 1, NULL);    // 2KB
xTaskCreate(PrintfTask, "Printf", 1024, NULL, 1, NULL);   // 4KB
xTaskCreate(FileTask, "File", 2048, NULL, 1, NULL);       // 8KB

2. 使用栈监控

// 在FreeRTOSConfig.h中启用
#define configCHECK_FOR_STACK_OVERFLOW  2

3. 考虑关闭可重入支持

如果RAM紧张,可以考虑:

#define configUSE_NEWLIB_REENTRANT 0

然后使用互斥锁保护共享资源。

总结

  • 最小推荐:512 words (2KB)
  • 安全推荐:1024 words (4KB)
  • 重度使用:2048 words (8KB)

建议从4KB开始,然后根据实际的栈使用情况进行调整。记住要定期检查栈的高水位标记,确保没有栈溢出的风险。

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

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

相关文章

Java零基础笔记01(JKD及开发工具IDEA安装配置)

1.Java简介 Java是一种广泛使用的计算机编程语言&#xff0c;由美国的Sun Microsystems公司&#xff08;Stanford University Network&#xff09;在1995年推出。Java以其跨平台、面向对象、安全性高等特点&#xff0c;广泛应用于企业级应用开发、移动应用开发等领域。2009年&a…

Spark SQL架构及高级用法

Spark SQL 架构概述 架构核心组件 API层&#xff08;用户接口&#xff09; 输入方式&#xff1a;SQL查询&#xff1b;DataFrame/Dataset API。统一性&#xff1a; 所有接口最终转换为逻辑计划树&#xff08;Logical Plan&#xff09;&#xff0c;进入优化流程。 编译器层&…

【机器学习深度学习】什么是下游任务模型?

目录 前言 一、什么是下游任务模型&#xff1f; 二、为什么需要下游任务模型&#xff1f; 三、下游任务模型都在干嘛&#xff1f; 四、下游模型怎么训练出来的&#xff1f; 五、图解理解&#xff1a;上游 vs 下游 六、一个现实案例&#xff1a;BERT做情感分析 原始数据…

补充:问题:CORS ,前后端访问跨域问题

补充&#xff1a;问题&#xff1a;CORS &#xff0c;前后端访问跨域问题 我这边的解决方法是&#xff1a; myAxios.defaults.withCredentials true; // 配置为true&#xff0c;表示前端向后端发送请求的时候&#xff0c;需要携带上凭证cookie整体的&#xff1a; import axio…

洛谷 P13014 [GESP202506 五级] 最大公因数-普及-

题目描述 对于两个正整数 a,ba,ba,b&#xff0c;他们的最大公因数记为 gcd⁡(a,b)\gcd(a,b)gcd(a,b)。对于 k>3k > 3k>3 个正整数 c1,c2,…,ckc_1,c_2,\dots,c_kc1​,c2​,…,ck​&#xff0c;他们的最大公因数为&#xff1a; gcd⁡(c1,c2,…,ck)gcd⁡(gcd⁡(c1,c2,……

前端-CSS-day1

目录 1、初识CSS 2、CSS引入方式 3、标签选择器 4、类选择器 5、id选择器 6、通配符选择器 7、画盒子 8、字体大小 9、字体粗细 10、字体倾斜 11、行高 12、行高-垂直居中 13、字体族 14、font属性 15、文本缩进 16、文本对齐方式 17、图片对齐方式 18、文本…

解锁万能文件内容提取器:Apache Tika

01 引言 在日常工作中&#xff0c;你是否曾为这些场景头疼过&#xff1f; 堆积如山的PDF、Word、Excel文档&#xff0c;如何快速提取关键信息&#xff1f;用户上传的文件五花八门&#xff0c;如何自动识别类型并安全处理&#xff1f;构建搜索引擎时&#xff0c;如何让系统“读懂…

gemini-cli初体验

目录 准备配置环境变量运行使用基础使用配置MCP调用MCP 参考 准备 NodeJS 18版本 配置环境变量 设置GEMINI_API_KEY 变量&#xff0c;在https://aistudio.google.com/apikey创建key 设置代理&#xff08;可选&#xff0c;取决于您的网络&#xff09;,不配置可能会报错 api e…

Java --类变量和类方法--main语句

1. 类变量和类方法 介绍&#xff1a; 类变量也叫静态变量/静态属性&#xff0c;是该类的所有对象共享的变量&#xff0c;任何一个该类的对象去访问它时&#xff0c;取到的都是相同的值&#xff0c;同样任何一个该类的对象去修改它时&#xff0c;修改的也是同一个变量。 语法…

spring boot项目配置使用minion

一. Minio概述 Minio是一款开源的高性能对象存储服务,兼容Amazon S3 API,适用于私有云、混合云及边缘计算场景。它采用分布式架构设计,支持水平扩展,提供数据加密、版本控制、生命周期管理等企业级功能,适用于存储非结构化数据(如图片、视频、日志等)。 核心特性 S3兼…

<5>_Linux进程控制

目录 一&#xff0c;进程创建&#xff0c;fork/vfork 1&#xff0c;fork创建子进程&#xff0c;操作系统都做了什么 2&#xff0c;写时拷贝的做了什么 二&#xff0c;进程终止&#xff0c;echo $&#xff1f; 1&#xff0c;进程终止时&#xff0c;操作系统做了什么 2&…

阿里云服务器正确配置 Docker 国内镜像的方法

&#x1f4e6; 原理说明&#xff1a;什么是“Docker 镜像加速器”&#xff1f; Docker 默认会从官方仓库 registry-1.docker.io 拉取镜像。由于网络原因&#xff0c;在中国大陆访问这个地址较慢甚至失败。 镜像加速器的作用是&#xff1a; 在国内部署一个缓存服务器&#xf…

PH热榜 | 2025-07-05

1. todai 标语&#xff1a;你的第一份个性化快乐生活指数 介绍&#xff1a;Todai 是你个人的人工智能助手&#xff0c;帮助你获得心理清晰和情感平衡。你可以随时随地记录自己的情绪&#xff0c;发现情绪变化的规律&#xff0c;并获取基于科学的工具。 产品网站&#xff1a;…

c++ duiLib环境集成

duiLib的Github链接&#xff1a;https://github.com/duilib/duilib 使用vcpkg快速安装duilib以及配置。步骤如下&#xff1a; 1、用git下载vcpkg&#xff0c;下载报错&#xff0c;这个错误通常表明在Git克隆过程中&#xff0c;与GitHub服务器的SSL连接被意外重置。改用http下…

一项基于粒子图像测速PIV系统的泥石流模拟冲击实验

1实验背景 全国进入“七下八上”防汛关键期&#xff0c;泥石流作为山区常见地质灾害&#xff0c;突发性强&#xff0c;破坏力大&#xff0c;对人民群众生命财产安全造成威胁&#xff0c;传统观测手段难以实现对碎石运动轨迹与水流场耦合效应的精细观测。而粒子图像测速PIV技术…

ADAS功能介绍

ADAS功能介绍 ADAS&#xff08;Advanced Driving Assistance System&#xff09;高级驾驶辅助系统&#xff0c;可分为如下几大类功能。 IA&#xff08;Information Assist&#xff09;信息辅助类 IA类功能&#xff0c;均不包含驾驶行为的控制。这些功能又可以进一步细分为三…

【LUT技术专题】CLUT代码讲解

本文是对CLUT技术的代码讲解&#xff0c;原文解读请看CLUT文章讲解。 1、原文概要 CLUT利用矩阵在保持3DLUT映射能力的前提下显著降低了参数量。整体流程如下所示。 整体还是基于3D-LUT的框架&#xff0c;只不过添加了一个压缩自适应的变换矩阵。作者使用的损失函数在3DLUT的…

在LinuxMint 22.1(Ubuntu24.04)上安装使用同花顺远航版

刚刚在LinuxMint 22.1(Ubuntu24.04)安装完成同花顺远航版&#xff0c;体验特别好&#xff0c;忍不住要及时给深受Linux平台无好用行情软件之苦的朋友们进行分享了。在此之前我一直只能用同花顺Linux原生版的行情软件&#xff0c;但是该软件只有很基本的行情功能&#xff0c;而且…

解决vue3路由配合Transition时跳转导致页面不渲染的问题

问题复现 <router-view v-slot"{ Component, route }"><transition name"fade" mode"out-in"><keep-alive><component :is"Component" :key"route.path" /></keep-alive></transition>…

java: 无法访问org.springframework.boot.SpringApplication,类文件具有错误的版本 61.0, 应为 52.0

问题 java: 无法访问org.springframework.boot.SpringApplication 错误的类文件: /D:/.m2/repository/org/springframework/boot/spring-boot/3.3.13/spring-boot-3.3.13.jar!/org/springframework/boot/SpringApplication.class 类文件具有错误的版本 61.0, 应为 52.0 请删除…