当前位置: 首页 > news >正文

广州网站建设在线谷歌官网入口

广州网站建设在线,谷歌官网入口,分析建设网站的可行性,网上做任务的网站是真的吗FreeRTOS工程创建 下载STM32CubeMX尽量找网盘下载(只是建议,没有说官网不行) 1.创建 STM32CubeMX 工程 (1)双击运行 STM32CubeMX,在首页面选择“Access to MCU Selector”,如下图所示&#xff1…

FreeRTOS工程创建


下载STM32CubeMX尽量找网盘下载(只是建议,没有说官网不行)

1.创建 STM32CubeMX 工程


(1)双击运行 STM32CubeMX,在首页面选择“Access to MCU Selector”,如下图所示:
(2)然后来到 MCU 选型界面,在序列号那里输入想要开发的芯片,作者使用的是STM32F103C8T6:

 2.配置时钟


(1)先配置处理器的时钟,在“System Core”的“RCC”处选择外部高速时钟源和低速时钟
源。DshanMCU-F103 使用了外部高速时钟源,如下图所示:

(2)另外,本实验使用了 FreeRTOS,FreeRTOS 的时基使用的是 Systick,而 STM32CubeMX 中默认的 HAL 库时基也是 Systick,为了避免可能的冲突,最好将 HAL 库的时基换做其它的硬
件定时器:
(3)最后去时钟配置界面配置系统时钟频率。直接在 HCLK 时钟那里输入 MCU 允许的最高时
钟频率。F103 的最高频率是 72Mhz,所以直接在那里输入 72 然后按回车:

3.配置 FreeRTOS


(1)STM32CubeMX 已经将 FreeRTOS 集成到工具中,并且将 RTOS 的接口进行了封装 CMSIS-RTOS V1/V2,相较之于 V1 版本的 CMSIS-RTOS API,V2 版本的 API 的兼容性更高,为了将来的开发和移植,建议开发者使用 V2 版本的 API:
(2)FreeRTOS 的参数包括时基频率、任务堆栈大小、是否使能互斥锁等等,需要开发者根
据自己对 FreeRTOS 的了解以及项目开发的需求,来定制参数
(3)使用 STM32CubeMX,可以手工添加任务、队列、信号量、互斥锁、定时器等等。但是本
课程不想严重依赖 STM32CubeMX,所以不会使用 STM32CubeMX 来添加这些对象,而是手写代
码来使用这些对象。
使用 STM32CubeMX 时,有一个默认任务,此任务无法删除,只能修改其名称和函数类型

4.生成 Keil MDK 的工程


(1)当对外设配置完成后,就去“Project Manager”中设置工程的名称、存储路径和开发
IDE

 (2)随后去同界面的“Code Generator”设置、生成工程:

5.问题 


由于不同的STM32CubeMX,软件的版本可能不同,我在配置之后,打开Keil发现按照以上方法配置会报错,这可能是你所使用STM32CubeMX 版本不匹配所导致的,只要打开如图

找见Firmware Package Name and Version,之后尝试修改版本即可

创建多任务程序


(1)系统默认线程理解


  • 在FreeRTOS微型操作系统中文件FreeRTOS.c存放着默认的线程代码
  • FreeRTOS与RT-Thread都属于微型实时操作系统,但是他们的代码不通用,所以有一个对实时操作系统的一个进行分装的文件cmsis_os2.c进行分装他们,类似也有,例如oled有不同型号,所以也要有文件对他们进行封装,lcd.c文件

在FreeRTOS.c中

这段代码就是创建了一个默认的Thread

osThreadNew方法属于cmsis_os2.c的一个基于FreeRTOS的方法

osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)

函数简介
osThreadNew 是一个用于创建新线程并将其添加到活动线程列表中的函数。
参数解析
func:线程函数的指针,这是线程启动后要执行的函数。

(就是这个线程启动要执行的代码的函数的名字)

