stm32f767中文手册_ALIENTEK 阿波罗 STM32F767 开发板资料连载第五章 SYSTEM 文件夹

1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子

69eeaf9d156684cffd0eccb3d02bf745.png

第五章 SYSTEM 文件夹介绍

第三章,我们介绍了如何在 MDK5 下建立 STM32F7 工程。在这个新建的工程之中,我们

用到了一个 SYSTEM 文件夹里面的代码,此文件夹里面的代码由 ALIENTEK 提供,是

STM32F7xx 系列的底层核心驱动函数,可以用在 STM32F7xx 系列的各个型号上面,方便大家

快速构建自己的工程。

SYSTEM 文件夹下包含了 delay、sys、usart 等三个文件夹。分别包含了 delay.c、sys.c、usart.c

及其头文件。通过这 3 个 c 文件,可以快速的给任何一款 STM32F7 构建最基本的框架。使用

起来是很方便的。

本章,我们将向大家介绍这些代码,通过这章的学习,大家将了解到这些代码的由来,也

希望大家可以灵活使用 SYSTEM 文件夹提供的函数,来快速构建工程,并实际应用到自己的项

目中去。

本章包括如下 3 个小结:

5.1,delay 文件夹代码介绍;

5.2,sys 文件夹代码介绍;

5.3,usart 文件夹代码介绍;

5.1 delay 文件夹代码介绍

delay 文件夹内包含了 delay.c 和 delay.h 两个文件,这两个文件用来实现系统的延时功能,

其中包含 7 个函数:

void delay_osschedlock(void);

void delay_osschedunlock(void);

void delay_ostimedly(u32 ticks);

void SysTick_Handler(void);

void delay_init(u8 SYSCLK);

void delay_ms(u16 nms);

void delay_us(u32 nus);

前面 4 个函数,仅在支持操作系统(OS)的时候,需要用到,而后面 3 个函数,则不论是

否支持 OS 都需要用到。

在介绍这些函数之前,我们先了解一下编程思想:CM4 内核的处理和 CM3 一样,内部都

包含了一个 SysTick 定时器,SysTick 是一个 24 位的倒计数定时器,当计到 0 时,将从 RELOAD

寄存器中自动重装载定时初值。只要不把它在 SysTick 控制及状态寄存器中的使能位清除,就

永不停息。SysTick 在《STM32F7 中文参考手册》里面基本没有介绍,其详细介绍,请参阅

《STM32F7 编程手册》第 211 页,4.4 节。我们就是利用 STM32 的内部 SysTick 来实现延时的,

这样既不占用中断,也不占用系统定时器。

这里我们将介绍的是 ALIENTEK 提供的最新版本的延时函数,该版本的延时函数支持在任

意操作系统(OS)下面使用,它可以和操作系统共用 SysTick 定时器。

这里,我们以 UCOSII 为例,介绍如何实现操作系统和我们的 delay 函数共用 SysTick 定时

器。首先,我们简单介绍下 UCOSII 的时钟:ucos 运行需要一个系统时钟节拍(类似 “心跳”),

而这个节拍是固定的(由 OS_TICKS_PER_SEC 宏定义设置),比如要求 5ms 一次(即可设置:

OS_TICKS_PER_SEC=200),在 STM32 上面,一般是由 SysTick 来提供这个节拍,也就是 SysTick

要设置为 5ms 中断一次,为 ucos 提供时钟节拍,而且这个时钟一般是不能被打断的(否则就不

准了)

因为在 ucos 下 systick 不能再被随意更改,如果我们还想利用 systick 来做 delay_us 或者

delay_ms 的延时,就必须想点办法了,这里我们利用的是时钟摘取法。以 delay_us 为例,比如

delay_us(50),在刚进入 delay_us 的时候先计算好这段延时需要等待的 systick 计数次数,这里

为 50*216(假设系统时钟为 216Mhz,因为我们设置 systick 的频率为系统时钟频率,那么 systick

每增加 1,就是 1/216us),然后我们就一直统计 systick 的计数变化,直到这个值变化了 50*216,

一旦检测到变化达到或者超过这个值,就说明延时 50us 时间到了。这样,我们只是抓取 SysTick

