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

开发网站公司门户网站淘宝这种网站怎么做的

开发网站公司门户网站,淘宝这种网站怎么做的,图片设计软件有哪些,互联网是什么工作写在前面#xff1a; 由于时间的不足与学习的碎片化#xff0c;写博客变得有些奢侈。 但是对于记录学习#xff08;忘了以后能快速复习#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位#xff0c;以时间为顺序#xff0c;仅仅将博客当做一个知识学习的目录 由于时间的不足与学习的碎片化写博客变得有些奢侈。 但是对于记录学习忘了以后能快速复习的渴望一天天变得强烈。 既然如此 不如以天为单位以时间为顺序仅仅将博客当做一个知识学习的目录记录笔者认为最通俗、最有帮助的资料并尽量总结几句话指明本质以便于日后搜索起来更加容易。 标题的结构如下“类型”“知识点”——“简短的解释” 部分内容由于保密协议无法上传。 点击此处进入学习日记的总目录 2024.03.08 二十三、UCOSIII临界段1、临界段简介2、Cortex-M内核快速关中断指令3、关中断4、开中断5、临界段代码的应用6、测量关中断时间1. 测量关中断时间初始化2. 测量最大关中断时间3. 获取最大关中断时间 二十三、UCOSIII临界段 1、临界段简介 临界段代码也称作临界域是一段不可分割的代码。μC/OS中包含了很多临界段代码。如果临界段可能被中断 那么就需要关中断以保护临界段。如果临界段可能被任务级代码打断那么需要锁调度器保护临界段。 临界段用一句话概括就是一段在执行的时候不能被中断的代码段。在μC/OS里面这个临界段最常出现的就是对全局变量的操作 全局变量就好像是一个枪把子谁都可以对他开枪但是我开枪的时候你就不能开枪否则就不知道是谁命中了靶子。 可能有人会说我可以在子弹上面做个标记我说你能不能不要瞎扯淡。 那么什么情况下临界段会被打断一个是系统调度还有一个就是外部中断。在μC/OS的系统调度最终也是产生PendSV中断 在PendSV Handler里面实现任务的切换所以还是可以归结为中断。既然这样μC/OS对临界段的保护最终还是回到对中断的开和关的控制。 μC/OS中定义了一个进入临界段的宏和两个出临界段的宏用户可以通过这些宏定义进入临界段和退出临界段。 OS_CRITICAL_ENTER()OS_CRITICAL_EXIT()OS_CRITICAL_EXIT_NO_SCHED() 此外还有一个开中断但是锁定调度器的宏定义OS_CRITICAL_ENTER_CPU_EXIT()。 2、Cortex-M内核快速关中断指令 为了快速地开关中断 Cortex-M内核专门设置了一条 CPS 指令有 4 种用法 CPSID I ;PRIMASK1 ;关中断 CPSIE I ;PRIMASK0 ;开中断 CPSID F ;FAULTMASK1 ;关异常 CPSIE F ;FAULTMASK0 ;开异常PRIMASK和FAULTMAST是Cortex-M内核里面三个中断屏蔽寄存器中的两个还有一个是BASEPRI 有关这三个寄存器的详细用法见表 名字功能描述PRIMASK这是个只有单一比特的寄存器。在它被置1 后就关掉所有可屏蔽的异常只剩下NMI 和硬FAULT可以响应。它的默认值是0表示没有关中断。FAULTMASK这是个只有1 个位的寄存器。当它置1 时只有NMI 才能响应所有其他的异常甚至是硬FAULT也通通闭嘴。它的默认值也是0表示没有关异常。BASEPRI这个寄存器最多有9 位由表达优先级的位数决定。它定义了被屏蔽优先级的阈值。当它被设成某个值后所有优先级号大于等于此值的中断都被关优先级号越大优先级越低。但若被设成0则不关闭任何中断0 也是默认值。 在μC/OS中对中断的开和关是通过操作PRIMASK寄存器来实现的使用CPSID I指令就能立即关闭中断。很是方便。 3、关中断 μC/OS中关中断的函数在cpu_a.asm中定义无论上层的宏定义是怎么实现的底层操作关中断的函数还是CPU_SR_Save() CPU_SR_SaveMRSR0, PRIMASK ;通过MRS指令将特殊寄存器PRIMASK寄存器的值存储到通用寄存器r0。;当在C中调用汇编的子程序返回时 会将r0作为函数的返回值。;所以在C中调用CPU_SR_Save()的时候需要事先声明一个变量用来存储CPU_SR_Save()的返回值即r0寄存器的值 也就是PRIMASK的值。CPSID I ;关闭中断即使用CPS指令将PRIMASK寄存器的值置1。;在这里我敢肯定一定会有人有这样一个疑 问关中断不就是直接使用 CPSID I 指令就行了嘛为什么还要第一步即在执行CPSIDI指令前要先把PRIMASK的值保存起来;这个 疑问接下来在“临界段代码的应用”这个小结揭晓。BX LR ;子程序返回。 4、开中断 开中断要与关中断配合使用μC/OS中开中断的函数在cpu_a.asm中定义无论上层的宏定义是怎么实现的 底层操作关中断的函数还是CPU_SR_Restore() CPU_SR_RestoreMSR PRIMASK, R0 ;通过MSR指令将通用寄存器r0的值存储到特殊寄存器PRIMASK。;当在C中调用汇编的子程序返回时 会将第一个形参传入到通用寄存器r0。;所以在C中调用CPU_SR_Restore()的时候需要传入一个形参 该形参是进入临界段之前保存的PRIMASK的值。;这个时候又有人会问开中断不就是使用CPSIE I指令就行了嘛 为啥跟我等凡人想的不一样;其中奥妙将在接下来“临界段代码的应用”这个小结揭晓。BX LR;子程序返回。5、临界段代码的应用 在进入临界段之前我们会先把中断关闭退出临界段时再把中断打开。 而且Cortex-M内核设置了快速关中断的CPS指令 那么按照我们的第一思维开关中断的函数的实现和临界段代码的保护应该是这样的。 ;//开关中断函数的实现 ;/* ; * void CPU_SR_Save(); ; */ CPU_SR_SaveCPSID I ;(1)BX LR;/* ; * void CPU_SR_Restore(void); ; */ CPU_SR_RestoreCPSIE I ;(2)BX LRPRIMASK 0; /* PRIMASK初始值为0,表示没有关中断 */ //(3)/* 临界段代码保护 */ {/* 临界段开始 */CPU_SR_Save(); /* 关中断,PRIMASK 1 */ //(4){/* 执行临界段代码不可中断 */(5)}/* 临界段结束 */CPU_SR_Restore(); /* 开中断,PRIMASK 0 */ //(6) }(1)关中断直接使用了CPSID I没有跟代码清单:临界段-2一样事先将PRIMASK的值保存在r0中。(2)开中断直接使用了CPSIE I而不是像代码清单:临界段-3那样从传进来的形参来恢复PRIMASK的值。(3)假设PRIMASK初始值为0表示没有关中断。(4)临界段开始调用关中断函数CPU_SR_Save()此时PRIMASK的值等于1确实中断已经关闭。(5)执行临界段代码不可中断。(6)临界段结束 调用开中断函数CPU_SR_Restore()此时PRIMASK的值等于0确实中断已经开启。 乍一看 上边的这种实现开关中断的方法确实有效没有什么错误。 但是我们忽略了一种情况 就是当临界段是出现嵌套的时候这种开关中断的方法就不行了具体怎么不行具体见下面代码。 ;//开关中断函数的实现 ;/* ; * void CPU_SR_Save(); ; */ CPU_SR_SaveCPSID IBX LR;/* ; * void CPU_SR_Restore(void); ; */ CPU_SR_RestoreCPSIE IBX LR PRIMASK 0; /* PRIMASK初始值为0,表示没有关中断 *//* 临界段代码 */ {/* 临界段1开始 */CPU_SR_Save(); /* 关中断,PRIMASK 1 */{/* 临界段2 */CPU_SR_Save(); /* 关中断,PRIMASK 1 */{}CPU_SR_Restore(); /* 开中断,PRIMASK 0 */ //(注意)}/* 临界段1结束 */CPU_SR_Restore(); /* 开中断,PRIMASK 0 */ }有错误只为讲解 当临界段出现嵌套的时候这里以一重嵌套为例。 临界段1开始和结束的时候PRIMASK分别等于1和0表示关闭中断和开启中断这是没有问题的。 临界段2开始的时候 PRIMASK等于1表示关闭中断这是没有问题的。 问题出现在临界段2结束的时候PRIMASK的值等于0如果单纯对于临界段2来说 这也是没有问题的因为临界段2已经结束可是临界段2是嵌套在临界段1中虽然临界段2已经结束但是临界段1还没有结束 中断是不能开启的如果此时有外部中断来临那么临界段1就会被中断违背了我们的初衷那应该怎么办 正确的做法具体见下面程序 ;//开关中断函数的实现 ;/* ; * void CPU_SR_Save(); ; */ CPU_SR_SaveMRS R0, PRIMASKCPSID IBX LR;/* ; * void CPU_SR_Restore(void); ; */ CPU_SR_RestoreMSR PRIMASK, R0BX LRPRIMASK 0; /* PRIMASK初始值为0,表示没有关中断 */ //(1)CPU_SR cpu_sr1 (CPU_SR)0 CPU_SR cpu_sr2 (CPU_SR)0 //(2)/* 临界段代码 */ {/* 临界段1开始 */cpu_sr1 CPU_SR_Save(); /* 关中断,cpu_sr10,PRIMASK1 */ //(3){/* 临界段2 */cpu_sr2 CPU_SR_Save();/*关中断,cpu_sr21,PRIMASK1 */ //(4){}CPU_SR_Restore(cpu_sr2); /*开中断,cpu_sr21,PRIMASK1 */ //(5)}/* 临界段1结束 */CPU_SR_Restore(cpu_sr1); /* 开中断,cpu_sr10,PRIMASK0 */ //(6) }(1)假设PRIMASK初始值为0,表示没有关中断。(2)定义两个变量留着后面用。(3)临界段1开始调用关中断函数CPU_SR_Save() CPU_SR_Save()函数先将PRIMASK的值存储在通用寄存器r0 一开始我们假设PRIMASK的值等于0所以此时r0的值即为0。然后执行汇编指令 CPSIDI关闭中断即设置PRIMASK等于1 在返回的时候r0当做函数的返回值存储在cpu_sr1所以cpu_sr1等于r0等于0。(4)临界段2开始调用关中断函数CPU_SR_Save() CPU_SR_Save()函数先将PRIMASK的值存储在通用寄存器r0 临界段1开始的时候我们关闭了中断即设置PRIMASK等于1 所以此时r0的值等于1。然后执行汇编指令 CPSIDI关闭中断即设置PRIMASK等于1 在返回的时候r0当做函数的返回值存储在cpu_sr2所以cpu_sr2等于r0等于1。(5)临界段2结束调用开中断函数CPU_SR_Restore(cpu_sr2) cpu_sr2作为函数的形参传入到通用寄存器r0 然后执行汇编指令 MSR r0, PRIMASK 恢复PRIMASK的值。此时PRIAMSK r0 cpu_sr2 1。 关键点来了为什么临界段2结束了 PRIMASK还是等于1按道理应该是等于0。因为此时临界段2是嵌套在临界段1中的还是没有完全离开临界段的范畴所以不能把中断打开 如果临界段是没有嵌套的使用当前的开关中断的方法的话那么PRIMASK确实是等于1(6)临界段1结束PRIMASK等于0开启中断与进入临界段1遥相呼应。具体见如下代码 ;//开关中断函数的实现 ;/* ; * void CPU_SR_Save(); ; */ CPU_SR_SaveMRS R0, PRIMASKCPSID IBX LR;/* ; * void CPU_SR_Restore(void); ; */ CPU_SR_RestoreMSR PRIMASK, R0BX LRPRIMASK 0; /* PRIMASK初始值为0,表示没有关中断 */CPU_SR cpu_sr1 (CPU_SR)0/* 临界段代码 */ {/* 临界段开始 */cpu_sr1 CPU_SR_Save();/* 关中断,cpu_sr10,PRIMASK1 */{}/* 临界段结束 */CPU_SR_Restore(cpu_sr1); /* 开中断,cpu_sr10,PRIMASK0 */ //(注意点) }6、测量关中断时间 μC/OS提供了测量关中断时间的功能通过设置cpu_cfg.h中的宏定义CPU_CFG_INT_DIS_MEAS_EN为1就表示启用该功能。 系统会在每次关中断前开始测量开中断后结束测量测量功能保存了 2个方面的测量值总的关中断时间与最近一次关中断的时间。 因此用户可以根据得到的关中断时间对其加以优化。 时间戳的速率决定于CPU的速率。 例如如果CPU速率为72MHz 时间戳的速率就为72MHz那么时间戳的分辨率为1/72M微秒大约为13.8纳秒ns。 显然 系统测出的关中断时间还包括了测量时消耗的额外时间那么测量得到的时间减掉测量时所耗时间就是实际上的关中断时间。 关中断时间跟处理器的指令、速度、内存访问速度有很大的关系。 1. 测量关中断时间初始化 关中断之前要用函数 CPU_IntDisMeasInit()函数进行初始化 可以直接调用函数 CPU_Init()函数进行初始化具体见如下代码 #ifdef CPU_CFG_INT_DIS_MEAS_EN static void CPU_IntDisMeasInit (void) {CPU_TS_TMR time_meas_tot_cnts;CPU_INT16U i;CPU_SR_ALLOC();CPU_IntDisMeasCtr 0u;CPU_IntDisNestCtr 0u;CPU_IntDisMeasStart_cnts 0u;CPU_IntDisMeasStop_cnts 0u;CPU_IntDisMeasMaxCur_cnts 0u;CPU_IntDisMeasMax_cnts 0u;CPU_IntDisMeasOvrhd_cnts 0u;time_meas_tot_cnts 0u;CPU_INT_DIS(); /* 关中断 */for (i 0u; i CPU_CFG_INT_DIS_MEAS_OVRHD_NBR; i){CPU_IntDisMeasMaxCur_cnts 0u;CPU_IntDisMeasStart(); /* 执行多个连续的开始/停止时间测量 */CPU_IntDisMeasStop();time_meas_tot_cnts CPU_IntDisMeasMaxCur_cnts; /* 计算总的时间 */}CPU_IntDisMeasOvrhd_cnts (time_meas_tot_cnts (CPU_CFG_INT_DIS_MEAS_OVRHD_NBR / 2u))/CPU_CFG_INT_DIS_MEAS_OVRHD_NBR;/*得到平均值就是每一次测量额外消耗的时间 */CPU_IntDisMeasMaxCur_cnts 0u;CPU_IntDisMeasMax_cnts 0u;CPU_INT_EN(); } #endif因为关中断测量本身也会耗费一定的时间这些时间实际是加入到我们测量到的最大关中断时间里面如果能够计算出这段时间 后面计算的时候将其减去可以得到更加准确的结果。 这段代码的核心思想很简单就是重复多次开始测量与停止测量 然后多次之后取得平均值那么这个值就可以看作一次开始测量与停止测量的时间保存在CPU_IntDisMeasOvrhd_cnts变量中。 2. 测量最大关中断时间 如果用户启用了CPU_CFG_INT_DIS_MEAS_EN这个宏定义那么系统在关中断的时候会调用了开始测量关中断最大时间的函数 CPU_IntDisMeasStart()开中断的时候调用停止测量关中断最大时间的函数CPU_IntDisMeasStop()。 从代码中我们能看到 只要在关中断且嵌套层数 OSSchedLockNestingCtr为0的时候保存下时间戳如果嵌套层数不为0肯定不是刚刚进入中断 退出中断且嵌套层数为 0 的时候这个时候才算是真正的退出中断把测得的时间戳减去一次测量额外消耗的时间 便得到这次关中断的时间再将这个时间跟历史保存下的最大的关中断的时间对比刷新最大的关中断时间 源码具体如下 /* 开始测量关中断时间 */ #ifdef CPU_CFG_INT_DIS_MEAS_EN void CPU_IntDisMeasStart (void) {CPU_IntDisMeasCtr;if (CPU_IntDisNestCtr 0u) /* 嵌套层数为0 */{CPU_IntDisMeasStart_cnts CPU_TS_TmrRd(); /* 保存时间戳 */}CPU_IntDisNestCtr; } #endif/* 停止测量关中断时间 */ #ifdef CPU_CFG_INT_DIS_MEAS_EN void CPU_IntDisMeasStop (void) {CPU_TS_TMR time_ints_disd_cnts;CPU_IntDisNestCtr--;if (CPU_IntDisNestCtr 0u) /* 嵌套层数为0*/{CPU_IntDisMeasStop_cnts CPU_TS_TmrRd(); /* 保存时间戳 */time_ints_disd_cnts CPU_IntDisMeasStop_cnts -CPU_IntDisMeasStart_cnts;/* 得到关中断时间 *//* 更新最大关中断时间 */if (CPU_IntDisMeasMaxCur_cnts time_ints_disd_cnts){CPU_IntDisMeasMaxCur_cnts time_ints_disd_cnts;}if (CPU_IntDisMeasMax_cnts time_ints_disd_cnts){CPU_IntDisMeasMax_cnts time_ints_disd_cnts;}} } #endif3. 获取最大关中断时间 现在得到了关中断时间那么μC/OS也提供了三个与获取关中断时间有关的函数分别是 CPU_IntDisMeasMaxCurReset()CPU_IntDisMeasMaxCurGet()CPU_IntDisMeasMaxGet() 如果想直接获取整个程序运行过程中最大的关中断时间的话直接调用函数 CPU_IntDisMeasMaxGet()获取即可。 如果想要测量某段程序执行的最大关中断时间那么在这段程序的前面调用CPU_IntDisMeasMaxCurReset()函数将 CPU_IntDisMeasMaxCur_cnts 变量清 0在这段程序结束的时候调用函数CPU_IntDisMeasMaxCurGet()即可。 这些函数的源码很简单 #ifdef CPU_CFG_INT_DIS_MEAS_EN//如果启用了关中断时间测量 CPU_TS_TMR CPU_IntDisMeasMaxCurGet (void) //获取测量的程序段的最大关中断时间 {CPU_TS_TMR time_tot_cnts;CPU_TS_TMR time_max_cnts;CPU_SR_ALLOC(); //使用到临界段在关/开中断时时必须用到该宏该宏声明和//定义一个局部变量用于保存关中断前的 CPU 状态寄存器// SR临界段关中断只需保存SR开中断时将该值还原。CPU_INT_DIS(); //关中断time_tot_cnts CPU_IntDisMeasMaxCur_cnts;//获取未处理的程序段最大关中断时间CPU_INT_EN(); //开中断time_max_cnts CPU_IntDisMeasMaxCalc(time_tot_cnts);//获取减去测量时间后的最大关中断时间return (time_max_cnts); //返回程序段的最大关中断时间 } #endif#ifdef CPU_CFG_INT_DIS_MEAS_EN//如果启用了关中断时间测量 CPU_TS_TMR CPU_IntDisMeasMaxGet (void) //获取整个程序目前最大的关中断时间 {CPU_TS_TMR time_tot_cnts;CPU_TS_TMR time_max_cnts;CPU_SR_ALLOC(); //使用到临界段在关/开中断时时必须用到该宏该宏声明和//定义一个局部变量用于保存关中断前的 CPU 状态寄存器// SR临界段关中断只需保存SR开中断时将该值还原。CPU_INT_DIS(); //关中断time_tot_cnts CPU_IntDisMeasMax_cnts;//获取尚未处理的最大关中断时间CPU_INT_EN(); //开中断time_max_cnts CPU_IntDisMeasMaxCalc(time_tot_cnts);//获取减去测量时间后的最大关中断时间return (time_max_cnts); //返回目前最大关中断时间 } #endif#ifdef CPU_CFG_INT_DIS_MEAS_EN//如果启用了关中断时间测量 CPU_TS_TMR CPU_IntDisMeasMaxCurReset (void) //初始化复位测量程序段的最大关中断时间 {CPU_TS_TMR time_max_cnts;CPU_SR_ALLOC(); //使用到临界段在关/开中断时时必须用到该宏该宏声明和//定义一个局部变量用于保存关中断前的 CPU 状态寄存器// SR临界段关中断只需保存SR开中断时将该值还原。time_max_cntsCPU_IntDisMeasMaxCurGet();//获取复位前的程序段最大关中断时间CPU_INT_DIS(); //关中断CPU_IntDisMeasMaxCur_cnts 0u; //清零程序段的最大关中断时间CPU_INT_EN(); //开中断return (time_max_cnts); //返回复位前的程序段最大关中断时间 } #endif
http://www.pierceye.com/news/8902/