/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */LCD_Init();LCD_Clear();for(;;){//Led_Test();LCD_Test();//MPU6050_Test(); //DS18B20_Test();//DHT11_Test();//ActiveBuzzer_Test();//PassiveBuzzer_Test();//ColorLED_Test();//IRReceiver_Test();//IRSender_Test();//LightSensor_Test();//IRObstacle_Test();//SR04_Test();//W25Q64_Test();//RotaryEncoder_Test();//Motor_Test();//Key_Test();//UART_Test();}/* USER CODE END StartDefaultTask */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

argument:传递给线程函数的参数,可以是任何类型的指针,这个指针将在线程启动时作为参数传入(一般看需求)

attr:线程属性的指针。如果设置为 NULL,则会使用默认值创建线程。这些属性可能包括线程的优先级、栈大小等设置。

defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

osThreadNew函数的返回值实际上是一个osThreadId_t类型的值

&defaultTask_attributes返回的是结构体值                                                                                                                                                                                                                                                

/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {.name = "defaultTask",.stack_size = 128 * 4,.priority = (osPriority_t) osPriorityNormal,
};

返回值
osThreadId_t:返回新创建线程的 ID,以便其他函数可以引用这个线程。
如果创建失败,返回值将是 NULL,表示发生了错误。
总结
这个函数的目的是方便开发者创建多线程应用,允许用户指定线程的功能和参数,同时支持自定义线程属性

(2)自己创建一个线程


找见如图所示位置

BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,const char * const pcName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */const configSTACK_DEPTH_TYPE usStackDepth,void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pxCreatedTask )

参数解释

  1. pxTaskCode

    • 类型TaskFunction_t
    • 描述:指向任务函数的指针,该函数包含任务的代码逻辑。
  2. pcName

    • 类型const char * const
    • 描述:任务的名称,用于调试和识别任务。可以是任意字符串,但最好简短且有意义。
  3. usStackDepth

    • 类型const configSTACK_DEPTH_TYPE
    • 描述:任务堆栈的深度,通常以堆栈大小(字)为单位。这个参数定义了任务可以使用的内存量。
  4. pvParameters

    • 类型void * const
    • 描述:传递给任务的参数,可以是任何类型的指针。任务内可以通过这个参数获取相关数据。
  5. uxPriority

    • 类型UBaseType_t
    • 描述:任务的优先级,数值越大,优先级越高。FreeRTOS 支持多个优先级。
  6. pxCreatedTask

    • 类型TaskHandle_t * const
    • 描述:用于接收创建的任务的句柄,便于后续管理(如删除、挂起等)。

返回值

  • 返回值类型BaseType_t
  • 描述:函数调用成功时返回 pdPASS,失败时返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 等错误码。

总结

这个函数的主要作用是创建一个新的任务,并为其分配堆栈空间和其他资源,以便在 FreeRTOS 环境中并发执行多个任务。

书写你的线程代码,找见位置

基于汇编对ARM架构的简单理解


1.汇编的简单学习

PUSH

在汇编语言中,PUSH指令用于将数据压入栈中。这是一个非常重要的操作,特别是在函数调用、保存寄存器值以及处理局部变量时。下面是关于PUSH指令的一些基本内容:

基本概念

  • :栈是一种后进先出(LIFO)的数据结构,通常用于临时存储数据。
  • PUSH指令:将指定的值压入栈顶,并自动调整栈指针

表示将r4到r7以及LR压入栈中,SP寄存器自动调整栈顶内容

MOV

  • 基本功能MOV 指令用于将数据从一个位置复制到另一个位置,可以是寄存器、内存或立即数。
  • 语法MOV destination, source
  • 操作数类型
    • 可以是寄存器与寄存器之间的复制。
    • 可以是寄存器与内存之间的复制。
    • 可以是立即数与寄存器或内存之间的复制。
  • 示例
  • MOV AX, 5       ; 将立即数5加载到AX寄存器
    MOV BX, AX      ; 将AX寄存器的值复制到BX寄存器
    

MOVS

  • 基本功能MOVS 指令用于在处理字符串时,将源地址指向的数据移动到目标地址。它通常用于复制字节、字或双字,常与 ESI 和 EDI 寄存器配合使用。
  • 语法MOVSBMOVSWMOVSD
  • 操作数类型
    • MOVSB:移动字节(8位)。
    • MOVSW:移动字(16位)。
    • MOVSD:移动双字(32位)。
  • 自动更新指针:执行后,ESI 和 EDI 指针会自动增加,以准备下一个数据项的复制。
  • MOVSB            ; 将ESI指向的字节复制到EDI指向的字节,并自动更新指针
    MOVSW            ; 将ESI指向的字复制到EDI指向的字
    MOVSD            ; 将ESI指向的双字复制到EDI指向的双字
    