计数器的变化,并不需要修改 SysTick 的任何状态,完全不影响 SysTick 作为 UCOS 时钟节拍

的功能,这就是实现 delay 和操作系统共用 SysTick 定时器的原理。

下面我们开始介绍这几个函数。

5.1.1 操作系统支持宏定义及相关函数

当需要 delay_ms 和 delay_us 支持操作系统(OS)的时候,我们需要用到 3 个宏定义和 4

个函数,宏定义及函数代码如下:

//本例程仅作 UCOSII 和 UCOSIII 的支持,其他 OS,请自行参考着移植

//支持 UCOSII

#ifdef OS_CRITICAL_METHOD

//OS_CRITICAL_METHOD 定义了,说明要支持 UCOSII

#define delay_osrunning

OSRunning

//OS 是否运行标记,0,不运行;1,在运行

#define delay_ostickspersec OS_TICKS_PER_SEC //OS 时钟节拍,即每秒调度次数

#define delay_osintnesting OSIntNesting

//中断嵌套级别,即中断嵌套次数

#endif

//支持 UCOSIII

#ifdef CPU_CFG_CRITICAL_METHOD

//CPU_CFG_CRITICAL_METHOD 定义了,说明要支持 UCOSIII

#define delay_osrunning

OSRunning

//OS 是否运行标记,0,不运行;1,在运行

#define delay_ostickspersec OSCfg_TickRate_Hz

//OS 时钟节拍,即每秒调度次数

#define delay_osintnesting OSIntNestingCtr

//中断嵌套级别,即中断嵌套次数

#endif

//us 级延时时,关闭任务调度(防止打断 us 级延迟)

void delay_osschedlock(void)

{

#ifdef CPU_CFG_CRITICAL_METHOD //使用 UCOSIII

OS_ERR err;

OSSchedLock(&err);

//UCOSIII 的方式,禁止调度,防止打断 us 延时

#else

//否则 UCOSII

OSSchedLock();

//UCOSII 的方式,禁止调度,防止打断 us 延时

#endif

}

//us 级延时时,恢复任务调度

void delay_osschedunlock(void)

{

#ifdef CPU_CFG_CRITICAL_METHOD //使用 UCOSIII

OS_ERR err;

OSSchedUnlock(&err);

//UCOSIII 的方式,恢复调度

#else

//否则 UCOSII

OSSchedUnlock();

//UCOSII 的方式,恢复调度

#endif

}

//调用 OS 自带的延时函数延时

//ticks:延时的节拍数

void delay_ostimedly(u32 ticks)

{

#ifdef CPU_CFG_CRITICAL_METHOD //使用 UCOSIII 时

OS_ERR err;

OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);//UCOSIII 延时采用周期模式

#else

OSTimeDly(ticks);

//UCOSII 延时

#endif

}

//systick 中断服务函数,使用 ucos 时用到

void SysTick_Handler(void)

{

if(delay_osrunning==1)

//OS 开始跑了,才执行正常的调度处理

{

OSIntEnter();

//进入中断

OSTimeTick();

//调用 ucos 的时钟服务程序

OSIntExit();

//触发任务切换软中断

}

}

以上代码,仅支持 UCOSII 和 UCOSIII,不过,对于其他 OS 的支持,也只需要对以上代

码进行简单修改即可实现。

支持 OS 需要用到的三个宏定义(以 UCOSII 为例)即

#define delay_osrunning

OSRunning

//OS 是否运行标记,0,不运行;1,在运行

#define delay_ostickspersec OS_TICKS_PER_SEC //OS 时钟节拍,即每秒调度次数

#define delay_osintnesting OSIntNesting

//中断嵌套级别,即中断嵌套次数

宏定义:delay_osrunning,用于标记 OS 是否正在运行,当 OS 已经开始运行时,该宏定义

值为 1,当 OS 还未运行时,该宏定义值为 0。

宏定义:delay_ ostickspersec,用于表示 OS 的时钟节拍,即 OS 每秒钟任务调度次数。

宏定义:delay_ osintnesting,用于表示 OS 中断嵌套级别,即中断嵌套次数,每进入一个

中断,该值加 1,每退出一个中断,该值减 1。

支持 OS 需要用到的 4 个函数,即

