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

西部数据网站备案流程表格比较多得网站这么做响应式

西部数据网站备案流程,表格比较多得网站这么做响应式,潜江资讯网房屋出售,免费网页模板下载大全目录 一、通用堆栈知识二、双堆栈用法三、PendSV 中断介绍和用法四、SVC 软中断介绍和用法五、特权级和非特权级使用方法 一、通用堆栈知识 在前面讲解 STM32 启动文件的时候就已经提到过#xff0c;有关堆栈大小的设置是在启动文件中设置的#xff1a; Heap 主要用于 Mal… 目录 一、通用堆栈知识二、双堆栈用法三、PendSV 中断介绍和用法四、SVC 软中断介绍和用法五、特权级和非特权级使用方法 一、通用堆栈知识 在前面讲解 STM32 启动文件的时候就已经提到过有关堆栈大小的设置是在启动文件中设置的 Heap 主要用于 Malloc、Free动态内存申请和释放。 Stack 也非常重要程序编译后所包含的大量 PUSH 和 POP 指令操作系统根据 SP堆栈指针 寄存器访问当前对应栈内存通过栈保存临时数据。大部分的栈都是向下生长的也有向上生长的。M 内核的栈是从高地址向低地址生长的下面通过一个例子演示一下 __IO uint32_t a 0x11111111; __IO uint32_t b 0x22222222; __IO uint32_t c 0x33333333; __IO uint32_t d 0x44444444; __IO uint32_t e 0x55555555; __IO uint32_t f 0x66666666; __IO uint32_t g 0x77777777; __IO uint32_t h 0x88888888;然后进入调试状态可以看到现在 SP 指针是 0x20000618。 可当我们实际点击单步调试的时候SP 指针现在又变成了 0x200005F80x20000618 - 0x200005F8 等于十进制的 32。也就是说少了 32 个字节。这里是因为程序一来就把这 8 个数据共 32 个字节的内存分配好了。 当你把 __IO 去掉后就不会出现以上的情况。__IO 其实就是 volatile所以在这里就是告诉编译器它后面所定义的变量随时都有可能改变因此编译后的程序每次需要存储或读取这个变量的时候告诉编译器对该变量不做优化都会直接从变量内存地址中读取数据从而可以提供对特殊地址的稳定访问。 下面继续执行可以看到数据是从高地址向低地址存储的。 当然内存空间只是连续字节数据的抽象本身并不区分堆和栈的概念它做的只是存储和读写信息。因此如何定义堆栈、初始化建立堆栈环境在嵌入式软件运行前便显得尤为重要。这涉及到处理器提供的堆栈机制、操作系统内存管理和进程切换等方方面面。 二、双堆栈用法 下图取自权威指南 在搭载实时操作系统内核的嵌入式软件中栈往往分为两大类除了满足系统基本的主栈main stack外往往还需要进程/线程栈process stack。这两部分内存空间是独立存在的 主栈位于系统的栈区stack而线程堆栈往往定义在堆区heap或静态区static 无论是静态还是动态创建线程栈都不会占用栈区的主栈空间。即线程栈并不在栈区可能在数据区或堆区再次说明主栈和线程栈内存空间独立。 理解这一点是理解 MCU 堆栈的关键前提。 所谓双堆栈本质上都是 R13不过在不同的运行状态下使用的栈是不同的并且在同一时刻只有其中的一个栈可用。在系统复位后、进入线程环境前默认使用主堆栈中断服务程序ISR中也是使用主堆栈。RTOS 各线程中的应用代码则使用线程堆栈。 如果使用了双堆栈那么在中断里只能使用 MSP而在中断以外可以使用 MSP也可以使用 PSP。不过在 RTOS 里中断以外全部使用 PSP后面讲原因。 上电后系统仅初始化了 MSP需要通过额外的汇编代码建立完整的双堆栈系统当实时内核准备就绪线程调度正常运行双堆栈机制开始工作。进中断时系统根据当前状态自动切换堆栈进程上下文切换时会更新不同线程的 PSP通过修改 EXC_RETURN 可以手动切换 MSP/PSP。 双堆栈机制使得内核/ISR 堆栈和线程应用堆栈分开管理通过不同的堆栈指针寄存器完成切换大大提高了系统的效率在绝大部分的嵌入式实时操作系统中都使用了双堆栈机制如 ucos、FreeRTOS、RT-Thread 等。 在一些简单的应用中例如裸机程序可以从头到尾都只使用主堆栈只要确保分配足够的空间即可。 还是一样通过例程来看在刚才的程序下面添加 __set_PSP(__get_MSP()); /* 设置PSP位置 */ __set_CONTROL(0x02); /* bit1 1表示使用PSPbit1 0表示使用MSP */ {__IO uint32_t a1 0x11111111;__IO uint32_t b1 0x22222222;__IO uint32_t c1 0x33333333;__IO uint32_t d1 0x44444444;__IO uint32_t e1 0x55555555;__IO uint32_t f1 0x66666666;__IO uint32_t g1 0x77777777;__IO uint32_t h1 0x88888888;printf(a1 %x, b1 %x\r\n, a1, b1); }下面继续执行 这里将 PSP 指向 MSP 一样的地址然后设置使用 PSP 然后继续执行 可以看到现在只是改成使用 PSP 了其它和 MSP 没有什么区别。 下面我在我的 SysTick_Handler 函数中打一个断点然后全速执行 栈指针又切换回 MSP 了。而退出中断后又会自动切换回 PSP 这也印证了刚才所说的在任务中使用 PSP在中断中使用 MSP。使用双堆栈把任务和中断使用的栈区分开这样安全性会更好一些。 三、PendSV 中断介绍和用法 PendSV 典型使用场合是在上下文切换时在不同任务之间切换。上下文切换的本质就是保存当前执行现场 A切换到另一个任务 B 里面。切换回来时又要恢复执行现场 A将一系列的寄存器入栈、出栈。 由于 PendSV 的特点就是支持缓期执行所以 RTOS 可以利用它这个特点进行任务调度过程的上下文切换。而为什么要使用缓期执行的特点来进行上下文切换呢简单的说就是任何 RTOS都需要尽量不打断外设中断。 我们来举例说明假如一个系统中有两个就绪的任务上下文切换被切换的场合可以是 执行一个系统调用系统滴答定时器 SYSTICK 中断触发了任务的调度。 假如我们在 Systick 中断服务程序中启动上下文切换流程图如下 但若在产生 SysTick 异常时正在响应一个中断则 SysTick 异常会抢占其ISR。在这种情况下OS 是不能执行上下文切换的否则将使中断请求被延迟而且在真实系统中延迟时间还往往不可预知——任何有一丁点实时要求的系统都决不能容忍这种事。因此在 CM3 中也是如果 OS 在某中断活跃时尝试切入线程模式将触犯用法 fault 异常。 为解决此问题早期的 OS 大多会检测当前是否有中断在活跃中只有在无任何中断需要响应时才执行上下文切换切换期间无法响应中断。然而这种方法的弊端在于它可以把任务切换动作拖延很久因为如果抢占了 IRQ则本次 SysTick 在执行后不得作上下文切换只能等待下一次 SysTick 异常尤其是当某中断源的频率和 SysTick 异常的频率比较接近时会发生“共振”使上下文切换迟迟不能进行。 如果将 SysTick 的优先级设置为最低然后在 SysTick 中进行上下文切换然后任务调度。这样不会触发 Fault。但是也有一个问题 一般 OS 在调度任务时会关闭中断也就是进入临界区而 OS 任务调度是要耗时的这就会出现一种情况 在任务调度期间如果新的外部 IRQ 发生CPU 将不能够快速响应处理。 而现在有了 PendSVPendSV 异常会自动延迟上下文切换的请求缓期执行直到其它的 ISR 都完成了处理后才放行。为实现这个机制需要把PendSV 为最低优先级的异常。 如果 OS 检测到某 IRQ 正在活动并且被 SysTick 抢占它将悬起一个 PendSV 异常以便缓期执行上下文切换。 下面用一个数组模拟栈空间来展示一下函数的切换 uint32_t PspStack[100]; /* PspStack栈空间 */int main(void) {...p_stk PspStack[100];/* 硬件自动入栈 */*(--p_stk) (uint32_t)0x01000000; /* xPSR */*(--p_stk) (uint32_t)PrintfLogo; /* PC */*(--p_stk) (uint32_t)0x00000000; /* R14 (LR) */*(--p_stk) (uint32_t)0xAAAAAAAA; /* R12 */*(--p_stk) (uint32_t)0xBBBBBBBB; /* R3 */*(--p_stk) (uint32_t)0xCCCCCCCC; /* R2 */*(--p_stk) (uint32_t)0xDDDDDDDD; /* R1 */*(--p_stk) (uint32_t)0xEEEEEEEE; /* R0 : argument *//* 根据需要手动入栈的 */*(--p_stk) (uint32_t)0x11111111; /* R11*/*(--p_stk) (uint32_t)0x22222222; /* R10*/*(--p_stk) (uint32_t)0x33333333; /* R9 */*(--p_stk) (uint32_t)0x44444444; /* R8 */*(--p_stk) (uint32_t)0x55555555; /* R7 */*(--p_stk) (uint32_t)0x66666666; /* R6 */*(--p_stk) (uint32_t)0x77777777; /* R5 */*(--p_stk) (uint32_t)0x88888888; /* R4 *//* 使能PendSV中断 */SCB-ICSR | SCB_ICSR_PENDSVSET_Msk;/*##- 测试SVC软中断 ####################################################*/SVCTest(0x11223344, 0x55667788, 0xaabbddee);... }void PendSV_Handler(void) {__asm(BKPT 0);__set_PSP((uint32_t)PspStack[92]); }在 M 内核R0、R1、R2、R3、R12、R14LR、R15PC、xPSR这 8 个寄存器是自动入栈的。而其余的寄存器是手动入栈的。 开启了 PendSV 中断后当来到 SVCTest后面会介绍时就会触发 PendSV 异常。 在 PendSV_Handler 函数中我们使 PSP 指向 PspStack[92]也就是 PrintfLogo。所以当触发 PendSV 中断的时候我们会将 PSP 指针指向 PrintfLogo 函数。也就是说原本正常情况下PC 指针保存的是当前 main 函数中下一条指令的地址这里我们手动将其修改成了另一个函数的地址。这就是任务切换的本质。 来看现象 再执行一步的时候就会跳转到 PendSV_Handler。 当跳出 PendSV_Handler 函数后正常情况下我们应该继续在 main 函数中向后执行而这里会跳转到 PrintfLogo 函数中 旁边的寄存器的值和我们硬件自动入栈的值也是对应的 四、SVC 软中断介绍和用法 SVC 用于生成系统函数调用的请求例如用户程序不允许直接访问硬件操作系统可以通过 SVC 提供对硬件的访问。因此当用户程序想要使用某些硬件时可以使用 SVC 指令然后执行操作系统中的软件异常处理程序并提供用户应用程序请求的服务。通过这种方式对硬件的访问由操作系统控制操作系统可以阻止用户应用程序直接访问硬件从而提供更可靠的系统。 SVC 还可以使软件更具可移植性因为用户程序不需要知道硬件的编程细节。用户程序只需要知道应用程序编程接口(API)函数 ID 和参数而实际的硬件级编程是由设备驱动程序处理的。 SVC 异常由 SVC 指令产生该指令需要一个立即数作为参数根据这个参数执行不同的 SVC 处理函数。例 SVC #0x3 ; 调用SVC 函数3 SVC 0x3 ; 传统的语法(没有#)也可行在 C 语言中可以使用编译器关键字函数 __svc 或者使用内联汇编代码来执行 SVC 指令。 对于操作系统来说当 SVC 处理程序被执行时我们可以通过读取堆栈中的 PC 值来确定 SVC 指令中的立即数据值然后从该地址读取指令并屏蔽不需要的位。如果使用的PSP堆栈则还需要通过LR寄存器判断当前使用的是哪个堆栈。 在 ARM7 中有一个软件中断指令 SWI(Software interrupt instruction)。实际上SVC 指令的二进制编码与 ARM7 中的 SWI 是相同的。由于异常模型发生了变化这条指令被重命名以确保程序员能够正确地将软件代码从 ARM7 移植到 Cortex-M3。 当 SVC 指令被执行后处理器会根据中断向量表中的信息跳转到相应的 SVC 中断处理函数执行 SVC 指令时处理器会自动保存当前的上下文并将处理器的模式切换为特权模式从而允许执行受限的操作。 简单来说RTOS 内核中的各个 API不是在任务里执行的而是在 SVC 软中断里执行的。这样一来就把 RTOS 内核和任务隔离开了。 __svc 是 MDK 内置的一个定义前缀用于设置 SVC 软中断的序号0~255可以用来区分不同的使用场景 void __svc(0) SVCTest(uint32_t a, uint32_t b, uint32_t c); /* SVC软中断 */.../*##- 测试SVC软中断 ####################################################*/ SVCTest(0x11223344, 0x55667788, 0xaabbddee);单步运行后直接跳转并且把函数数据也一并保存在 R0、R1、R2 寄存器中 当我们调用 OS 内核的 API 的时候一调用就会进入到 SVC 中断让这个函数直接在 SVC 中断中执行这样把 OS 的函数和我们自己写的应用程序隔离开了。 五、特权级和非特权级使用方法 特权级和非特权级只是针对中断外的任务来说的中断全部都是特权级 如果代码是在中断里执行则只能是特权级中断以外可以是特权级也可以是非特权级。 非特权级主要是 RTX 在使用。如果是在非特权级的模式下则不能访问和配置 Cortex-M 内核相关的寄存器例如 SCB否则会触发异常。 /*##- 测试非特权级 ####################################################*/ __set_CONTROL(0x01); /* bit0 1表示应用程序工作在非特权级模式bit1 0表示应用程序工作在特权级模式 */ SCB-ICSR | SCB_ICSR_PENDSVSET_Msk; /* 操作SCB就会进入异常 */例程中先开启非特权模式然后再操作 SCB系统控制块寄存器时会触发异常 直接就来到 HardFault 了。 那非特权级模式下核心外设寄存器如何初始化 如果用户将 RTX 操作系统的任务设置在非特权级模式下运行那么核心外设寄存器应该放在哪里进行初始化呢主要有以下两种方法 使用 SVCSupervisor Call软中断。在初始化和开启RTX多任务前做核心外设的初始化。 那在 Cortex-M3/M4/M7 内核如何切换两种模式Cortex-M3/M4/M7 中的特殊功能寄存器包括 程序状态寄存器组PSRs、xPSR中断屏蔽寄存器组PRIMASK、FAULTMASK、BASEPRI控制寄存器CONTROL 其中控制寄存器 CONTROL 是用来设置特权级和非特权级切换的CONTROL 寄存器定义如下 前面的例子中也演示了如何设置 CONTROL 寄存器 __set_CONTROL(uint32_t control)
http://www.w-s-a.com/news/303188/

