基于TI-RTOS的CC2650DK开发(7)---软件中断
3.5 软件中断
- Swi_andn()
- Swi_dec()
- Swi_inc()
- Swi_or()
- Swi_post()
一个Swi会运行至结束,除非它被Hwi中断或更高优先级的Swi抢占。
任何触发或提交Swi的硬件ISR都必须已经被Hwi调度器调用(对于不支持Hwi调度器的平台,由中断存根产生,如MSP430)。这意味着,Swi必须由Hwi对象所调用的函数触发。
关于完整的Swi API、配置和对象参考信息,请参照在线文档“ti.sysbios.knl”包的Swi模块。(运行在线帮助的相关信息,请参考1.6.1节,23页---Using the API Reference Help System)
Swi_Handle swi0;
Swi_Params swiParams; Error_Block eb; Error_init(&eb); Swi_Params_init(&swiParams); swi0 = Swi_create(swiFunc, &swiParams, &eb); if (swi0 == NULL) { System_abort("Swi create failed"); } |
var Swi = xdc.useModule('ti.sysbios.knl.Swi');
var swiParams = new Swi.Params(); program.global.swi0 = Swi.create(swiParams); |
Swi的优先级分为不同级别。你可在内存限制所允许的范围内为每个优先级创建尽可能多的Swis。你可以为拥有更短实时期限线程的Swi选择一个更高的优先级(更大的优先级序号),也可以为Swi分配一个更低的优先级,用于处理那些拥有不太关键执行期限的线程。
Program.stack = yourStackSize;
|
下表显示了在最坏Swi中断嵌套情况下所需要的系统栈尺寸。第一列数字是某目标的首个优先级系统栈尺寸。第二列数字显示的是每个之后的优先级所使用的系统栈的尺寸。
![](http://img2.ph.126.net/BHzcEtssNpmfZL2HpbfXlA==/6631747263888331241.jpg)
查看3.4.2节获知Hwis的系统栈使用信息,查看3.6.3节获知task栈尺寸信息。
如果Swis可用,Swi管理器会对比提交的Swi对象的优先权和当前运行线程的优先权。如果当前运行线程是后台Idle Loop、一个Task、或低优先级Swi,Swi管理器将从Swis posted列表删除Swi,将CPU控制权从当前线程切换至提交的Swi函数,并开始运行。
- 当Swi开始执行,它必须无阻塞地执行完毕。
- 当从硬件ISR中被调用,任何触发或提交Swi的函数的代码必须已经被Hwi调度器调用(对于不支持Hwi调度器的平台,由中断存根产生,如MSP430)。这意味着,Swi必须由Hwi对象所调用的函数触发。
- 当Swi_post()用于提交Swi时,不会改变Swi对象触发器的值。
- Swi_or()设置由作为参数传递过来的掩码决定的触发器的标志位,然后提交Swi。
- Swi_inc()在提交Swi对象前将Swi的触发器值加1。
- Swi_andn()和Swidec()仅在Swi对象的触发器值变为0时提交它。
- Swi_andn()将作为参数传递过来的掩码决定的触发器的标志位清0。
- Swi_dec()将触发器值减1。
![](http://img2.ph.126.net/jGQZU30K0hCMAo-I2XvPYQ==/6631783547772058337.jpg)
![](http://img2.ph.126.net/M5Lsa4Nl_EcyDzkHhwTugQ==/6631576839586041470.jpg)
![](http://img1.ph.126.net/2vJJhmFST7ujVNMKA7VsVw==/6631712079516271264.jpg)
![](http://img1.ph.126.net/yz_HdFJ3sQW--Sh44g9TeQ==/6631476784027923688.jpg)
![](http://img0.ph.126.net/0kU-qvaj_Sm16RYPWlhufQ==/6631697785865092200.jpg)
3.5.6 利弊权衡
- 如果使用Swi函数而不是Hwi来更改共享数据结构体,你可通过在Task访问共享数据结构体时禁用Swis获得互斥(见73页)。这使得系统可以使用Hwis实时响应事件。相比之下,如果Hwi函数直接更改共享数据结构体,Tasks就需要禁止Hwis访问数据结构体以获得互斥。显而易见,禁用Hwis会降低实时系统的性能。
- 将长的ISRs分成两块通常是有意义的。Hwi关心那些对时间要求极其严格的关键操作,而把不太关键的处理在Hwi内提交到Swi函数进行推迟处理。
key = Swi_disable();
|
Swi_restore(key);
|
- Register:在所静态创建Swis前被调用,用于在运行时进行初始化。register hook在main()前的中断使能前被调用。
- Create:在创建一个Swi时被调用。包括静态创建和使用Swi_create()进行动态创建。
- Ready:在任何Swi准备运行前调用。
- Begin:在运行一个Swi函数前调用。
- End:Swi函数返回前被调用。
- Delete:在运行时使用Swi_delete()删除一个Swi时调用。
typedef struct Swi_HookSet
{ Void (*registerFxn)(Int); /* Register Hook */ Void (*createFxn)(Handle, Error.Block *); /* Create Hook */ Void (*readyFxn)(Handle); /* Ready Hook */ Void (*beginFxn)(Handle); /* Begin Hook */ Void (*endFxn)(Handle); /* End Hook */ Void (*deleteFxn)(Handle); /* Delete Hook */ }; |
Void registerFxn(Int id);
|
Void createFxn(Swi_Handle swi, Error_Block *eb);
Void deleteFxn(Swi_Handle swi); |
Ready、Begin和End hook函数在中断可用时调用。readyFxn函数在Swi已经提交,并准备运行时调用。beginFxn函数在给定Swi所关联的函数运行前调用。endFxn函数在Swi函数返回后调用。
Void readyFxn(Swi_Handle swi);
Void beginFxn(Swi_Handle swi); Void endFxn(Swi_Handle swi); |
C文件代码:
#include <xdc/std.h>
#include <xdc/runtime/Error.h> #include <xdc/runtime/System.h> #include <xdc/runtime/Timestamp.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/hal/Timer.h> #include <ti/sysbios/knl/Swi.h> Swi_Handle mySwi; Int myHookSetId1, myHookSetId2; /* HookSet 1 functions */ /* ======== myRegister1 ======== * invoked during Swi module startup before main * for each HookSet */ Void myRegister1(Int hookSetId) { System_printf("myRegister1: assigned hookSet Id = %d\n", hookSetId); myHookSetId1 = hookSetId; } /* ======== myCreate1 ======== * invoked during Swi_create for dynamically created Swis */ Void myCreate1(Swi_Handle swi, Error_Block *eb) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId1); /* pEnv should be 0 at this point. If not, there's a bug. */ System_printf("myCreate1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId1, (Ptr)0xdead1); } //* ======== myReady1 ======== /* invoked when Swi is posted */ Void myReady1(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId1); System_printf("myReady1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId1, (Ptr)0xbeef1); } /* ======== myBegin1 ======== * invoked just before Swi func is run */ Void myBegin1(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId1); System_printf("myBegin1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId1, (Ptr)0xfeeb1); } /* ======== myEnd1 ======== * invoked after Swi func returns */ Void myEnd1(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId1); System_printf("myEnd1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId1, (Ptr)0xc0de1); } /* ======== myDelete1 ======== * invoked upon Swi deletion */ Void myDelete1(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId1); System_printf("myDelete1: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); } /* HookSet 2 functions */ /* ======== myRegister2 ======== * invoked during Swi module startup before main * for each HookSet */ Void myRegister2(Int hookSetId) { System_printf("myRegister2: assigned hookSet Id = %d\n", hookSetId); myHookSetId2 = hookSetId; } /* ======== myCreate2 ======== * invoked during Swi_create for dynamically created Swis */ Void myCreate2(Swi_Handle swi, Error_Block *eb) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId2); /* pEnv should be 0 at this point. If not, there's a bug. */ System_printf("myCreate2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId2, (Ptr)0xdead2); } /* ======== myReady2 ======== * invoked when Swi is posted */ Void myReady2(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId2); System_printf("myReady2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId2, (Ptr)0xbeef2); } /* ======== myBegin2 ======== * invoked just before Swi func is run */ Void myBegin2(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId2); System_printf("myBegin2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId2, (Ptr)0xfeeb2); } /* ======== myEnd2 ======== * invoked after Swi func returns */ Void myEnd2(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId2); System_printf("myEnd2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); Swi_setHookContext(swi, myHookSetId2, (Ptr)0xc0de2); } /* ======== myDelete2 ======== * invoked upon Swi deletion */ Void myDelete2(Swi_Handle swi) { Ptr pEnv; pEnv = Swi_getHookContext(swi, myHookSetId2); System_printf("myDelete2: pEnv = 0x%x, time = %d\n", pEnv, Timestamp_get32()); } /* ======== mySwiFunc ======== */ Void mySwiFunc(UArg arg0, UArg arg1) { System_printf("Entering mySwi.\n"); } /* ======== myTaskFunc ======== */ Void myTaskFunc(UArg arg0, UArg arg1) { System_printf("Entering myTask.\n"); System_printf("Posting mySwi.\n"); Swi_post(mySwi); System_printf("Deleting mySwi.\n"); Swi_delete(&mySwi); System_printf("myTask exiting ...\n"); } /* ======== myIdleFunc ======== */ Void myIdleFunc() { System_printf("Entering myIdleFunc().\n"); System_exit(0); } /* ======== main ======== */ Int main(Int argc, Char *argv[]) { Error_Block eb; Error_init(&eb); System_printf("Starting SwiHookExample...\n"); /* Create mySwi with default params * to exercise Swi Hook Functions */ mySwi = Swi_create(mySwiFunc, NULL, &eb); if (mySwi == NULL) { System_abort("Swi create failed"); } BIOS_start(); return (0); } |
/* pull in Timestamp to print time in hook functions */
xdc.useModule('xdc.runtime.Timestamp'); /* Disable Clock so that ours is the only Swi in the application */ var BIOS = xdc.useModule('ti.sysbios.BIOS'); BIOS.clockEnabled = false; var Idle = xdc.useModule('ti.sysbios.knl.Idle'); Idle.addFunc('&myIdleFunc'); /* Create myTask with default task params */ var Task = xdc.useModule('ti.sysbios.knl.Task'); var taskParams = new Task.Params(); Program.global.myTask = Task.create('&myTaskFunc', taskParams); /* Define and add two Swi Hook Sets */ var Swi = xdc.useModule("ti.sysbios.knl.Swi"); /* Hook Set 1 */ Swi.addHookSet({ registerFxn: '&myRegister1', createFxn: '&myCreate1', readyFxn: '&myReady1', beginFxn: '&myBegin1', endFxn: '&myEnd1', deleteFxn: '&myDelete1' }); /* Hook Set 2 */ Swi.addHookSet({ registerFxn: '&myRegister2', createFxn: '&myCreate2', readyFxn: '&myReady2', beginFxn: '&myBegin2', endFxn: '&myEnd2', deleteFxn: '&myDelete2' }); |
[Cortex_M3_0] myRegister1: assigned hookSet Id = 0
myRegister2: assigned hookSet Id = 1 Starting SwiHookExample... myCreate1: pEnv = 0x0, time = 6 myCreate2: pEnv = 0x0, time = 14 Entering myTask. Posting mySwi. myReady1: pEnv = 0xdead1, time = 30 myReady2: pEnv = 0xdead2, time = 38 myBegin1: pEnv = 0xbeef1, time = 48 myBegin2: pEnv = 0xbeef2, time = 58 Entering mySwi. myEnd1: pEnv = 0xfeeb1, time = 72 myEnd2: pEnv = 0xfeeb2, time = 80 Deleting mySwi. myDelete1: pEnv = 0xc0de1, time = 92 myDelete2: pEnv = 0xc0de2, time = 102 myTask exiting ... Entering myIdleFunc(). |
![](http://img0.ph.126.net/uxo9kHYlmkG8lmNKngkppA==/6631483381097707827.jpg)
基于TI-RTOS的CC2650DK开发(7)---软件中断相关推荐
- 基于TI AM335x创龙开发板的快速体验
着手体验的是创龙TL335x-IDK,这个板子的特点如下: 基于 TI AM335x ARM Cortex-A8 CPU,主频可高达 1GHz,运算能力可高达 2000DMIPS,搭配DDR3,兼容 ...
- 基于TI AM5728 + Artix-7 FPGA开发板(DSP+ARM) 5G通信测试手册
前 言 本文主要基于我司TL5728F-EVM评估板 + 移远RM500Q 5G模块演示5G网络的功能. 本指导文档适用开发环境: Windows开发环境:Windows 7 64bit.Window ...
- 基于TI AM335x创龙开发板U-Boot编译
分享一下基于广州创龙TL335x-IDK开发板的U-Boot编译.希望能帮助上你. 板子特点如下: 基于 TI AM335x ARM Cortex-A8 CPU,主频可高达 1GHz,运算能力可高 ...
- 基于TI Davinci架构的双核嵌入式应用处理器OMAPL138开发入门(TI达芬奇双核开发资料 [
基于TI Davinci架构的双核嵌入式应用处理器OMAPL138开发入门 一.简介 TI的达芬奇架构嵌入式应用处理器使用DSP与ARM结合的非对称多核结构,当然现在也有管脚全兼容的单核.本文要介绍的 ...
- 创龙基于TI AM335x ARM Cortex-A8 CPU,主频高达1GHz开发板规格书,用于电力控制
TL335x-EVM是由广州创龙基于TI ARM Cortex-A8而设计的工业级开发板.它为用户提供了SOM-TL335x核心板的测试平台,用于快速评估SOM-TL335x核心板的整体性能. TL3 ...
- Zigbee通讯之开发篇(基于TI 的Z-Stack)
1.Zigbee协议和Z-Stack Zigbee协议和Z-Stack是什么关系?这可能是初学Zigbee同学想知道的问题.给大家举个例子吧,我们生活中使用的插排是要符合一定的标准的,现在国家标准 ...
- 基于TI AM5728(浮点双DSP C66x +双ARM Cortex-A15)的开发板
开发板简介 基于TI AM5728浮点双DSP C66x +双ARM Cortex-A15工业控制及高性能音视频处理器: 多核异构CPU,集成双核Cortex-A15.双核C66x浮点DSP.双核PR ...
- ESP8266基于WIN10+UBUNTU18.04的开发环境搭建(RTOS 3.2)(比较水)
ESP8266基于WIN10+UBUNTU18.04的开发环境搭建(RTOS v3.2) 软件基础环境参考 硬件环境参考 软件环境安装的详细内容 软件基础环境参考 WIN10家庭版1803的64位版本 ...
- 温故知新(一)——基于 RTOS 的软件开发理论
目录 前言 1 RTOS的特点 2 任务设计 2.1 任务的特性 2.2 任务划分的方法 2.2.1 设备依赖性任务 2.2.2 关键任务 2.2.3 紧迫任务 2.2.4 数据处理任务 2.2.5 ...
- 基于TI C55x架构的定点TMS320VC5509A音频专用DSP处理器开发板规格书
TL5509-EVM是一款基于广州创龙TI C55x架构的定点TMS320VC5509A低功耗核心板SOM-TL5509设计的高端DSP开发板,底板采用沉金无铅工艺的2层板设计,它为用户提供了SOM- ...
最新文章
- 2022-2028年中国联合办公行业深度调研及投资前景预测报告
- java thread isalive,《Java多线程编程核心技术(第2版)》 —1.4 isAlive()方法
- 今日头条 CEO 张一鸣:面试了 2000 个年轻人
- 边缘计算大热 AI芯片站上风口
- 在 Azure Resource Manager 中为虚拟机设置密钥保管库
- could not perform addBatch
- Node跨域cors模块,nodejs+express跨域
- 税友软件公司java面试_税友集团java面试题
- 关于数据库timestamp类型问题
- 2020-11-30 04_机器视觉中的特征提取与描述
- 二、Json对象、Json数组和Json字符串
- VGG16网络参数细节
- 电脑插入头戴式耳机后声音依然外放
- 邮件群发海外服务器,国内与国外在邮件群发营销中的差别
- mysql mpm_Zabbix Mysql Fpmmm(MPM)监控的教程
- 外贸独立站之Facebook广告
- 微信40029 code解决办法
- Python图像处理之透视变换
- LTV预估与留存曲线拟合:指数函数还是幂函数?
- shell 知:ola