函数:delay_osschedlock,用于 delay_us 延时,作用是禁止 OS 进行调度,以防打断 us 级

延时,导致延时时间不准。

函数:delay_osschedunlock,同样用于 delay_us 延时,作用是在延时结束后恢复 OS 的调度,

继续正常的 OS 任务调度。

函数:delay_ostimedly,则是调用 OS 自带的延时函数,实现延时。该函数的参数为时钟节

拍数。

函数:SysTick_Handler,则是 systick 的中断服务函数,该函数为 OS 提供时钟节拍,同时

可以引起任务调度。

以上就是 delay_ms 和 delay_us 支持操作系统时,需要实现的 3 个宏定义和 4 个函数。

5.1.2 delay_init 函数

该函数用来初始化 2 个重要参数:fac_us 以及 fac_ms;同时把 SysTick 的时钟源选择为外

部时钟,如果需要支持操作系统(OS),只需要在 sys.h 里面,设置 SYSTEM_SUPPORT_OS 宏

的值为 1 即可,然后,该函数会根据 delay_ostickspersec 宏的设置,来配置 SysTick 的中断时间,

并开启 SysTick 中断。具体代码如下:

//初始化延迟函数

//当使用 OS 的时候,此函数会初始化 OS 的时钟节拍

//SYSTICK 的时钟固定为 HCLK

void delay_init(u8 SYSCLK)

{

#if SYSTEM_SUPPORT_OS

//如果需要支持 OS.

u32 reload;

#endif

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

//SysTick 频率为 HCLK

fac_us=SYSCLK;

//不论是否使用 OS,fac_us 都需要使用

#if SYSTEM_SUPPORT_OS

//如果需要支持 OS.

reload=SYSCLK;

//每秒钟的计数次数 单位为 K

reload*=1000000/delay_ostickspersec; //根据 delay_ostickspersec 设定溢出时间

//reload 为 24 位寄存器,最大值:16777216,在 180M 下,约合 0.745s 左右

fac_ms=1000/delay_ostickspersec;

//代表 OS 可以延时的最少单位

SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启 SYSTICK 中断

SysTick->LOAD=reload;

//每 1/OS_TICKS_PER_SEC 秒中断一次

SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启 SYSTICK

#else

#endif

}

可以看到,delay_init 函数使用了条件编译,来选择不同的初始化过程,如果不使用 OS 的

时候,只是设置一下 SysTick 的时钟源以及确定 fac_us 值。而如果使用 OS 的时候,则会进行

一些不同的配置,这里的条件编译是根据SYSTEM_SUPPORT_OS这个宏来确定的,该宏在sys.h

里面定义。

SysTick 是 MDK 定义了的一个结构体(在 core_m4.h 里面),里面包含 CTRL、LOAD、VAL、

CALIB 等 4 个寄存器,

SysTick->CTRL 的各位定义如图 5.1.2.1 所示:

f0b6bb76e4d41fe5aecf653e033bc2aa.png

图 5.1.2.1 SysTick->CTRL 寄存器各位定义

SysTick-> LOAD 的定义如图 5.1.2.2 所示:

d0c75224f71a60e36a3cf01fc6676695.png

图 5.1.2.2 SysTick->LOAD 寄存器各位定义

SysTick-> VAL 的定义如图 5.1.2.3 所示:

f3c66afb326fafd23b5974c0a69eca6e.png

图 5.1.2.3 SysTick->VAL 寄存器各位定义

SysTick-> CALIB 不常用,在这里我们也用不到,故不介绍了。

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);这句代码把 SysTick 的时钟选择为

内核时钟,这里需要注意的是:SysTick 的时钟源自 HCLK,假设我们外部晶振为 25M,然后

倍频到 216MHZ,那么 SysTick 的时钟即为 216Mhz,也就是 SysTick 的计数器 VAL 每减 1,就

代表时间过了 1/216us。所以 fac_us=SYSCLK;这句话就是计算在 SYSCLK 时钟频率下延时 1us

需要多少个 SysTick 时钟周期。

在不使用 OS 的时候:fac_us,为 us 延时的基数,也就是延时 1us,Systick 定时器需要走

