Freertos Cortex-M3上下文切换

2023-05-16

上下文切换是操作系统实现虚拟化的核心功能,操作系统对任务的管理通过上下文切换完成。
Freertos 在STM32F103上的上下文切换是本文介绍的内容。STM32F103 采用 Cortex-M3 内核 。

上下文切换的本质是对现场的保护和恢复现场,切换 CPU的运行环境。
上下文切换的触发来源于调度器,调度器根据复杂智能的调度算法来判断,是否要进行上下文切换。这换意味着一个任务被‘暂停’,任务中所做的事情都会被暂停。

1.调度器的优先级
Freertos 调度器本身的周期性运行是靠一个时间定时器systick的中断来触发的 ,假设每过1ms调度器就会随着systick的中断而运行。CUP不得不每过1ms就要去处理一下调度器的任务,增加了系统开销。这个时间间隔过短就会频繁中断CPU,过长就会让任务无法及时的切换。通常这个时间间隔选择1ms。

实时系统管关注的是实时性,Freertos做了一个非常聪明的机制。设定systick的中断优先级,那么比这个优先级高的中断就不会被打断,这样在系统中需要及时处理的问题就不会受到调度器的干扰。
这个优先级的定义
configMAX_SYSCALL_INTERRUPT_PRIORITY
默认的设定是 调度器不希望打断任何中断,所以把systick的中断优先级 设置为所有中断中最低的优先级。这样调度器不会打乱任何中断的运行。

那么这个中断优先级是如何设定的,打开Cortex-M3 权威指南
下图是异常列表
在这里插入图片描述
在这里插入图片描述

0~15是16 个 Cortex-M3 的中断线 对于外部中断,从第十六个开始。
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号: 15)。来产生操作系统需要的滴答中断,作为整个系统的时基。
11 为SVCall,14为PendSv 上下文切换就放在11和14中进行
所有我们要把他配置为最低的中断优先级就可以了。直接写0不就完事了吗?

挺有趣的, Cortex-M3 中0是可以配置的最大优先级,在 Cortex-M3 中优先级寄存器数字越小代表优先级最高。所以我们就是要确定优先级寄存器最大能填多少,这样就能找到最低优先级了。

这里已经很有趣又有点绕了,STM32F103在优先级设定上又做了一次设计,神操作让我们设定一下优先级 会变的的这么复杂。Cortex-M3 设计优先级的时候,一个中断节点优先级用8bit表示。STM32F103只用了其中4个,而且是最高位4个。所以中断优先级一共222*2=16级。但是IC设计人员没有用8位,用的高4位 所以,16 优先级来说来说就是
1111 0000 =240

Freertos的开发人员为了应对不同IC厂的操作,他们想了一个办法。
就是先拿一个中断寄存器出来,写个最大值进去,ARM Cortex-M3 给了8bit干脆就写个256(0xff)进去。然后读出来看看是多少,比如写 1111 1111(0xFF )进去读出来是 1111 0000,那显然这IC是用了高4位。
然后我们看Freertos的源码xPortStartSchedule一下截取一部分

xPortStartScheduler()
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );

/* Determine the maximum priority from which ISR safe FreeRTOS API
 * functions can be called.  ISR safe functions are those that end in
 * "FromISR".  FreeRTOS maintains separate thread and ISR API functions to
 * ensure interrupt entry is as fast and simple as possible.
 *
 * Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;

/* Determine the number of priority bits available.  First write to all
 * possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;

/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;

/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;

这里一堆代码就是干这个事情,最后怕搞出事情来,再把原来的值给写回去
谁是这个幸运儿呢?就是第16个中断节点,IRQ #0,显然他是一个外人。

ulOriginalPriority = *pucFirstUserPriorityRegister;
*pucFirstUserPriorityRegister = ulOriginalPriority;

在这里插入图片描述

优先级的事情说完了。

2.异常处理

异常差不多就可以认为是我们原来学过的中断,异常有时候说是来源于内核。我们 原来所学的中断基本上是说来源于外部。有的时候异常也叫做陷阱。种之就是停下当前做的事情去执行其他的事情。Cortex-M3权威指南把这些都统称为异常。这个其他事情的入口就是异常向量表了。我们发起一个异常请求,那么CPU就会做异常跳转。跳转也是 一种上下文切换,硬件会保存一些寄存器的值。

3.栈
能关注上下文切换的同学都已经知道什么是栈了。
在 CPU启动的时候,为了建立C语言的运行环境 ,已经设置了一个栈 MSP指向栈顶。异常的调转发生时,硬件会做上下文保存入MSP系统主栈,可以认为这个是裸机栈。保存的内容为
在这里插入图片描述
4.上下文切换

Cortex-M3 的双堆栈机制
任务创建的时候我们为每个任务设定了栈空间,这个空间用来保存任务在CPU中运行的上下文,也就是CPU中和任务执行相关的数据,如果这些数据丢了,那么任务也就没办法恢复运行了。
一般来说CPU再进行异常调转的时候,因为异常调转是硬件进行的,所以他会自动保存一些数据。这个是下上文的一部分。那么自动保存到哪里去了呢?默认情况下是主栈MSP。开机到运行Main,都在使用MSP。裸机的情况下所有的代码都是一个任务,这个MSP就是大任务的栈。有个时候,要把这个 栈切换 到任务自己的栈。

使用线程模式,CPU硬件入栈 对应的栈为PSP栈
使用内核模式,CPU硬件入栈,对应的是MSP栈
通过读取 PSP 的值, OS 就能够获取用户应用程序使用的堆栈,进一步地就知道了在发
生异常时,被压入寄存器的内容,而且还可以把其它寄存器进一步压栈(使用STMDB 和LDMIA
的书写形式)。 OS 还可以修改 PSP,用于实现多任务中的任务上下文切换。

上下文的切换的重点
1:搞清楚所使用的栈 MSP,PSP,各个任务的栈
2:上下文寄存器 哪些手动保存,哪些由硬件自动保存。
3:不同模式下,内核选择使用什么栈

笼统地讲,堆栈操作就是对内存的读写操作,但是其地址由 SP 给出。寄存器的数据通
过 PUSH 操作存入堆栈,以后用 POP 操作从堆栈中取回。在 PUSH 与 POP 的操作中, SP 的
值会按堆栈的使用法则自动调整,以保证后续的 PUSH 不会破坏先前 PUSH 进去的内容。

任务初始化的模拟入栈
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
	/* Simulate the stack frame as it would be created by a context switch
	interrupt. */
	pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
	pxTopOfStack--;
	*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK;	/* PC */
	pxTopOfStack--;
	*pxTopOfStack = ( StackType_t ) prvTaskExitError;	/* LR */

	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
	*pxTopOfStack = ( StackType_t ) pvParameters;	/* R0 */
	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */

	return pxTopOfStack;
}
__asm void vPortSVCHandler( void )
{
	PRESERVE8

	ldr	r3, =pxCurrentTCB	/* Restore the context. */
	ldr r1, [r3]			/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
	ldr r0, [r1]			/* The first item in pxCurrentTCB is the task top of stack. */
	ldmia r0!, {r4-r11}		/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
	msr psp, r0				/* Restore the task stack pointer. */
	isb
	mov r0, #0
	msr	basepri, r0
	orr r14, #0xd
	bx r14
}
/*-----------------------------------------------------------*/

__asm void prvStartFirstTask( void )
{
	PRESERVE8

	/* Use the NVIC offset register to locate the stack. */
	ldr r0, =0xE000ED08
	ldr r0, [r0]
	ldr r0, [r0]

	/* Set the msp back to the start of the stack. */
	msr msp, r0
	/* Globally enable interrupts. */
	cpsie i
	cpsie f
	dsb
	isb
	/* Call SVC to start the first task. */
	svc 0
	nop
	nop
}
/*-----------------------------------------------------------*/

