【.Net Micro Framework PortingKit - 07】NVIC中断处理

简介:       Cortex-M3的中断架构和以往的ARM7、ARM9、ARM11有了很大的区别,IRQ、FIQ的概念的已经消失,随之而来的是NVIC中断管理(支持最多256个中断优先级,128级抢断)及中断向量表。

      Cortex-M3的中断架构和以往的ARM7ARM9ARM11有了很大的区别,IRQFIQ的概念的已经消失,随之而来的是NVIC中断管理(支持最多256个中断优先级,128级抢断)及中断向量表。这个中断向量表似有相识之感,在当时大学时期学习DOS平台下的C语言开发的时候,在设置BIOS时钟中断的时候,就曾把中断函数的指针地址设置到时钟中断的入口地址区,以期中断发生的时候,执行指定的函数。当然不仅是时钟中断,其它的中断的处理方式也类似。在DOS那个时代,估计最高深一点的编程就是程序驻留和钩子函数(姑且把修改中断地址以截获信息的这一类函数为钩子函数吧),以此看来,Cortex-M3的中断架构倒是借鉴了BIOS的中断处理机制。

ARM公司大力推出Cortex-M3系列CPU核,一改往日的命名方式,并且内存映射、中断架构等以往因不同芯片厂商而多变的架构,变得统一起来。看来ARM其志不小,想要在嵌入式领域开发技术层面一统江湖。这种统一意义巨大,大大降低了嵌入式软件移植的难度,不知道今后这种改变,能否在嵌入式领域中催生出类似昔日PC领域的王者组合:操作系统(Microsoft+CPUIntel)。

.Net Micro Framework的整个底层架构是建立在ARM7ARM9基础之上的,而Cortex-M3的出现,大大的冲击了这一架构,这也是在MF3.0源码中就已经出现了CortexM3的目录,而到现在官方无一款可支持的Cortex-M3开发板的原因。因为要改动的代码太多,要保持ARM7ARM9Cortex-M3的代码统一太难。

所以在这里我单立了一个目录,大力进行修改而不遗余力(所谓不破不立),我觉得,这也是我们在一个划时代事物出现的面前,所应持有的态度和立场。

在第4<修改启动代码&重写向量表>中我们所写的中断向量表,我们要进行一番调整,以期支持动态加入中断函数的功能。