过的时钟周期数。 当使用 OS 的时候,fac_us,还是 us 延时的基数,不过这个值不会被写到

SysTick->LOAD 寄存器来实现延时,而是通过时钟摘取的办法实现的(前面已经介绍了)。而

fac_ms 则代表 ucos 自带的延时函数所能实现的最小延时时间(如 delay_ostickspersec=200,那

么 fac_ms 就是 5ms)。

5.1.3 delay_us 函数

该函数用来延时指定的 us,其参数 nus 为要延时的微秒数。该函数有使用 OS 和不使用 OS

两个版本,这里我们首先介绍不使用 OS 的时候,实现函数如下:

//延时 nus

//nus 为要延时的 us 数.

//nus:0~204522252(最大值即 2^32/fac_us@fac_us=21)

void delay_us(u32 nus)

{

u32 ticks;

u32 told,tnow,tcnt=0;

u32 reload=SysTick->LOAD;

//LOAD 的值

ticks=nus*fac_us;

//需要的节拍数

told=SysTick->VAL;

//刚进入时的计数器值

while(1)

{

tnow=SysTick->VAL;

if(tnow!=told)

{

if(tnow

else tcnt+=reload-tnow+told;

told=tnow;

if(tcnt>=ticks)break;

//时间超过/等于要延迟的时间,则退出.

}

};

}

这里就正是利用了我们前面提到的时钟摘取法,ticks 是延时 nus 需要等待的 SysTick 计数

次数(也就是延时时间),told 用于记录最近一次的 SysTick->VAL 值,然后 tnow 则是当前的

SysTick->VAL 值,通过他们的对比累加,实现 SysTick 计数次数的统计,统计值存放在 tcnt 里

面,然后通过对比 tcnt 和 ticks,来判断延时是否到达,从而达到不修改 SysTick 实现 nus 的延

时。对于使用 OS 的时候,delay_us 的实现函数和不使用 OS 的时候方法类似,都是使用的时钟

摘取法,只不过使用 delay_osschedlock 和 delay_osschedunlock 两个函数,用于调度上锁和解锁,

这是为了防止 OS 在 delay_us 的时候打断延时,可能导致的延时不准,所以我们利用这两个函

数来实现免打断,从而保证延时精度。

5.1.4 delay_ms 函数

该函数是用来延时指定的 ms 的,其参数 nms 为要延时的毫秒数。该函数有使用 OS 和不

使用 OS 两个版本,这里我们分别介绍,首先是不使用 OS 的时候,实现函数如下:

//延时 nms

//nms:要延时的 ms 数

void delay_ms(u16 nms)

{

u32 i;

for(i=0;i< nms;i++) delay_us(1000);

}

该函数其实就是多次调用前面所讲的 delay_us 函数,来实现毫秒级延时的。

再来看看使用 OS 的时候,delay_ms 的实现函数如下:

//延时 nms

//nms:要延时的 ms 数

//nms:0~65535

void delay_ms(u16 nms)

{

if(delay_osrunning&&delay_osintnesting==0)//如果 OS 已经在跑了,且不是在中断里面

{

if(nms>=fac_ms)

//延时的时间大于 OS 的最少时间周期

{

delay_ostimedly(nms/fac_ms);

//OS 延时

}

nms%=fac_ms;

//OS 已经无法提供这么小的延时了,采用普通方式延时

}

delay_us((u32)(nms*1000)); //普通方式延时

}

该函数中,delay_osrunning 是 OS 正在运行的标志,delay_osintnesting 则是 OS 中断嵌套次

数,必须 delay_osrunning 为真,且 delay_osintnesting 为 0 的时候,才可以调用 OS 自带的延时

函数进行延时(可以进行任务调度),delay_ostimedly 函数就是利用 OS 自带的延时函数,实现

任 务级 延时 的, 其参数 代表 延时 的时 钟节拍 数( 假设 delay_ostickspersec=200 ,那 么

delay_ostimedly (1),就代表延时 5ms)。

当 OS 还未运行的时候,我们的 delay_ms 就是直接由 delay_us 实现的,OS 下的 delay_us

可以实现很长的延时(达到 204 秒)而不溢出!,所以放心的使用 delay_us 来实现 delay_ms,

不过由于 delay_us 的时候,任务调度被上锁了,所以还是建议不要用 delay_us 来延时很长的时

间,否则影响整个系统的性能。

当 OS 运行的时候,我们的 delay_ms 函数将先判断延时时长是否大于等于 1 个 OS 时钟节

拍(fac_ms),当大于这个值的时候,我们就通过调用 OS 的延时函数来实现(此时任务可以调

度),不足 1 个时钟节拍的时候,直接调用 delay_us 函数实现(此时任务无法调度)。

5.1.5 HAL 库延时函数 HAL_Delay 解析

前面我们讲解了 ALIENTEK 提供的使用 Systick 实现延时相关函数。实际上,HAL 库有提

供延时函数,只不过它只能实现简单的毫秒级别延时,没有实现 us 级别延时。下面我们列出

HAL 库实现延时相关的函数。首先是功能配置函数:

//调用 HAL_SYSTICK_Config 函数配置每隔 1ms 中断一次:文件 stm32f7xx_hal.c 中定义

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)

