.Net Micro Framework的中断处理机制相对比较简单,不支持中断嵌套,中断优先级功能的实现由相关硬件提供支持,软件层面仅仅进行相关优先级的设定即可。
下面以TI DM335开发板为例简单介绍一下相关技术细节(这里仅介绍普通中断IRQ)。
1 中断向量表
我们知道中断向量表一般默认的存放在内存0起始地址处。
先让我们在NativeSample或TinyCLR目录中找到Scatterfile_tools_xxx.xml文件,我们会发现在其中都会有如下这么一段文字:
<ExecRegion Name="ER_RAM_RO" Base="0x00000000" Options="ABSOLUTE" Size="0x1A000">
<FileMapping Name="VectorsTrampolines.obj" Options="(+RO, +FIRST)" />
</ExecRegion>
这是一个编译选项,告诉ARM编译器,连接时把VectorsTrampolines.obj的相关内容放在位置0处(我们可以用WinHex查看编译后的Bin文件,我们会发现Bin文件中最开始的内容就是中断向量表的内容)。
下面是VectorsTrampolines.s文件的汇编代码:
;**************************************************************************
IMPORT UNDEF_SubHandler
IMPORT ABORTP_SubHandler
IMPORT ABORTD_SubHandler
IMPORT IRQ_Handler ; from stubs.cpp
EXPORT ARM_Vectors
;**************************************************************************
AREA |.text|, CODE, READONLY
; ARM directive is only valid for ARM/THUMB processor, but not CORTEX
IF :DEF:COMPILE_ARM :LOR: :DEF:COMPILE_THUMB
ARM
ENDIF
ARM_Vectors
; RESET
RESET_VECTOR
b UNDEF_VECTOR
; UNDEF INSTR
UNDEF_VECTOR
ldr pc, UNDEF_SubHandler_Trampoline
; SWI
SWI_VECTOR
DCD 0xbaadf00d
; PREFETCH ABORT
PREFETCH_VECTOR
ldr pc, ABORTP_SubHandler_Trampoline
; DATA ABORT
DATA_VECTOR
ldr pc, ABORTD_SubHandler_Trampoline
; unused
USED_VECTOR
DCD 0xbaadf00d
; IRQ
IRQ_VECTOR
ldr pc, IRQ_SubHandler_Trampoline
; FIQ
; we place the FIQ handler where it was designed to go, immediately at the end of the vector table
; this saves an additional 3+ clock cycle branch to the handler
FIQ_Handler
IF :DEF: FIQ_SAMPLING_PROFILER
ldr pc,FIQ_SubHandler_Trampoline
FIQ_SubHandler_Trampoline
DCD FIQ_SubHandler
ENDIF
UNDEF_SubHandler_Trampoline
DCD UNDEF_SubHandler
ABORTP_SubHandler_Trampoline
DCD ABORTP_SubHandler
ABORTD_SubHandler_Trampoline
DCD ABORTD_SubHandler
; route the normal interupt handler to the proper lowest level driver
IRQ_SubHandler_Trampoline
DCD IRQ_Handler
;**************************************************************************
从中我们可以看出,当硬件触发IRQ中断时,跳转的最终位置为IRQ_Handler。
【疑问】中断向量表的内容最开始的时候一定是存放在Flash(或其它存储介质)中,它是如何被转移到内存0处的呢(当然调试时也可以通过调试器把中断向量表直接Download到内存中去)?
【解答】在FirstEntry.s汇编代码中有这么一句代码 “bl BootstrapCode”,BootstrapCode是一个子函数,该函数优先于“b BootEntry”执行,在BootstrapCode函数中又调用了一个子函数PrepareImageRegions,在PrepareImageRegions函数中我们就可以看到拷贝中断向量表的相关代码:
UINT32* src = (UINT32*)&LOAD_RAM_RO_BASE;
UINT32* dst = (UINT32*)&IMAGE_RAM_RO_BASE;
UINT32 len = (UINT32 )&IMAGE_RAM_RO_LENGTH + (UINT32)&Image$$ER_RAM_RW$$Length;
Prepare_Copy( src, dst, len );
注:FIQ_SAMPLING_PROFILER选项是没有定义的,所以在DM335开发板上支持FIQ是有问题的。
2 中断函数(IRQ_Handler)
中断向量表一经设置,则触发相关中断时,CPU会把PC指针指到相关的入口地址处,对IRQ中断来说,其入口地址就是IRQ_Handler。
对DM335平台,IRQ_Handler函数的内容如下:
void __irq IRQ_Handler(void)
{
DM335_INTC_Driver::IRQ_Handler();
}
void /*__irq*/DM335_INTC_Driver::IRQ_Handler(void)
{
DM335_INTC &pAic = DM335::INTC();
unsigned int index;
// set before jumping elsewhere or allowing other interrupts
SystemState_SetNoLock(SYSTEM_STATE_ISR);
SystemState_SetNoLock(SYSTEM_STATE_NO_CONTINUATIONS);
while(pAic.IRQENTRY != 0x0)
{
index = (pAic.IRQENTRY>>2) - 1;
if(index < 32)
pAic.IRQ0 |= 1 << index;
else
pAic.IRQ1 |= 1 << (index % 32);
s_IsrTable[index].Handler.Execute(); //执行对应的中断处理函数
}
SystemState_ClearNoLock(SYSTEM_STATE_NO_CONTINUATIONS); // nestable
SystemState_ClearNoLock(SYSTEM_STATE_ISR); // nestable
}
在中断函数执行之前,其实已经执行了中断寄存器的初始工作,比如根据需要打开或关闭(Enable/Disable)相关的中断,对我们的应用来说串口和USB的中断是要打开的,而DMA中断就是关闭的。此外根据你应用的需求,你也可以设置不同中断的优先级(0~7,其中0~1对应快速中断,对我们来说由于快速中断无效,所以中断的优先级最高可设为2)。
相同等级的中断同时来到,是谁来排序呢?
对DM335来说,是由硬件完成的,DM335提供一个寄存器IRQENTRY,IRQENTRY寄存器中存放的值,就是下一个要执行的中断号(要经过一定的换算),该寄存器就像一个队列的出队口,排好队的中断依次出列,直到IRQENTRY的值为0为止(表示当前队列中没有任何中断被触发)。
(当然我们也可以直接根据IRQ0和IRQ1中的值触发二级中断函数,但是这样来做,设定的中断优先级就没有任何意义了。)
这时候我们就可以根据不同的中断号,执行相对应的二级中断函数了。
那中断来了,程序是如何知道该执行那个二级中断函数呢?请看下一节内容就明白了。
3 中断连接函数
CPU_INTC_ActivateInterrupt函数是把硬件的中断号和要执行的中断函数联系起来,其原型是:
BOOL CPU_INTC_ActivateInterrupt(UINT32 Irq_Index, HAL_CALLBACK_FPN ISR, void *ISR_Param);
Irq_Index – 中断号(可根据相关硬件手册进行设定)
ISR – 该中断触发时所要执行的中断函数
ISR_Param –中断函数的入口参数(可以为空)
当然根据需要也可以断开这种连接,或关掉相应的中断,这些函数由于比较好理解,所以这里就不过多介绍了。
我们以USB驱动为例,简单介绍一下CPU_INTC_ActivateInterrupt函数的使用,在USB的初始化函数中,我们添加了如下代码:
CPU_INTC_ActivateInterrupt(DM335_INTC::c_IRQ_Index_USBINT, Global_ISR, NULL);
其中断函数Global_ISR的部分代码如下:
void DM335_USB_Driver::Global_ISR(void *Param)
{
DM335_USB &usb = DM335_USB::Type();
UINT32 endpoint = 0;
UINT32 tmp = usb.Base.INTSRCR;
usb.Base.INTCLRR = usb.Base.INTSRCR;
//在这里面就可以根据USB相关寄存器的值,确定那一个中断被触发了
// … …
}
这样一层一层,由根到枝,按图索骥,获知实际的中断,并最终执行相关的处理代码(如接收数据或发送数据等等)。
4 中断控制
在Porting Kit提供的样例代码中,我们会在中断函数中看到不少GLOBAL_LOCK(irq)代码,由于MF目前不支持中断嵌套,所以从某种意义上说,在中端函数中添加代码GLOBAL_LOCK(irq)是没有意义的(对IRQ中断来说,CPU在触发该中断时,就已经关闭了IRQ中断位,除非你在中断函数中又打开了,当然你这样做的目的一般就是支持中断嵌套了,这部分内容暂不在讨论之列)。
GLOBAL_LOCK是一个宏,其实现为:
#define GLOBAL_LOCK(x) SmartPtr_IRQ x
而SmartPtr_IRQ类的代码为:
class SmartPtr_IRQ
{
UINT32 m_state;
void* m_context;
public:
SmartPtr_IRQ(void* context=NULL) { m_context = context; Disable(); }
~SmartPtr_IRQ() { Restore(); }
…
}
void SmartPtr_IRQ::Disable()
{
UINT32 Cp;
UINT32 Cs;
__asm
{
MRS Cp, CPSR
ORR Cs, Cp, #0x80
MSR CPSR_c, Cs
}
m_state = Cp;
}
void SmartPtr_IRQ::Restore()
{
UINT32 Cp = m_state;
if((Cp & DISABLED_MASK) == 0)
{
ASSERT_SYSTEM_IRQ_MODE(Cp);
__asm
{
MRS Cp, CPSR
BIC Cp, Cp, #0x80
MSR CPSR_c, Cp
}
}
}
由以上代码可知,定义SmartPtr_IRQ的实例的同时,就执行了构造函数,也就是执行了Disable函数(关闭IRQ中断)。换句话说,GLOBAL_LOCK(irq)代码的作用就是,在irq的生命周期内关闭IRQ中断。
相信,如果MF的后续版本开始支持中断嵌套,该部分的内容才会变的复杂。
5 补充说明
MF应用程序(C#)中的中断(或事件函数)其实和我们这章内容所说的中断不是一会事,由以上内容我们可以了解到,中断函数串序执行,所以每一个中断函数执行时间尽量短,否则整个系统的效率便会大大降低。所以我们上层的事件函数是不可能直接勾连在中端函数内,因为在实际的应用中,我们非常有可能在事件函数中执行很多耗时的操作的。实际上TinyCLR代码对这两部分进行了一定得隔离处理,等我们有时间在一一剖析相关的实现机理。
除了中断函数被执行外,对嵌入式应用来说剩下的也就是一个Main函数(对MF来说就是ApplicationEntryPoint)和一个while循环了。对于我们的TinyCLR来说其实就是一个在相对简陋的操作系统上的一个精彩应用而已:
void ApplicationEntryPoint()
{
CLR_SETTINGS clrSettings;
memset(&clrSettings, 0, sizeof(CLR_SETTINGS));
clrSettings.MaxContextSwitches = 50;
#if !defined(BUILD_RTM)
clrSettings.PerformGarbageCollection = false;
clrSettings.PerformHeapCompaction = false;
#endif
clrSettings.WaitForDebugger = false;
ClrStartup( clrSettings );
#if !defined(BUILD_RTM)
debug_printf( "Exiting.\r\n" );
#else
::CPU_Reset();
#endif
}
分享到:
相关推荐
飞思卡尔KEA128的C#代码可能包括了初始化配置、中断处理、定时器管理、串口通信以及电机控制算法等功能。 在文件名称列表中,"飞思卡尔KEA128电磁能跑的代码"很可能包含了一系列源文件,如.c或.cs,这些文件包含了...
在本文中,我们将深入探讨如何使用C#语言和Winform技术来驱动...开发者可以通过研究这个源码学习到如何利用WIA或MF API与摄像头交互,实现视频预览、图像捕获等功能,这对于开发涉及多媒体处理的桌面应用非常有价值。
6. **异常处理**:为了保证系统的稳定运行,需要对可能出现的错误进行捕获和处理,防止程序意外中断。 7. **日志记录**:记录系统的操作和异常,方便后期的调试和问题追踪。 8. **权限管理**:根据不同的角色设置...
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
前端分析-2023071100789
基于kinect的3D人体建模C++完整代码.cpp
搞机工具箱10.1.0.7z
GRU+informer时间序列预测(Python完整源码和数据),python代码,pytorch架构,适合各种时间序列直接预测。 适合小白,注释清楚,都能看懂。功能如下: 代码基于数据集划分为训练集测试集。 1.多变量输入,单变量输出/可改多输出 2.多时间步预测,单时间步预测 3.评价指标:R方 RMSE MAE MAPE,对比图 4.数据从excel/csv文件中读取,直接替换即可。 5.结果保存到文本中,可以后续处理。 代码带数据,注释清晰,直接一键运行即可,适合新手小白。
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水模拟dem-sph-fem耦合 ,基于ANSYS LSDyna; 滑坡入水模拟; DEM-SPH-FEM 耦合,基于DEM-SPH-FEM耦合的ANSYS LSDyna滑坡入水模拟
auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
复件 复件 建设工程可行性研究合同[示范文本].doc
13考试真题最近的t64.txt
好用我已经解决报错问题
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!
auto_gptq-0.4.2-cp38-cp38-win_amd64.whl
自动立体库设计方案.pptx
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!