新的中断函数表,我们仅需预先填写前三项:(1 堆栈TOP地址,(2)复位地址,(3)不可屏蔽中断函数地址(NMIException)。VectorsTrampolines.s修改后的代码如下(和以前的代码相比,是不是简化了很多):

  EXPORT  ARM_Vectors

    IMPORT  StackTop

    IMPORT  EntryPoint

     IMPORT  NMIException

   

;********************************************************

    AREA |.text|, CODE, READONLY

 

    ;向量表

ARM_Vectors

         DCD  StackTop                   ; Top of Stack  栈顶

         DCD  EntryPoint                                    ; 复位

         DCD  NMIException

    ;...                            ; 向量表定位在 RAM中,由程序动态生成

    SPACE  384                     ; 预留空间 (76 - 3) * 4 = 292   

   

;*********************************************************

    END

 

其中SPACE 384的代码也可以不要,不过要确保Scatterfile_tools_mdk.xml文件中,如下项没有<FileMapping Name="*" Options="(SectionForFlashOperations)" />

  <ExecRegion Name="ER_RAM_RO" Base="0x20000000" Options="ABSOLUTE" Size="">

       <FileMapping Name="VectorsTrampolines.obj" Options="(+RO, +FIRST)" />

       <FileMapping Name="*" Options="(SectionForFlashOperations)" />

  </ExecRegion>

此外还有一个改进就是删除我们原先在/DeviceCode/Targets/Native/CortexM3/DeviceCode目录下的建立的VectorsHandler_Temp库文件,这个库我们已经不需要了,我们随时根据需要,动态的在中断向量表中写入我们所需的中断函数地址。

好了,在/DeviceCode/Targets/Native/CortexM3/DeviceCode目录中建立NVIC目录(相当于以前体系的INTC),在写具体代码之前,我们现在写下如下代码(大概),这是对NVIC相关寄存器的描述。

struct CortexM3_NVIC

{  

    static const UINT32 c_Base = 0xE000E100;

    //中断使能 置位复位

    /****/ volatile UINT32 SETENA[2];

    UINT32  RESERVED0[30];

    /****/ volatile UINT32 CLRENA[2];

    UINT32  RSERVED1[30];

   

    //中断悬起 置位复位

    /****/ volatile UINT32 SETPEN[2];

    UINT32  RESERVED2[30];

    /****/ volatile UINT32 CLRPEN[2];

    UINT32  RESERVED3[30];

   

    //中断活动状态

    /****/ volatile UINT32 ACTIVE[2];

    UINT32  RESERVED4[62];

 

    //中断优先级

    /****/ volatile UINT8 PRI[60];

   

    static const UINT32 c_IRQ_MAX_INDEX = 16+60;

   

    //IRQ Index Table   

    static const UINT32 c_IRQ_Index_NMI = 0x2;

    static const UINT32 c_IRQ_Index_HardFault = 0x3;

    static const UINT32 c_IRQ_Index_MemManage = 0x4;

    static const UINT32 c_IRQ_Index_BusFault = 0x5;

    static const UINT32 c_IRQ_Index_UsageFault = 0x6;

    //7,8,9,A NULL

    static const UINT32 c_IRQ_Index_SVC = 0xB;

    static const UINT32 c_IRQ_Index_DebugMonitor = 0xC;

         //D NULL

    static const UINT32 c_IRQ_Index_PendSVC = 0xE;

    static const UINT32 c_IRQ_Index_SysTick = 0xF; 

    //--

    static const UINT32 c_IRQ_Index_WWDG = 0x10; 

    static const UINT32 c_IRQ_Index_PVD = 0x11;

    static const UINT32 c_IRQ_Index_TAMPER = 0x12; 

     //

    static const UINT32 c_IRQ_Index_DMA2_Channel3 = 0x4A;

    static const UINT32 c_IRQ_Index_DMA2_Channel4_5 = 0x4B;   

 

    //IRQ Priority index Table

    static const UINT32 c_IRQ_Priority_NULL = 0xFF;

    static const UINT32 c_IRQ_Priority_Leve0 = 0x00;

    static const UINT32 c_IRQ_Priority_Leve1 = 0x10;

    static const UINT32 c_IRQ_Priority_Leve2 = 0x20;

     //

    static const UINT32 c_IRQ_Priority_Leve14 = 0xE0;

    static const UINT32 c_IRQ_Priority_Leve15 = 0xF0;

};

 

NVIC目录下建立三个文件:NVIC.cppNVIC.hdoNetMF.proj

NVIC.cpp的核心内容如下:

void CortexM3_NVIC_Driver::Initialize()

{

   //外部中断

   CortexM3_NVIC &NVIC = CortexM3::NVIC();

   NVIC.CLRENA[0]=0xFFFFFFFF;   //清外部中断

   NVIC.CLRENA[1]=0xFFFFFFFF;

   NVIC.CLRPEN[0]=0xFFFFFFFF;

   NVIC.CLRPEN[1]=0xFFFFFFFF;

 

   //系统中断

   CortexM3_SCB &SCB = CortexM3::SCB();  

   SCB.ICSR = 0x0A000000;

   SCB.VTOR = (UINT32)&IMAGE_RAM_RO_BASE;   // 重定向中断向量表

   SCB.AIRCR = CortexM3_SCB::AIRCR_VECTKEY_MASK | CortexM3_SCB::NVIC_PriorityGroup_1;

   SCB.SCR = 0x00000000;

   SCB.CCR = 0x00000000;

   SCB.SHCSR = 0x00000000;  //系统中断使能位

   SCB.CFSR = 0xFFFFFFFF;  

   SCB.HFSR = 0xFFFFFFFF;

   SCB.DFSR = 0xFFFFFFFF;

 

   //优先级设定

   IRQ_VECTORING *IsrVector = s_IsrTable;

   for(int i = 0; i < CortexM3_NVIC::c_IRQ_MAX_INDEX; i++)

   {

     //

   }

}

//激活中断

BOOL CortexM3_NVIC_Driver::ActivateInterrupt(UINT32 Irq_Index,UINT32 ISR)

{

    InterruptEnable(Irq_Index);

    UINT32 *p= (UINT32*)&IMAGE_RAM_RO_BASE + Irq_Index;

         *p=ISR;       

    return TRUE;

}

//关闭中断

BOOL CortexM3_NVIC_Driver::DeactivateInterrupt(UINT32 Irq_Index)

{

    InterruptDisable(Irq_Index);

    return TRUE;

}

 

BOOL CortexM3_NVIC_Driver::InterruptEnable(UINT32 Irq_Index)

{

    if(Irq_Index<16)

    {

       CortexM3_SCB &SCB = CortexM3::SCB(); 

             if(Irq_Index==CortexM3_NVIC::c_IRQ_Index_MemManage)  //4

                           SCB.SHCSR |= 0x1<<16;

             if(Irq_Index==CortexM3_NVIC::c_IRQ_Index_BusFault)   //5

                           SCB.SHCSR |= 0x1<<17;

        if(Irq_Index==CortexM3_NVIC::c_IRQ_Index_UsageFault) //6

                           SCB.SHCSR |= 0x1<<18;

                   if(Irq_Index==CortexM3_NVIC::c_IRQ_Index_SysTick)    //15

                   {

                      CortexM3_SysTick &SysTick= CortexM3::SysTick();   

                SysTick.CTRL |= CortexM3_SysTick::CTRL_TICKINT | CortexM3_SysTick::CTRL_ENABLE;

                   }

          

    }

         else

         {

            CortexM3_NVIC &NVIC = CortexM3::NVIC();

            int irq=Irq_Index-16;

            NVIC.SETENA[irq/32] = 0x1 << (irq % 32);

         }

    return TRUE;

}

BOOL CortexM3_NVIC_Driver::InterruptDisable(UINT32 Irq_Index)

{

    //

    return TRUE;

}

在其中,我们为了适应新架构的需要,增加了一个中断函数连接接口,声明如下:

BOOL CPU_INTC_ActivateInterruptEx(UINT32 Irq_Index, UINT32 ISR)

{

         return CortexM3_NVIC_Driver::ActivateInterrupt(Irq_Index, ISR);

}

原先的(如下),已经废弃不用(暂保留)。

BOOL CPU_INTC_ActivateInterrupt(UINT32 Irq_Index, HAL_CALLBACK_FPN ISR, void *ISR_Param)

{

    return FALSE;

}

 

以上代码中最重要的莫过于“激活中断”函数中的如下代码

UINT32 *p= (UINT32*)&IMAGE_RAM_RO_BASE + Irq_Index;

*p=ISR;   

简单的两行代码,便实现了中断函数的动态注册(在GPIO和串口驱动中我们将详细讲这一点)。

此外,最后要记得在NativeSample.proj添加如下内容:

  <ItemGroup>

    <RequiredProjects Include="$(SPOCLIENT)/DeviceCode/Targets/Native/CortexM3/DeviceCode/Nvic/dotNetMF.proj" />

    <DriverLibs Include="nvic.$(LIB_EXT)" />

  </ItemGroup>

前一两个礼拜没有写相关文章,是因为代码修改量很大,一直在调试相关功能。目前GPIO、串口等功能均已经调试通过,所以后续的几天,我便一一介绍它们的实现过程。

相关文章
|
关系型数据库 MySQL 数据库
找不到请求的 .Net Framework Data Provider。可能没有安装
做的一个项目,框架为.net framework 数据库为mysql 出现如标题错误 检查是否安装mysql、是否安装mysql connector net 笔者是因为没有安装后者mysql connector net 下载地址: [mysql connector net](https://downloads.mysql.com/archives/c-net/ "mysql connector net") 笔者安装截图如下: ![请在此添加图片描述](https://developer-private-1258344699.cos.ap-guangzhou.myqcloud.com/c
248 0
|
2月前
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
49 1
|
2月前
|
开发框架 缓存 监控
NET Framework 到 .NET 5/6 的迁移是重大的升级
本文详细介绍了从 .NET Framework 4.8 迁移到 .NET 5/6 的过程,通过具体案例分析了迁移策略与最佳实践,包括技术栈评估、代码迁移、依赖项更新及数据库访问层的调整,强调了分阶段迁移、保持代码可维护性及性能监控的重要性。
58 3
|
2月前
|
机器学习/深度学习 编解码 算法
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
《nnU-Net: 自适应框架用于基于U-Net的医学图像分割》是一篇2018年的论文,发表在Nature上。该研究提出了一种自适应的医学图像分割框架nnU-Net,能够自动调整模型的超参数以适应不同的数据集。通过2D和3D U-Net及级联U-Net的组合,nnU-Net在10个医学分割数据集上取得了卓越的性能,无需手动调整。该方法强调数据增强、预处理和训练策略等技巧,为医学图像分割提供了一个强大的解决方案。
82 0
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
本文讨论了在基于.NET 6和.NET Framework的WinForms项目中添加图表控件的不同方法。由于.NET 6的WinForms项目默认不包含Chart控件,可以通过NuGet包管理器安装如ScottPlot等图表插件。而对于基于.NET Framework的WinForms项目,Chart控件是默认存在的,也可以通过NuGet安装额外的图表插件,例如LiveCharts。文中提供了通过NuGet添加图表控件的步骤和截图说明。
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
|
4月前
|
开发框架 缓存 前端开发
实战.NET Framework 迁移到 .NET 5/6
从.NET Framework 迁移到.NET 5/6 是一次重要的技术革新,涵盖开发环境与应用架构的全面升级。本文通过具体案例详细解析迁移流程,包括评估现有应用、利用.NET Portability Analyzer 工具识别可移植代码、创建新项目、逐步迁移代码及处理依赖项更新等关键步骤。特别关注命名空间调整、JSON 序列化工具更换及数据库访问层重构等内容,旨在帮助开发者掌握最佳实践,确保迁移过程平稳高效,同时提升应用性能与可维护性。
146 2
|
4月前
|
开发框架 JSON 监控
实战指南:从 .NET Framework 迁移到 .NET 5/6 的策略与最佳实践
【8月更文挑战第28天】从 .NET Framework 迁移到 .NET 5/6 是一次重要的技术升级,涉及开发环境与应用架构的改进。本文通过具体案例分析,介绍迁移策略与最佳实践,帮助开发者顺利完成转变。
88 1
|
4月前
|
缓存 程序员
封装一个给 .NET Framework 用的内存缓存帮助类
封装一个给 .NET Framework 用的内存缓存帮助类
|
5月前
|
开发框架 前端开发 JavaScript
基于SqlSugar的数据库访问处理的封装,支持.net FrameWork和.net core的项目调用
基于SqlSugar的数据库访问处理的封装,支持.net FrameWork和.net core的项目调用
|
4月前
|
XML JSON 程序员
总结一下 .NET FrameWork 和 .NET Core 创建的项目的不同点
总结一下 .NET FrameWork 和 .NET Core 创建的项目的不同点
103 0