MOV与MOVS区别

总结
  1. 用途不同
    • MOV 用于通用的数据传输。
    • MOVS 系列用于字符串或块数据的复制。
  2. 指针更新
    • MOV 不会自动更新任何指针。
    • MOVS 在操作后会自动更新 ESI 和 EDI 寄存器。
  3. 操作数类型
    • MOV 可以处理多种数据类型和操作数。
    • MOVS 专注于字节、字和双字的移动。

SUB

在汇编语言中,SUB 指令用于执行减法操作。它从一个操作数中减去另一个操作数,并将结果存储在第一个操作数中。以下是关于 SUB 指令的一些详细信息:

基本概念
  • 功能SUB 指令用于从第一个操作数中减去第二个操作数。
  • 语法SUB destination, source
    • destination:要进行减法运算的目标位置(通常是寄存器或内存)。
    • source:要减去的值(可以是寄存器、立即数或内存)。
    • SUB AX, BX      ; 将BX寄存器的值从AX寄存器中减去,结果存储在AX中
      

LDRD 

LDRD 是一种汇编指令,通常用于 ARM 体系结构中。它的功能是从内存中加载双字(通常是 64 位或 32 位)到寄存器中。以下是关于 LDRD 指令的一些详细信息:

基本概念
  • 功能LDRD 从内存中加载两个连续的数据项到两个寄存器中。
  • 语法LDRD destination1, destination2, [address]
    • destination1 和 destination2 是要加载数据的寄存器。
    • [address] 是内存地址,指向要加载的数据的起始位置。
LDRD R0, R1, [R2]  ; 从R2指向的内存地址加载数据,R0加载低地址的数据,R1加载高地址的数据

ADD

ADD 是一种基本的汇编指令,用于执行加法操作。它通常用于将两个操作数相加,并将结果存储在指定的目标寄存器中。以下是关于 ADD 指令的一些详细信息:

基本概念
  • 功能ADD 将两个操作数相加,并将结果存储在第一个操作数中。
  • 语法ADD destination, source1, source2
    • destination:用于存储结果的寄存器或内存位置。
    • source1 和 source2:要相加的两个操作数,可以是寄存器、立即数或内存。
ADD R0, R1, R2  ; 将R1和R2的值相加,结果存储在R0中

STR

STR 是一种汇编指令,主要用于将寄存器中的数据存储到内存中。以下是关于 STR 指令的一些详细信息:

基本概念
  • 功能STR 将一个寄存器的值存储到指定的内存地址。
  • 语法STR source, [address]
    • source:要存储的寄存器。
    • [address]:目标内存地址,可以是直接地址或通过基址加偏移量计算得出。