{

/*配置 1ms 中断一次*/

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0);

return HAL_OK;

}

//HAL 库的 SYSTICK 配置函数:文件 stm32f7xx_hal_context.c 中定义

uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)

{

return SysTick_Config(TicksNumb);

}

//内核的 Systick 配置函数,配置每隔 ticks 个 systick 周期中断一次

//文件 core_cm4.h 中

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)

{

...//此处省略函数定义

}

上面三个函数,实际上开放给 HAL 调用的主要是 HAL_InitTick 函数,该函数在 HAL 库初

始化函数 HAL_Init 中会被调用。该函数通过间接调用 SysTick_Config 函数配置 Systick 定时器

每隔 1ms 中断一次,永不停歇。

接下来我们来看看延时的逻辑控制代码:

//Systick 中断服务函数:文件 stm32f7xx_it.c 中

void SysTick_Handler(void)

{

HAL_IncTick();

}

//下面代码均在文件 stm32f7xx_hal.c 中

static __IO uint32_t uwTick; //定义计数全局变量

__weak void HAL_IncTick(void) //全局变量 uwTick 递增

{

uwTick++;

}

__weak uint32_t HAL_GetTick(void) //获取全局变量 uwTick 的值

{

return uwTick;

}

//开放的 HAL 延时函数,延时 Delay 毫秒

__weak void HAL_Delay(__IO uint32_t Delay)

{

uint32_t tickstart = 0;

tickstart = HAL_GetTick();

while((HAL_GetTick() - tickstart) < Delay)

{

}

}

HAL 库实现延时功能非常简单,首先定义了一个 32 位全局变量 uwTick,在 Systick 中断

服务函数 SysTick_Handler 中通过调用 HAL_IncTick 实现 uwTick 值不断增加,也就是每隔 1ms

增加 1。而 HAL_Delay 函数在进入函数之后先记录当前 uwTick 的值,然后不断在循环中读取

uwTick 当前值,进行减运算,得出的就是延时的毫秒数,整个逻辑非常简单也非常清晰。

但是,HAL库的延时函数有一个局限性,在中断服务函数中使用 HAL_Delay会引起混乱,

因为它是通过中断方式实现,而 Systick 的中断优先级是最低的,所以在中断中运行 HAL_Delay

会导致延时出现严重误差。所以一般情况下,推荐大家使用 ALIENTEK 提供的延时函数库。

5.2 sys 文件夹代码介绍

sys 文件夹内包含了 sys.c 和 sys.h 两个文件。在 sys.h 里面除了函数申明外主要是定义了一

些常用数据类型短关键字。sys.c 里面除了定义时钟系统配置函数 Stm32_Clock_Init 外主要是一

些汇编函数以及 Cache 相关操作函数,对于函数 Stm32_Clock_Init 的讲解请参考本手册 4.3 小

节 STM32F7 时钟系统章节内容。接下来我们看看 STM32F7 的 Cache 使能函数。

5.2.1 Cache 使能函数

STM32F7 自带了指令 Cache(I Cache)和数据 Cache(D Cache),使用 I/D Cache 可以缓存

指令/数据,提高 CPU 访问指令/数据的速度,从而大大提高 MCU 的性能。不过,MCU 在复位