static void prvPortStartFirstTask( void )
{
__asm volatile(
" ldr r0, =0xE000ED08 \n" /向量表偏移寄存器地址 CotexM3/
" ldr r0, [r0] \n" /取向量表地址/
" ldr r0, [r0] \n" /取 MSP 初始值/
/重置msp指针 宣示 系统接管/
" msr msp, r0 \n"
" cpsie i \n" /开中断/
" cpsie f \n" /开异常/
/流水线相关/
" dsb \n" /数据同步隔离/
" isb \n" /指令同步隔离/
/触发异常 启动第一个任务/
" svc 0 \n"
" nop \n"
);
}
第一个程序运行的时候主栈复位。然后跳转到SVC处理第一次上下文切换

void vPortSVCHandler( void )
{
__asm volatile (
/取 pxCurrentTCB 的地址/
“ldr r3, pxCurrentTCBConst2 \n”
/取出 pxCurrentTCB 的值 : TCB 地址/
“ldr r1, [r3] \n”
/*取出 TCB 第一项 : 任务的栈顶 */
“ldr r0, [r1] \n”
/恢复寄存器数据/
“ldmia r0!, {r4-r11} \n”
/设置线程指针: 任务的栈指针/
“msr psp, r0 \n”
/流水线清洗/
“isb \n”
“mov r0, #0 \n”
“msr basepri, r0 \n”
/设置返回后进入线程模式/
“orr r14, #0xd \n”
“bx r14 \n”
" \n"
“.align 4 \n”
“pxCurrentTCBConst2: .word pxCurrentTCB \n”
);
首先发生SVC后,ARM处理器会转为 主栈,自动保存R0 ~ PSR
进入SVC后恢复R4~R11
然后清洗流水线返回线程模式。这个时候线程栈中的R0~PSR(任务初始化是填入的值)就会恢复到CPU,从而完成切换。

正常情况下的上下文切换
PUSH 指令和 POP 指令默认使用 SP。
stmdb用于将寄存器压栈,ldmia用于将寄存器弹出栈
1.进入PSV后,CPU自动切换为主栈 也就是当前sp为异常向量表开头设置的主栈
2.mrs r0, psp 获取当前 任务栈的位置
3.保存当前任务控制块
4.把R4~R11 保存到当前 任务栈中,应为r4-r11不会自动入栈。
5.然后保存当前r0也就是当前任务的栈位置
6.执行一次 C函数,保存当前 r3 r14
7.执行选取目标任务
8.恢复r4~r11 这部分是需要手动保存
9.这个时候需要更新到新任务堆栈应为返回的时候,会把psp恢复到CPU
10.线程模式返回

void xPortPendSVHandler( void )
{
    /* This is a naked function. */
    __asm volatile
    (
    /*取出当前任务的栈顶指针 也就是 psp -> R0*/
    "   mrs r0, psp                         \n"
    "   isb                                 \n"
    "                                       \n"
    /*取出当前任务控制块指针 -> R2*/
    "   ldr r3, pxCurrentTCBConst           \n"
    "   ldr r2, [r3]                        \n"
    "                                       \n"
    /*R4-R11 这些系统不会自动入栈,需要手动推到当前任务的堆栈*/
    "   stmdb r0!, {r4-r11}                 \n"
    /*最后,保存当前的栈顶指针 
    R0 保存当前任务栈顶地址
    [R2] 是 TCB 首地址,也就是 pxTopOfStack
    下次,任务激活可以重新取出恢复栈顶,并取出其他数据
    */
    "   str r0, [r2]                        \n"
    "                                       \n"
    /*保护现场,调用函数更新下一个准备运行的新任务*/
    "   stmdb sp!, {r3, r14}                \n"
    /*设置优先级 第一个参数,
    即:configMAX_SYSCALL_INTERRUPT_PRIORITY
    进入临界区*/
    "   mov r0, %0                          \n"
    "   msr basepri, r0                     \n"
    "   bl vTaskSwitchContext               \n"
    "   mov r0, #0                          \n"
    "   msr basepri, r0                     \n"
    "   ldmia sp!, {r3, r14}                \n"
    "                                       \n"
    /*函数返回 退出临界区
    pxCurrentTCB 指向新任务
    取出新的 pxCurrentTCB 保存到 R1
    */
    "   ldr r1, [r3]                        \n"
    /*取出新任务的栈顶*/
    "   ldr r0, [r1]                        \n"
    /*恢复手动保存的寄存器*/
    "   ldmia r0!, {r4-r11}                 \n"
    /*设置线程指针 psp 指向新任务栈顶*/
    "   msr psp, r0                         \n"
    "   isb                                 \n"
    /*返回, 硬件执行现场恢复
    开始执行任务
    */
    "   bx r14                              \n"
    "                                       \n"
    "   .align 4                            \n"
    "pxCurrentTCBConst: .word pxCurrentTCB  \n"
    );
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Freertos Cortex-M3上下文切换 的相关文章

  • FreeRTOS-内核控制函数

    FreeRTOS 内核控制函数 FreeRTOS中有一些内核函数 一般来说这些内核函数在应用层不会使用 但是内核控制函数是理解FreeRTOS中断的基础 接下来我们逐一分析这些内核函数 taskYIELD 该函数的作用是进行任务切换 这是一
  • FreeRTOS软件定时器创建、复位、开始和停止(备忘)

    目录 一 简介 1 1 开发环境 1 2 摘要 二 STM32CubeIDE配置 三 创建定时器 3 1 头文件声明 3 2 工程文件定义 3 3 创建定时器 3 4 开启 复位 和关闭定时器 四 定时器回调函数 一 简介 1 1 开发环境
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能
  • FreeRTOS系列

    1 RTOS简介 RTOS全称为 Real Time Operation System 即实时操作系统 RTOS强调的是实时性 又分为硬实时和软实时 硬实时要求在规定的时间内必须完成操作 不允许超时 而软实时里对处理过程超时的要求则没有很严
  • STM32移植FreeRTOS的Tips

    转自 http bbs armfly com read php tid 7140 1 在FreeRTOS的demo文件夹中拷贝对应的FreeRTOSConfig h文件后 需要加入一行 define configUSE MUTEXES 1
  • FreeRTOS打印任务对CPU的占有率

    1 配置RTOS 1 打开RTOS Config Parameter 找到Run Time And Task States gathering related definitions 使能GENERATE RUN TIME STATS US
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS之软件定时器

    FreeRTOS之软件定时器 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 include sys h include delay h include usart h include led h in
  • FreeRTOS笔记(十)中断

    中断 当CPU在执行某一事件A时 发生另外一个更重要紧急的事件B请求CPU去处理 产生了中断 于是CPU暂时中断当前正在执行的事件A任务而对对事件B进行处理 CPU处理完事件B后再返回之前中断的位置继续执行原来的事件A 这一过程统称为中断
  • RT-Thread记录(五、RT-Thread 临界区保护与FreeRTOS的比较)

    本文聊聊临界区 以及RT Thread对临界区的处理 通过源码分析一下 RT Thread 对临界区保护的实现以及与 FreeRTOS 处理的不同 目录 前言 一 临界区 1 1 什么是临界区 1 2 RTOS中的临界区 二 RT Thre
  • FreeRTOS临界段

    1 临界段 在访问共享资源时不希望被其他任务或者中断打断的代码 这段要执行的代码称为临界段代码 2 设置临界段的目的 保护共享资源 例如 全局变量 公共函数 不可重入函数 函数里面使用 了一些静态全局变量 malloc 等 保护外设的实时性
  • 13-FreeRTOS任务创建与删除

    任务创建和删除API函数位于文件task c中 需要包含task h头文件 task h里面包函数任务的类型函数 例如 对xTaskCreate的调用 通过指针方式 返回一个TaskHandle t 变量 然后可将该变量用vTaskDele
  • FreeRTOS实时操作系统(三)任务挂起与恢复

    系列文章 FreeRTOS实时操作系统 一 RTOS的基本概念 FreeRTOS实时操作系统 二 任务创建与任务删除 HAL库 FreeRTOS实时操作系统 三 任务挂起与恢复 FreeRTOS实时操作系统 四 中断任务管理 FreeRTO
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • FreeRTOS多任务调度器基础

    Cortex M4中SysTick调度器核心 Cortex M4中的中断管理 Cortex M4中影子栈指针 Cortex M4中SVC和PendSV异常 1 Cortex M4中SysTick调度器核心 systick每一次中断都会触发内
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 有可用的 FreeRTOS 解释语言库吗?

    我在一家公司工作 该公司使用 FreeRTOS 为多个设备创建固件 最近 我们对新功能的要求已经超出了我们固件工程师的工作能力 但我们现在也无力雇用任何新人 即使进行微小的更改 也需要固件人员在非常低的级别上进行修改 我一直在为 FreeR
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 有关 CMake 错误的问题:没有为目标提供源

    我正在尝试使用 cmake 和 eclipse 将 FreeRtos 添加到我的项目中 但出现错误 我运行的是 debian 10 我的 cmake 版本是 3 13 4 cmake 的文件可以在以下位置找到这个 git 仓库 https

随机推荐

  • "指定的文件格式无法识别或为不支持的二进制"

    次奥 xff0c 你没有正确设置启动项目 转载于 https www cnblogs com tupx p 3701598 html
  • Linux安装MySQL8.0.16

    1 下载安装包 https www mysql com 2 安装MySQL 将下载好的安装包上传到服务器 然后解压 tar xvf mysql 8 0 16 el7 x86 64 tar gz 然后将解压目录重命名为mysql 8 0 16
  • 硬件中断和软件中断的区别

    中断 中断指当出现需要时 xff0c CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程 即在程序运行过程中 xff0c 系统出现了一个必须由CPU立即处理的情况 xff0c 此时 xff0c CPU暂时中止程序的执行转而处理这
  • 嵌入式C语言自我修养笔记1-ARM体系结构与编译运行

    目录 ARM 体系结构ARM 体系结构ARM 汇编指令ARM 寻址方式ARM 伪指令C 与汇编混合编程 程序编译链接与安装运行预处理过程编译过程链接过程程序安装apt get链接静态库动态链接共享库插件工作原理Linux 内核模块运行机制L
  • Renode应用:在RISC-V核上运行FreeRTOS

    本篇记录通过Renode在RISC V核上运行FreeRTOS demo的情况 本来不准备写这一篇 xff0c 但是发现近期工作学习密度实在太大 xff0c 上周工作的中间结果这周竟然完全想不起来了 xff0c 不得不又花了一些时间从头摸索
  • VideoStream流媒体(VOD视频点播)系统平台

    软件介绍 xff1a VideoStream是集流媒体视频服务和流媒体应用管理为一体的综合流媒体服务系统 xff0c 本产品通过宽带IP网络为教育系统 各类运营商 政府企业等用户提供音视频服务的应用 系统特点 xff1a 1 采用WEB端口
  • c语言实现模拟FTP服务器项目

    下载源码后 xff0c 直接可以在ubuntu中编译运行 xff1a FTP服务器程序功能 xff1a 客户端 xff1a 1 输入命令 xff1a help 查看FTP服务器所支持的所有命令 2 输入名 xff1a ls 查看服务器上可以
  • 基于ArUco的视觉定位

    参考如下 博客 基于ArUco的视觉定位 1 3 https www freesion com article 4265319144 基于ArUco的视觉定位 4 https www pianshen com article 2491452
  • 伺服电机和步进电机的区别

    硬件型号 xff1a 三菱伺服电机HG KR43J 系统版本 xff1a 电机系统 1 控制的方式不同 步进电机 xff1a 通过控制脉冲的个数控制转动角度的 xff0c 一个脉冲对应一个步距角 伺服电机 xff1a 通过控制脉冲时间的长短
  • ubutnu更换国内源后,更新一直出现404,Not Found的问题

    1 问题 题主系统是ubuntu16 04 64位系统 尝试更换国内各种源 连ubuntu官方源都尝试了 sudo vim etc apt sources list修改为 deb https mirrors tuna tsinghua ed
  • Python+Flask实现股价查询系统。Python绘制股票k线走势

    文章目录 一 实现效果图二 实现思路1 获取数据 2 可视化数据三 源码获取 一 实现效果图 打开默认显示半年线 xff0c 可以通过可视化类型选择可视化k线图 高低点等 xff08 目前只完成了初版 xff0c 当查询的股票数据返回为空时
  • Failed to fetch http://mirrors.tuna.tsinghua.edu.cn/ubuntu/pool/main/g/gcc-5/g++-5_5.4.0-6ubuntu1~16

    今天在ubutun中在安装redis过程中 xff0c 安装gcc时遇到了Failed to fetch http mirrors tuna tsinghua edu cn ubuntu pool main g gcc 5 g 43 43
  • 切换日语输入法找不到MicrosoftIME键盘选项了

    去微软官方下载一个 Microsoft IME office 2010后 xff0c 安装解决 转载于 https www cnblogs com tupx p 3816026 html
  • msgid 属性

    Android源码中的String xml文件 xff0c msgid这个属性是干嘛的 xff1f 全局资源 xff0c 方便引用 比如在布局的text和activity中用到 转载于 https www cnblogs com Ph on
  • 2017年09月23日普级组 数列

    Description 小S今天给你出了一道找规律题 xff0c 题目如下 xff1a 有如下的数列1 xff0c 11 xff0c 21 xff0c 1211 xff0c 111221 xff0c 312211 xff0c 小S问你这个数
  • python 机器学习实战:信用卡欺诈异常值检测

    今晚又实战了一个小案例 xff0c 把它总结出来 xff1a 有些人利用信用卡进行诈骗等活动 xff0c 如何根据用户的行为 xff0c 来判断该用户的信用卡账单涉嫌欺诈呢 xff1f 数据集见及链接 xff1a 在这个数据集中 xff0c
  • Virtual Serial Port Driver 虚拟串口工具软件 使用介绍

    一般来说 xff0c 电脑的外部设备可以用过各种端口和电脑连接 常见的有USB xff0c VGA xff0c DVI等等 在工业领域或者是软件开发领域 xff0c 我们常常需要用简单低成本快捷的方式 xff0c 完成电脑和设备的连接 那么
  • Freertos 源码分析 队列queue

    队列queue xff08 零 xff09 队列的基础概念和形态 xff08 一 xff09 Freertos 队列 queue c FreeRTOS Kernel 10 4 6 include queue h Freertos队列模块包含
  • Freertos 任务TASK(一) 任务创建

    任务的创建 Freertos 的任务创建难点 1 xff09 堆栈生长的方向 2 xff09 64字节的对齐 3 xff09 任务堆栈初始化 Freertos 的任务使用任务控制块来进行管理 xff0c 是对任务的抽象 任务本身就是一段可执
  • Freertos Cortex-M3上下文切换

    上下文切换是操作系统实现虚拟化的核心功能 xff0c 操作系统对任务的管理通过上下文切换完成 Freertos 在STM32F103上的上下文切换是本文介绍的内容 STM32F103 采用 Cortex M3 内核 上下文切换的本质是对现场