相关文章:

  • 如何让公司网站网站转备案
  • 获得网站所有关键字北京网站建设116net
  • 铜陵电子商务网站建设做龙之向导网站有用吗
  • 购物网站制作费用沧州新华区
  • 信宜网站设计公司在线购物商城系统
  • 网站维护是什么样如何制作网站教程视频讲解
  • 网站建设网络推广代理公司wordpress图片防盗链
  • 网站备案关站沈阳男科医院哪家好点
  • 王者荣耀网站建设的步骤网站页面用什么软件做
  • 典型网站开发的流程房屋装修效果图三室一厅
  • 制作微网站多少钱阿里巴巴做网站的电话号码
  • 风铃建站模板安卓手机软件开发外包
  • 深圳市住房和建设局门户网站域名转移影响网站访问吗
  • 做母婴网站赚钱汕头百姓网
  • 那个网站建设好动漫制作技术升本可以升什么专业
  • 网站建设企业响应式网站模板广西建设部投诉网站
  • app营销的特点wordpress优化方案
  • 静安网站建设公司如何编辑wordpress
  • 做网站的职位叫什么问题常州金坛网站建设
  • 保健品网站模板用jsp做的网站前后端交互
  • 网站带后台品牌网页设计图片
  • 保定清苑住房和城乡建设局网站分类信息网站程序
  • 可以做视频推广的网站选择大连网站建设
  • 在线网站开发网站在哪里
  • 建站的步骤上海快速优化排名
  • 招聘网站做一下要多少钱网站设计公司 国际
  • 巩义专业网站建设公司首选seo研究院
  • 大流量网站解决访问量友情链接如何添加
  • 教育网站建设网永康市住房和城乡建设局网站
  • 阿里巴巴官网网站django 做网站的代码