后,I/D Cache 默认都是关闭的,为了提高性能,我们需要开启 I/D Cache,在 sys.c 里面,我们

提供了如下函数:

//使能 STM32F7 的 L1-Cache,同时开启 D cache 的强制透写

void Cache_Enable(void)

{

SCB_EnableICache(); //使能 I-Cache,函数在 core_cm7.h 里面定义

SCB_EnableDCache(); //使能 D-Cache,函数在 core_cm7.h 里面定义

SCB->CACR|=1<<2; //强制 D-Cache 透写,如不开启,实际使用中可能遇到各种问题

}

该函数,通过调用 SCB_EnableICache 和 SCB_EnableDCache 这两个函数来使能 I Cache 和

D Cache。不过,在使能 D Cache 之后,SRAM 里面的数据有可能会被缓存在 Cache 里面,此

时如果有 DMA 之类的外设访问这个 SRAM 里面的数据,就有可能和 Cache 里面数据不同步,

导致数据出错,为了防止这种问题,保证数据的一致性,我们设置了 D Cache 的强制透写功能

(Write Through),这样 CPU 每次操作 Cache 里面的数据,同时也会更新到 SRAM 里面,保证

D Cache 和 SRAM 里面数据一致。关于 Cache 的详细介绍,请参考《STM32F7 Cache Oveview》

和《Level 1 cache on STM32F7 Series》(见光盘:8,STM32 参考资料 文件夹)。

这里 SCB_EnableICache 和 SCB_EnableDCache 这两个函数,是在 core_cm7.h 里面定义的,

我们直接调用即可,另外,core_cm7.h 里面还提供了以下五个常用函数:

1,SCB_DisableICache 函数,用于关闭 I Cache。

2,SCB_DisableDCache 函数,用于关闭 D Cache。

3,SCB_InvalidateDCache 函数,用于丢弃 D Cache 当前数据,重新从 SRAM 获取数据。

4,SCB_CleanDCache 函数,用于将 D Cache 数据回写到 SRAM 里面,同步数据。

5,SCB_CleanInvalidateDCache 函数,用于回写数据到 SRAM,并重新获取 D Cache 数据。

在 Cache_Enable 函数里面,我们直接开启了 D Cache 的透写模式,这样带来的好处就是可

以保证D Cache 和SRAM里面数据的一致性,坏处就是会损失一定的性能(每次都要回写数据),

如果大家想自己控制 D Cache 数据的回写,以获得最佳性能,则可以关闭 D Cache 透写模式,

并在适当的时候,调用 SCB_CleanDCache、SCB_InvalidateDCache 和 SCB_CleanInvalidateDCache

等函数,这对程序员的要求非常高,程序员必须清楚什么时候该回写,什么时候该更新 D Cache!

如果能力不够,还是建议开启 D Cache 的透写,以免引起各种莫名其妙的问题。

5.3 usart 文件夹介绍

该文件夹下面有 usart.c 和 usarts.h 两个文件。串口相关知识,我们将在第九章讲解串

口实验的时候给大家详细讲解。本节我们只给大家讲解比较独立的 printf 函数支持相关的

知识。

5.3.1 printf 函数支持

printf 函数支持的代码在 usart.c 文件的最上方,在我们初始化和使能串口 1 之后,然

后把这段代码加入到工程,便可以通过 printf 函数向串口 1 发送我们需要的内容,方便开

发过程中查看代码执行情况以及一些变量值。这段代码如果要修改一般也只是用来改变

printf 函数针对的串口号,大多情况我们都不需要修改。

代码内容如下:

//加入以下代码,支持 printf 函数,而不需要选择 use MicroLIB

#if 1

#pragma import(__use_no_semihosting)

//标准库需要的支持函数

struct __FILE

{

int handle;

};

FILE __stdout;

//定义_sys_exit()以避免使用半主机模式

_sys_exit(int x)

{

x = x;

}

//重定义 fputc 函数

int fputc(int ch, FILE *f)

{

while((USART1->SR&0X40)==0);//循环发送,直到发送完毕

USART1->DR = (u8) ch;

return ch;

}

#endif

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

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

相关文章

