【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建
为摒弃在接受keil邮件,研究了下gun编译,以STM32F407为例,简单记录
1. 软件包准备
- Git
选择对应版本直接安装即可https://git-scm.com/download/win - make
- gcc

1)将上述软件包放置于C盘根目录

2)添加环境变量

3)cmd命令行测试环境
分别输入
make -v
gcc -v


2. 编写makefile
# ------------------------------------------------
#
# @file Makefile (based on gcc)
# @author urien
# @version v1.0.0
#
# ChangeLog :
# 2023-10-20
# ------------------------------------------------######################################
# target
######################################
TARGET = update######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -Og#######################################
# paths
#######################################
# Build path
BUILD_DIR = build######################################
# source
######################################
# C sources
C_DIRS += ../Libraries/FreeRTOS
C_DIRS += ../Libraries/FreeRTOS/portable/GCC/ARM_CM4F
C_DIRS += ../Libraries/CMSIS/Device/ST/STM32F4xx/Source
C_DIRS += ../Libraries/STM32F4xx_StdPeriph_Driver/src
C_DIRS += ../User/app
C_DIRS += ../User/bsp
C_DIRS += ../User/mid
C_DIRS += ../User/misc
C_DIRS += ../User/gui/app
C_DIRS += ../User/gui/lib
C_DIRS += ../User/usb
C_DIRS += ../Libraries/FATFS/source
C_DIRS += ../Libraries/STM32_USB_HOST_Library/Core/src
C_DIRS += ../Libraries/STM32_USB_HOST_Library/Class/MSC/src
C_DIRS += ../Libraries/PDF
SRC_OBJS_DIRS += $(foreach DIR, $(C_DIRS), $(wildcard $(DIR)/*.c))
C_SOURCES = $(SRC_OBJS_DIRS) \
../Libraries/FreeRTOS/portable/MemMang/heap_4.c \
../Libraries/STM32_USB_OTG_Driver/src/usb_core.c \
../Libraries/STM32_USB_OTG_Driver/src/usb_hcd.c \
../Libraries/STM32_USB_OTG_Driver/src/usb_hcd_int.c \# Core/Src/main.c \
# Core/Src/fr# ASM sources
ASM_SOURCES = \
startup_stm32f407xx.s#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S#######################################
# CFLAGS
#######################################
# cpu
CPU = -mcpu=cortex-m4# fpu
FPU = -mfpu=fpv4-sp-d16# float-abi
FLOAT-ABI = -mfloat-abi=hard# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)# macros for gcc
# AS defines
AS_DEFS = # C defines
C_DEFS = \
-DSTM32F407xx \
-DSTM32F40_41xxx \
-DUSE_STDPERIPH_DRIVER \
-DUSE_USB_OTG_FS \
-DUSER_VECT_TAB_ADDRESS \
# -D__FPU_PRESENT \
# -D__FPU_USED \# AS includes
AS_INCLUDES = # C includesC_INCS += ../Libraries/CMSIS/Include
C_INCS += ../Libraries/CMSIS/Core/Include
C_INCS += ../Libraries/CMSIS/Device/ST/STM32F4xx/Include
C_INCS += ../Libraries/STM32F4xx_StdPeriph_Driver/inc
C_INCS += ../Libraries/FreeRTOS/include
C_INCS += ../Libraries/FreeRTOS/GCC/ARM_CM4F
C_INCS += ../Libraries/FreeRTOS/portable/GCC/ARM_CM4F
C_INCS += ../Libraries/PDF
C_INCS += ../User/app
C_INCS += ../User/bsp
C_INCS += ../User/mid
C_INCS += ../User/misc
C_INCS += ../User/gui/app
C_INCS += ../User/gui/lib
C_INCS += ../User/usb
C_INCS += ../Libraries/STM32_USB_OTG_Driver/inc
C_INCS += ../Libraries/STM32_USB_HOST_Library/Class/MSC/inc
C_INCS += ../Libraries/STM32_USB_HOST_Library/Core/inc
C_INCS += ../Libraries/FATFS/source
INCS_OBJS_DIR = $(foreach DIR2, $(C_INCS), $(wildcard $(DIR2)/*.h))
INCS_OBJS_PATH = $(sort $(dir $(INCS_OBJS_DIR)))
C_INCLUDES = $(addprefix -I,$(INCS_OBJS_PATH)) \# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sectionsCFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sectionsifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = STM32F407VGTx_FLASH.ld# libraries
LIBS = -lc -lm -lnosys
LIBDIR =
# LDFLAGS += -lc -lrdimon -u _printf_float
# LDFLAGS += -specs=nano.specs
LDFLAGS += $(MCU) -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)$(AS) -c $(CFLAGS) $< -o $@$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile$(CC) $(OBJECTS) $(LDFLAGS) -o $@$(SZ) $@$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)$(HEX) $< $@$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)$(BIN) $< $@ $(BUILD_DIR):mkdir $@ #######################################
# clean up
#######################################
clean:-rm -fR $(BUILD_DIR)#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)#######################################
# download .hex/.bin by jlink
#######################################
#Your JLink installation directory
PATH_WINPC = 'C:/Program Files (x86)/SEGGER/JLink/'
#PATH_LINUX = /opt/SEGGER/JLink_V640b/JLinkExe
JK_DPATH = $(PATH_WINPC)
#Jlink script store directory
JKS_DIR = .
#Chip type
CHIP_TYPE = STM32F407VG
flash:@$(JK_DPATH)JLink.exe -device $(CHIP_TYPE) -if SWD -speed 4000 -autoconnect 1 -CommanderScript $(JKS_DIR)/flash.jlink@echo "Download Completed!"debug:@$(JK_DPATH)JLinkGDBServer.exe -select USB -device $(CHIP_TYPE) -if SWD -speed auto -noir -LocalhostOnly# *** EOF ***
3. __CC_ARM转__GUNC__注意
启动文件及LD文件
通过CubeMx工具生成即可
目录路径表示问题
// __CC_ARM环境
#define DBG_PATH_DIR '\\' // 目录结构
// __GUNC__环境
#define DBG_PATH_DIR '/' // 目录结构
字节对齐及指定位置存储问题
// __CC_ARM环境
__align(32) unsigned char ucaMemPool[MEM_MAX_SIZE]; // 内存池(32字节对齐)
// __GUNC__环境
#pragma pack(32) // 内存池(32字节对齐)
unsigned char ucaMemPool[MEM_MAX_SIZE];
#pragma pack()// __CC_ARM环境
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__((at(0X10000000)));
// __GUNC__环境
static uint8_t ucHeap[configTOTAL_HEAP_SIZE] __attribute__ ((section(".ccmram")));
/**
其中.ccmram在LD中定义,如果没有则需要自定义
*/.ccmram :{. = ALIGN(4);_sccmram = .; /* create a global symbol at ccmram start */*(.ccmram)*(.ccmram*). = ALIGN(4);_eccmram = .; /* create a global symbol at ccmram end */} >CCMRAM AT> FLASH
FreeRTOS兼容问题

底层接口RVDS替换为GCC
const功能接口注册问题
// __CC_ARM环境
#define REGISTER_CMD(cmd, handler, desc) \const char _register_##cmd##_cmd[] = #cmd; \const char _register_##cmd##_desc[] = #desc; \CMD_USED cmd_t _register_##cmd SECTION("CMDS") = \{ \_register_##cmd##_cmd, \_register_##cmd##_desc, \(unsigned int)CMD_HASH, \(cmd_handler)&handler};
void cmd_get_time(void *param)
{CALENDAR_T struCal;if_rtc_get(&struCal);__printf("%d-%d-%d %d:%d:%d %d\r\n", struCal.year, struCal.month, struCal.day,struCal.hour, struCal.minute, struCal.second, struCal.week);
}
REGISTER_CMD(get_time, cmd_get_time, get_time);// __GUNC__环境需要实现功能注册必须建表。
// 屏蔽原先接口
#define REGISTER_CMD(...)
// 新建关联表
cmd_t cmd_table[] ={{"set_time", "set_time[ymdhmsw]", 0, cmd_set_time},{"get_time", "get_time", 0, cmd_get_time},{"get_sensor", "get_sensor", 0, cmd_get_sensor},{"set_tp", "set_tp[tp1 tp2]", 0, cmd_set_target},...{0, 0, 0, 0},
};
USB_OTG问题
移植是需要删除一下文件:
usbh_msc_fatfs.c
usb_conf_template.h
特殊函数替换
__CC_ARM环境
// THUMB指令不支持汇编内联
// 采用如下方法实现执行汇编指令WFI
__asm void WFI_SET(void)
{WFI;
}
// 关闭所有中断(但是不包括fault和NMI中断)
__asm void INTX_DISABLE(void)
{CPSID IBX LR
}
// 开启所有中断
__asm void INTX_ENABLE(void)
{CPSIE IBX LR
}
// 设置栈顶地址
// addr:栈顶地址
__asm void MSR_MSP(u32 addr)
{MSR MSP, r0 // set Main Stack valueBX r14
}
__GUNC__环境
/*** @brief 执行: WFI指令(执行完该指令进入低功耗状态, 等待中断唤醒)* @param 无* @retval 无*/
void sys_wfi_set(void)
{__ASM volatile("wfi");
}/*** @brief 关闭所有中断(但是不包括fault和NMI中断)* @param 无* @retval 无*/
void sys_intx_disable(void)
{__ASM volatile("cpsid i");
}/*** @brief 开启所有中断* @param 无* @retval 无*/
void sys_intx_enable(void)
{__ASM volatile("cpsie i");
}/*** @brief 设置栈顶地址* @note 左侧的红X, 属于MDK误报, 实际是没问题的* @param addr: 栈顶地址* @retval 无*/
void sys_msr_msp(uint32_t addr)
{__set_MSP(addr); /* 设置栈顶地址 */
}
IAP相关问题
bootloader工程flash最好也修改限制自身的大小限制
MEMORY
{RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128KCCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64KFLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
}
bootloader跳转问题

// __GUNC__环境编译后得到的hex及bin文件无法满足以下条件
if ((tmp & 0x2FFE0000) == 0x20000000) // 检查栈顶地址是否合法.
目前没有找到更好的办法,做注释处理。
u32 tmp = 0;
s8 iap_load_app(u32 appxaddr)
{// if ((tmp & 0x2FFE0000) == 0x20000000) // 检查栈顶地址是否合法.{jump2app = (iapfun) * (vu32 *)(appxaddr + 4); // 用户代码区第二个字为程序开始地址(复位地址)__set_MSP(appxaddr); /* 设置栈顶地址 */// MSR_MSP(*(vu32 *)appxaddr); // 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)jump2app(); // 跳转到APP.}return 1;
}
application需要修改三处
// 第一处 LD文件
MEMORY
{RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128KCCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64KFLASH (rx) : ORIGIN = 0x08010000, LENGTH = 960K
}// 第二处 makefile文件
// 增加USER_VECT_TAB_ADDRESS宏定义
C_DEFS = \
-DUSER_VECT_TAB_ADDRESS \// 第三处 system_stm32f4xx.c文件
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field. \This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. \This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field. \This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00010000U /*!< Vector Table base offset field. \This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
关于下载
下载可以借用sergger - jlink驱动,在makefile文件添加如下:
#######################################
# download .hex/.bin by jlink
#######################################
#Your JLink installation directory
PATH_WINPC = 'C:/Program Files (x86)/SEGGER/JLink/'
#PATH_LINUX = /opt/SEGGER/JLink_V640b/JLinkExe
JK_DPATH = $(PATH_WINPC)
#Jlink script store directory
JKS_DIR = .
#Chip type
CHIP_TYPE = STM32F407VG
flash:@$(JK_DPATH)JLink.exe -device $(CHIP_TYPE) -if SWD -speed 4000 -autoconnect 1 -CommanderScript $(JKS_DIR)/flash.jlink@echo "Download Completed!"debug:@$(JK_DPATH)JLinkGDBServer.exe -select USB -device $(CHIP_TYPE) -if SWD -speed auto -noir -LocalhostOnly
主要注意两个地方:
1)驱动的安装位置
2)JKS_DIR定义的位置,这个直接索引编译后的hex文件
浮点数打印及格式化问题
makefile文件中去除-specs=nano.specs
# LDFLAGS += -specs=nano.specs
注意:去除后编译大小将增加40K代码空间
关于VSCODE编写代码高亮、索引、宏定义关联问题
在.vscode文件夹下根据需要添加目录索引及相关宏定义即可

4. 关于二次开发
二次开发新建的文件,存放于user对应的目录下即可,无需修改makefile文件。
4. 编译、下载、清除
urien@urien MINGW64 /d/work/prj_sealer/05软件/biolink-m4/source/application/Project (branch_sealer_gcc)
$ make -j20
....-mfloat-abi=hard -TSTM32F407VGTx_FLASH.ld -lc -lm -lnosys -Wl,-Map=build/update.map,--cref -Wl,--gc-sections -o build/update.elf
arm-none-eabi-size build/update.elftext data bss dec hex filename243772 60912 113784 418468 662a4 build/update.elf
arm-none-eabi-objcopy -O ihex build/update.elf build/update.hex
arm-none-eabi-objcopy -O binary -S build/update.elf build/update.binurien@urien MINGW64 /d/work/prj_sealer/05软件/biolink-m4/source/application/Project (branch_sealer_gcc)
$
urien@urien MINGW64 /d/work/prj_sealer/05软件/biolink-m4/source/application/Project (branch_sealer_gcc)
$ make flash
...
Script processing completed.Download Completed!urien@urien MINGW64 /d/work/prj_sealer/05软件/biolink-m4/source/application/Project (branch_sealer_gcc)
$
urien@urien MINGW64 /d/work/prj_sealer/05软件/biolink-m4/source/application/Project (branch_sealer_gcc)
$ make clean
rm -fR build
相关文章:
【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建
为摒弃在接受keil邮件,研究了下gun编译,以STM32F407为例,简单记录 1. 软件包准备 Git 选择对应版本直接安装即可https://git-scm.com/download/winmakegcc 1)将上述软件包放置于C盘根目录 2)添加环境变量 3&am…...
Oracle 控制文件的作用与控制文件创建
1、控制文件存储的数据信息 1) 数据库名称和数据库唯一标识符 (DBID),通过 select name,dbid from v$database; 查 询 DBID 和数据库名称 2) 创建数据库的时间戳 3) 有关数据文件、联机重做日志文件、归档重做日志文件的信息 4) 表空间信息 5) 检查点信息 6) 日志序…...
bootloader介绍
什么是bootloader bootloader是处理器上电后执行的第一个程序boot:将硬件引导到正常工作的状态loader:加载操作系统内核到内存的指定位置现在bootloader的功能:增加开机显示、开机音乐、OTA升级、固件验证等功能常见的bootloader:…...
以太网——ARP协议工作原理
ARP目录 MAC地址一、ARP是什么?二、ARP工作原理工作机制总结三、ARP报文结构四、ARP缓存MAC地址 我们知道别人的 IP 地址后,就能够向这个 IP 地址所在的主机发送数据包。但是IP 地址只是标识网络层的地址,那么在网络层下方数据链路层是不是也有一个地址能够告诉对方主机自己…...
一文了解AIGC与ChatGPT
一、AIGC简介 1.AIGC基础 (1)AIGC是什么 AIGC是人工智能图形计算的缩写,是一种基于图形处理器(GPU)的计算技术,可以加速各种计算任务,包括机器学习、深度学习、计算机视觉等。 AIGC是一种基于GPU的计算技术&#x…...
Java利用反射和读取xml实现迷你容器
由于需要框架能实现多态,达到控制反转解耦。所以容器还是需要的,容器的存在可以简化对象获取工作,但是容器也不是万能的。合理使用即可,Spring对我来说太庞大了,用不着,为此给框架写一个迷你版容器。 容器…...
Android12之DRM基本接口实现(二)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
普通二维码跳转微信小程序实战
简介 服务端springboot项目,前端基于uniapp的微信小程序,要求扫描二维码之后进入到小程序指定页面,下面记录一下实现过程以及过程中遇到的问题. 实现过程 下面是成功跳转的配置截图: 首先说下二维码规则,这个地方需要填写扫描二维码之后打开的地址,这个地址在我的项目里…...
spring boot 配置加载顺序
由官网的文档得知 https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config Default properties (specified by setting SpringApplication.setDefaultProperties).PropertySource annotations on your Configuration classe…...
基于stm32控制的4G模块在设备模式下通讯
这里的32控制其实和51的控制思路都是一样的,都是先利用一个网络助手将家里的无线网生成局域网,接着通过花生壳软件将局域网变成公共网,最后是利用串口助手,在4G模块的AT指令模式写入命令ATSOCKTCPC,公共网IP地址,公共网端口号&…...
预测宝可梦武力值、分类宝可梦
regression case 股票预测 无人车看到的各种sensor 影像镜头看到马路上的东西作为输入,输出就是方向盘角度等等的操纵策略 scalar 标量 这个是热力图,相当于你的XYZ但是Z用颜色表示了 closed-form solution 闭合解 learning rate事先定好的数值 在lin…...
Linux使用find命令查找文件
find命令 简介语法格式基本参数 参考实例根目录下文件名称的例子指定路径下特定类型的例子指定路径、文件类型特定文件名称的例子指定路径、文件类型特定文件大小的例子指定路径、文件类型 查找近期修改时间的例子指定路径、文件类型 查找空文件或目录的例子指定路径、文件类型…...
安卓使用android studio跨进程通信之AIDL
我写这篇文章不想从最基础的介绍开始,我直接上步骤吧. 1.创建服务端 1.1:创建服务端项目:我的as版本比较高,页面就是这样的 1.2:创建AIDL文件,右键项目,选中aidl aidl名字可以自定义也可以默认 basicTypes是自带的,可以删掉,也可以不删,然后把你自己所需的接口写上去 1.3:创建…...
RabbitMQ基础篇 笔记
RabbitMQ 余额支付 同步调用 一步一步的来,支付业务写完后,如果之后加需求,还需要增加代码,不符合开闭原则。 性能上也有问题,openfeign是同步调用,性能太差。 同步调用耦合太多。 同步的优势是可以立…...
实践小记—静态成员的使用注意(或许由此产生的不知名Bug)
序言 在实际生产过程中,为了便于调用,static修饰的成员会比较容易出现。 如果后期该变量并不会被修改,可以考虑使用。但如果后期需要被修改,使用该变量修饰符则需要慎重考虑。 尤其是在对硬件控制的实际生产中,更需…...
华为OD 身高体重排序(100分)【java】A卷+B卷
华为OD统一考试A卷B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目,A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载,请点击以下链接进入ÿ…...
在Word中,图片显示不全
在今天交作业的时候,发现了一个非常SB的事情,把图片复制过去显示不完全: 使用文心一言查看搜索了一下,发现可能是以下几种原因: 图片所在行的行高设置不正确。可以重新设置行高,具体步骤包括打开图片显示…...
C++数据结构X篇_20_选择排序
文章目录 1. 选择排序原理2. 选择排序原理核心代码3. 选择排序时间消耗 1. 选择排序原理 选择排序:相对于冒泡排序,减少了交换次数,下图展示了选择排序的原理,具体仍需要结合代码分析。 2. 选择排序原理核心代码 //选择排序 v…...
华为OD技术面试-最短距离矩阵(动态规划、广度优先)
背景 记录2023-10-21 晚华为OD三面的手撕代码题,当时没做出来,给面试官说了我的想法,评价:解法复杂了,只是简单的动态规范 或 广度优先算法,事后找资料记录实现方式。 题目 腐烂的橘子 问题描述ÿ…...
【代码规范】switch 块级的作用域问题
代码规范的一些事儿 问题 今日 Git 提交代码时,出现报错: error Unexpected lexical declaration in case block no-case-declarations 解决过程 我马上就去百度,就找到了这篇文章:解决 Unexpected lexical declaration in ca…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