STR R2, [R3, #4]  ; 将寄存器R2中的值存储到R3指向的内存地址加上4的偏移量

POP

POP 是一种汇编指令,用于从栈中弹出数据并将其存储到指定的寄存器或内存位置。以下是关于 POP 指令的一些详细信息:

基本概念
  • 功能POP 从栈顶弹出一个值,并将其存储到指定的目标寄存器或内存地址中。
  • 语法POP destination
    • destination:要接收弹出值的寄存器或内存位置
POP {R1, R2, R3}  ; 同时从栈中弹出值到寄存器 R1, R2 和 R3

2.volatile


volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

底层栈区细节请看

3.ARM内部架构简单理解


 


 

 

执行的是以下代码

		cnt = add(cnt, 1);

执行的是以下代码

int add(volatile int a, volatile int b)
{volatile int sum;sum = a + b;return sum;
}

这个是地址码

这个是地址码对应的数据(在Flash中)

这个是为人类设计的汇编代码

 

add函数代码汇编解析 


int add(volatile int a, volatile int b)
{volatile int sum;sum = a + b;return sum;
}
(1)PUSH  {r0,r1,1r}

在栈区分配三个长度为4的内存空间分别为r0,r1,LR

sp这个地址在的栈区减12

(2)SUB sp,sp,#4

再分配一个空间用来存放sum

(3)LDRD r0,r1,[sp,#4]

读取(sp+4)地址以上的r0,r1的值

(4)ADD r0,r0,r1

r0=r0+r1;

(5)STR r0,[sp,#0]

将r0赋值给[sp+0]地址下的值sum

(6)POP {r1-r3,pc}

将LR寄存器指向的值给pc寄存器,返回r1,r2,r3

4.PC寄存器


程序计数器(PC,Program Counter)是CPU中的一个特殊寄存器,它的主要功能是存储下一条要执行的指令的地址。这样,CPU就能够知道接下来需要执行哪一条指令,从而保证程序的连续执行。在程序开始执行前,程序的首地址(即第一条指令所在的内存单元地址)会被送入PC。当执行指令时,CPU会自动修改PC的内容,使其始终指向将要执行的下一条指令的地址。大多数情况下,指令是顺序执行的,所以PC的值通常会自动递增,递增的量等于指令所含的字节数。当遇到转移指令时,下一条指令的地址将由转移指令的地址码字段来指定,而不是简单地通过递增PC的值来获取 。
在ARM架构中,程序计数器PC(R15)是唯一的,并且被所有模式共用。ARM处理器中使用R15作为PC,它总是指向取指单元。ARM处理器可以寻址4GB的地址空间,这是因为R15有32位宽度。在ARM状态下,R15的值总是能被4整除,也就是R15寄存器的最低2位总是0;而在Thumb状态下,R15的值总是能被2整除,也就是R15寄存器的最低位总是0 。
PC寄存器在计算机系统中扮演着重要的角色,它是CPU内部的重要组成部分,能够直接与CPU进行数据交换,提高数据的处理速度。同时,PC寄存器还可以协助CPU完成各种复杂的运算和控制操作,使得计算机系统能够高效、稳定地运行 。
在JVM(Java虚拟机)中,PC寄存器是对物理PC寄存器的一种抽象模拟。它用来存储指向下一条指令的地址,也即将要执行的指令代码。JVM中的PC寄存器是线程私有的,每个线程都有自己的程序计数器,它的生命周期与线程的生命周期保持一致。PC寄存器是程序控制流的指示灯,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成 。

5.LR寄存器


在ARM架构中,LR(Link Register)是一个特殊的寄存器,其主要作用是存储子程序调用的返回地址。当执行函数调用指令(如BL,Branch and Link)时,LR寄存器会被自动设置为当前指令的下一条指令地址,即返回地址。这样,在函数执行完毕后,可以通过将LR寄存器的值复制到程序计数器PC来实现函数的返回,通常使用的指令是 MOV PC, LR 或者 BX LR 。
LR寄存器在异常处理中也扮演着重要角色。当异常发生时,异常模式的LR用来保存异常返回地址,即将当前的PC值保存到LR中,以便在异常处理程序结束后,能够通过LR寄存器恢复执行流,回到异常发生前的状态。
ARM处理器针对不同的模式,共有6个链接寄存器资源,其中用户模式和系统模式共用一个LR,每种异常模式都有各自专用的R14寄存器(LR)。这些链接寄存器分别为R14、R14_svc、R14_abt、R14_und、R14_irq、R14_fiq。程序设计者需要清晰地了解处理器的模式与相应寄存器的对应关系,因为不同模式下的R14不是同一个物理资源,其内容可能截然不同。
在ARMv8架构中,LR寄存器的功能被X30寄存器所取代。在ARM64模式下,X30用作链接寄存器,存储子程序调用的返回地址。


文章转载自:
http://slapstick.rgxf.cn
http://parsoness.rgxf.cn
http://cabinetmaking.rgxf.cn
http://celandine.rgxf.cn
http://kamasutra.rgxf.cn
http://superpersonality.rgxf.cn
http://ultrasonic.rgxf.cn
http://digestive.rgxf.cn
http://jatha.rgxf.cn
http://search.rgxf.cn
http://carefulness.rgxf.cn
http://coly.rgxf.cn
http://macropsia.rgxf.cn
http://formality.rgxf.cn
http://patency.rgxf.cn
http://antiobscenity.rgxf.cn
http://litchi.rgxf.cn
http://epee.rgxf.cn
http://lapsable.rgxf.cn
http://ashpit.rgxf.cn
http://forge.rgxf.cn
http://nivation.rgxf.cn
http://mephistopheles.rgxf.cn
http://hermitage.rgxf.cn
http://rapeseed.rgxf.cn
http://interwork.rgxf.cn
http://stepstone.rgxf.cn
http://conjuror.rgxf.cn
http://trophozoite.rgxf.cn
http://rugger.rgxf.cn
http://remould.rgxf.cn
http://revanchard.rgxf.cn
http://enrichment.rgxf.cn
http://joyously.rgxf.cn
http://rasp.rgxf.cn
http://tediousness.rgxf.cn
http://acquaintance.rgxf.cn
http://gadabout.rgxf.cn
http://vendace.rgxf.cn
http://ferronickel.rgxf.cn
http://entorganism.rgxf.cn
http://depurate.rgxf.cn
http://reconciliatory.rgxf.cn
http://antibusing.rgxf.cn
http://endocrinopathy.rgxf.cn
http://peppertree.rgxf.cn
http://meekness.rgxf.cn
http://incalculable.rgxf.cn
http://flection.rgxf.cn
http://rau.rgxf.cn
http://flexor.rgxf.cn
http://merit.rgxf.cn
http://bosque.rgxf.cn
http://umpirage.rgxf.cn
http://isd.rgxf.cn
http://eunuchism.rgxf.cn
http://infantilize.rgxf.cn
http://cassini.rgxf.cn
http://urbanise.rgxf.cn
http://microteaching.rgxf.cn
http://undeviating.rgxf.cn
http://clownery.rgxf.cn
http://alabama.rgxf.cn
http://ogrish.rgxf.cn
http://clearstory.rgxf.cn
http://quercitol.rgxf.cn
http://iioilo.rgxf.cn
http://gyttja.rgxf.cn
http://litigate.rgxf.cn
http://meteyard.rgxf.cn
http://connoisseurship.rgxf.cn
http://denobilize.rgxf.cn
http://recheck.rgxf.cn
http://eloign.rgxf.cn
http://labdanum.rgxf.cn
http://cubanize.rgxf.cn
http://rhodinal.rgxf.cn
http://paracusis.rgxf.cn
http://scilla.rgxf.cn
http://aloft.rgxf.cn
http://pont.rgxf.cn
http://bacchantic.rgxf.cn
http://horseshoe.rgxf.cn
http://ferroalloy.rgxf.cn
http://philippeville.rgxf.cn
http://chromhidrosis.rgxf.cn
http://marconi.rgxf.cn
http://yieldingness.rgxf.cn
http://memoirist.rgxf.cn
http://villeinage.rgxf.cn
http://systematization.rgxf.cn
http://tester.rgxf.cn
http://wooded.rgxf.cn
http://thy.rgxf.cn
http://braider.rgxf.cn
http://minbar.rgxf.cn
http://cholinomimetic.rgxf.cn
http://retest.rgxf.cn
http://recrudescence.rgxf.cn
http://refocus.rgxf.cn
http://www.dt0577.cn/news/61258.html

相关文章:

  • 北京网站设计公司新鸿儒怎么推广公司网站
  • 南京网站设计公司大全旺道seo怎么优化网站
  • 全flash网站模板营销型外贸网站建设
  • 做静态网站怎样让图片自己切换推广app的软文案例
  • 红酒网站模板下载电商运营转行后悔了
  • 网站备案被恶意注销网红推广一般怎么收费
  • 南宫做网站制作一个网站的全过程
  • 济南建网站要免费外链发布
  • 南京高新区网站建设网店运营教学
  • 建设银行吴中支行网站今日国内新闻最新消息大事
  • 苏州公司建设网站权威解读当前经济热点问题
  • 网站 橙色如何做线上销售和推广
  • 2017优秀网站设计最新营销模式
  • 仙桃网站建设免费的模板网站
  • 永乐网站建设论坛推广网站
  • 做哪些网站可以赚钱的银川seo优化
  • Java做网站的学习路线做推广的都是怎么推
  • 做网站市场价格多少钱百度推广运营工作是什么
  • 客户网站开发全流程上海网络关键词优化
  • 网站建设明细报价我想注册一个网站怎么注册
  • cpc引流做网站cpa推广外链是什么
  • 邢台瑞光网络科技有限公司山东seo
  • 腾讯邮箱网页版登录入口seo站内优化和站外优化
  • 鲜花网站模板上海seo公司
  • 织梦怎么制作手机网站阿里云搜索
  • 外管局网站上做预收登记注册一个网站
  • 网站图怎么做杭州网站排名seo
  • 怎么才能搜索到自己做的网站企业网站seo托管怎么做
  • 外贸品牌网站设计公司建站
  • 电商商城平台福鼎网站优化公司