手机安卓学习 内核开发

官网开源代码 Documentation - MiCode/Xiaomi_Kernel_OpenSource - Sourcegraph Xiaomi 11T Pro GitHub - MiCode/Xiaomi_Kernel_OpenSource: Xiaomi Mobile Phone Kernel OpenSourceAndroid 开源项目 | Android Open Source Project google安卓官网 目录概览 参考…

vs 启动调用的目标发生异常_如何解决不可测、异常场景的问题?

阿里QA导读&#xff1a;在软件研发过程中&#xff0c;发布前跨多个系统的联调测试是不可或缺的一环&#xff0c;而在联调过程中&#xff0c;经常会遇到一些比较棘手的困难&#xff0c;阻塞整个联调进程。其中比较典型的有&#xff1a;第三方的研发节奏不一致&#xff0c;导致无…

Linux内核 scatterlist介绍

scatterlist 物理内存的散列表。通俗讲&#xff0c;就是把一些分散的物理内存&#xff0c;以列表的形式组织起来 诞生背景 假设有三个模块可以访问memory&#xff1a;CPU、DMA控制器和某个外设。CPU通过MMU以虚拟地址&#xff08;VA&#xff09;的形式访问memory&#xff1b;…

Linux内核 crypto文件夹 密码学知识学习

密码算法分类 对称算法非对称算法消息摘要&#xff08;单向哈希&#xff09;算法这些算法作为加密函数框架的最底层&#xff0c;提供加密和解密的实际操作。这些函数可以在内核crypto文件夹下&#xff0c;相应的文件中找到。不过内核模块不能直接调用这些函数&#xff0c;因为…

Linux crypto相关知识的汇总 Linux加密框架crypto中的算法和算法模式(一)

Linux加密框架中的算法和算法模式 Linux加密框架中的算法和算法模式&#xff08;一&#xff09;_家有一希的博客-CSDN博客 加密框架支持的密码算法主要是对称密码算法和哈希算法&#xff0c;暂时不支持非对称密码算法。除密码算法外&#xff0c;加密框架还包括伪随机数生成算法…

Linux crypto相关知识的汇总 Linux加密框架crypto对称算法和哈希算法加密模式

参考链接 Linux加密框架中的算法和算法模式&#xff08;二&#xff09;_家有一希的博客-CSDN博客 对称算法 分组算法模式 ECB模式 ECB模式下&#xff0c;明文数据被分为大小合适的分组&#xff0c;然后对每个分组独立进行加密或解密如下图所示如果两个明文块相同&#xff0c…

Linux加密框架中的算法和算法模式

参考链接 Linux加密框架中的算法和算法模式&#xff08;三&#xff09;_家有一希的博客-CSDN博客 对称算法 14 如上所示&#xff0c;在arc4.c中定义了两个与RC4算法相关的算法实现&#xff0c;分别为arc4和ecb(arc4)&#xff0c;其中arc4是RC算法的算法实现&#xff0c;而ecb…

Linux加密框架crypto AES代码相关