相关文章:

  • 辛集建设局官方网站建程网土石方工程
  • 上海做网站最低价ui网页界面设计素材
  • 如何写好网站开发技术文档明星静态网站
  • 网站的制作百度一下 你就知道首页官网
  • 苏州网站建设制作工作室广东建设厅网站首页
  • 信息发布网站推广技巧如何自己做论坛网站
  • 吕梁seo网站建设怎么做可以访问网站
  • 鹤城建设集团网站个人网页设计的方法
  • 山东建设局网站网站备案信息保护
  • 网站的总体风格包括东营建设银行电话号码
  • 网站被泛解析广告优化师面试
  • 百度推广做网站wordpress登录更改域名后
  • dw做电影网站扬州市工程信息网
  • 娱乐建网站门户网站制作服务
  • 手机移动端网站是什么网站架设教程
  • 手机建站系统一般建设企业网站的费用
  • 福建网站建设费用网站org免费注册
  • 电商学习网站seo公司排名榜
  • 上海市建设人才网站个人博客登录入口
  • 网站建立的方式是什么网站开发朋友圈广告
  • 租用海外服务器的网站有域名吗价格优化网站建设
  • 主题公园旅游景区网站建设怎么建立一个属于自己的网站
  • 望城警务督察网站建设免费ppt模板素材免费下载
  • 阳新网站建设网站开发应聘问题
  • 三亚市住房和城乡建设局网站做整合营销的网站
  • 杭州做网站的公司排行本地做的网站怎么解析到域名
  • 对于政务网站建设的建议如何快速推广自己的产品
  • 移动端网站开发教程seo优化的网站
  • 网站建设到运营需要多少钱佛山网站开发哪家好
  • 东莞外贸网站能发朋友圈的网站建设语