例子 aes_generic.c - crypto/aes_generic.c - Linux source code (v5.15.11) - Bootlin static struct crypto_alg aes_alg {.cra_name "aes",.cra_driver_name "aes-generic",.cra_priority 100,.cra_flags CRYPTO_ALG_TYPE_CIPHER,.cra_blocks…

Linux加密框架 crypto RC4

参考链接 arc4.h Linux加密框架中的主要数据结构&#xff08;一&#xff09;_家有一希的博客-CSDN博客 头文件 arc4.h - include/crypto/arc4.h - Linux source code (v5.15.11) - Bootlin实现代码 arc4.c arc4.c - crypto/arc4.c - Linux source code (v5.15.11) - Bootlin…

Linux加密框架 crypto 哈希算法说明 同步哈希shash_alg | 异步哈希 ahash_alg | 通用部分抽象 hash_alg_common

参考链接 Linux加密框架中的主要数据结构&#xff08;二&#xff09;_家有一希的博客-CSDN博客 定义 通用算法说明数据结构crypto_alg的联合体成员变量cra_u中包含多种算法的个性化属性&#xff0c;如分组算法、块加密算法、压缩算法、伪随机数算法等&#xff0c;但不包含哈希…

Linux加密框架 crypto 哈希算法举例 MD5

参考链接 Linux加密框架 crypto 哈希算法说明 同步哈希shash_alg | 异步哈希 ahash_alg | 通用部分抽象 hash_alg_common_CHYabc123456hh的博客-CSDN博客Linux加密框架中的主要数据结构&#xff08;二&#xff09;_家有一希的博客-CSDN博客 MD5 md5.h - include/crypto/md5.h …

事务没提交的数据查的出来吗?_“金三银四”面试官:说说事务的ACID,什么是脏读、幻读?...

一、事务事务是数据库管理系统执行过程中的一个逻辑单位&#xff0c;由一个有限的数据库操作序列构成。--摘自百科在MySQL里&#xff0c;事务是在引擎层面实现&#xff0c;比如MyIsam不支持&#xff0c;InnoDB支持面试清单&#xff08;Java岗&#xff09;&#xff1a;JavaJVM数…

Linux加密框架 crypto 算法模板

参考链接 Linux加密框架中的主要数据结构&#xff08;三&#xff09;_家有一希的博客-CSDN博客algapi.h - include/crypto/algapi.h - Linux source code (v5.15.11) - Bootlin 定义 struct crypto_template {struct list_head list;struct hlist_head instances;struct modu…

Linux加密框架 crypto 算法模板 CBC模板举例

参考链接 Linux加密框架中的主要数据结构&#xff08;三&#xff09;_家有一希的博客-CSDN博客https://blog.csdn.net/CHYabc123456hh/article/details/122194754 CBC算法模板 cbc.c - crypto/cbc.c - Linux source code (v5.15.11) - BootlinCBC算法模板属性 1)CBC算法模板名…

leetcode数组汇总_LeetCode刷题实战43:字符串相乘

算法的重要性&#xff0c;我就不多说了吧&#xff0c;想去大厂&#xff0c;就必须要经过基础知识和业务逻辑面试算法面试。所以&#xff0c;为了提高大家的算法能力&#xff0c;这个公众号后续每天带大家做一道算法题&#xff0c;题目就从LeetCode上面选 &#xff01;今天和大家…

Linux加密框架 crypto 算法模板 HMAC模板举例

参考链接 Linux加密框架中的主要数据结构&#xff08;三&#xff09;_家有一希的博客-CSDN博客Linux加密框架 crypto 算法模板_CHYabc123456hh的博客-CSDN博客 HMAC算法模板 hmac.c - crypto/hmac.c - Linux source code (v5.15.11) - Bootlinhmac.c - crypto/hmac.c - Linux…

判断非负整数是否是3的倍数_五年级数学因数与倍数知识点汇总与解题方法技巧...

在日常教学过程中&#xff0c;我发现孩子们和某些家长对学习数学的方法有一些误区&#xff0c;就是觉着数学&#xff0c;单纯就是逻辑思维&#xff0c;只要多做练习题就能学好&#xff0c;但是不是这样的&#xff0c;低年级的学生&#xff0c;学习数学还是以背诵为主&#xff0…

tcp通讯一次最多能发送多少数据?_关于TCP/IP,必须知道的十个知识点

本文整理了一些TCP/IP协议簇中需要必知必会的十大问题&#xff0c;既是面试高频问题&#xff0c;又是程序员必备基础素养。一、TCP/IP模型TCP/IP协议模型&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;&#xff0c;包含了一系列构成互联网基础的网络…

Linux内核crypto子系统的调用逻辑

testmgr.c - crypto/testmgr.c - Linux source code (v5.15.11) - Bootlin上述代码是内核内部即crypto子系统对外提供密码服务的测试程序调用流程&#xff1a;crypto API <—> crypto core <—> crypto_register_alg处于用户态的程序想要调用处于内核态的密码算法&…

Linux加密框架 crypto算法模板 以及CBC算法模板实例

参考链接 Linux加密框架中的主要数据结构&#xff08;四&#xff09;_家有一希的博客-CSDN博客algapi.h - include/crypto/algapi.h - Linux source code (v5.15.11) - Bootlin struct crypto_instance {struct crypto_alg alg;struct crypto_template *tmpl;union {/* Node i…