ARM Cortex-M内核软件中断触发方式

ARM Cortex-M内核软件中断触发方式

1. 背景

在嵌入式开发过程中,如果不是参与操作系统调度开发的,其实应该是较少使用软件中断的,或者在常规的驱动开发过程中,应该对使用软件中断应该是感觉到意外,因为明明可以直接执行相应的程序,为什么还要使用中断去执行。在正常的嵌入式开发过程中,确实很难会接触软件中断这一概念,更多的可能是用计时器来进行定时触发一些动作,或者也有可能借助外部中断软件触发的方式来做软中断,那本篇博客就简单探讨一下软件中断的作用和在STM32中有那些实现方式。

2. 软件中断之于操作系统

对于操作系统而言,最为核心的部分当然就是支持并发性,通过对task的调度,分时复用CPU资源来实现并发,操作系统将在Systick中断中发起对task的调度,但是并非是Systick一到,就应该立刻发起调度,因为这时如果,当前正处于cpu内核态,调度完线程,就会返回用户态,所以操作系统中,systick中是向一个低优先级的软件中断挂起一个请求,等到cpu回到用户态时,就会立刻进行task调度。操作系统中的软件中断,或者也可以称之为系统服务调用。比如8086汇编中的int 0x80,arm7中的swi,这里的swi其实就是software interrupt,arm7的swi和svc的地位其实是相同的,而且机器码也相同。这里的软件中断是用户为了向系统提出操作对应的硬件请求,而硬件的操作部分是位于系统内核态,所以用户就可以方便再用户态,调用所需要的硬件功能,而不必受限于当前的cpu权限,操作系统内核也无需担心用户误操作而引起系统瘫痪。

3. Cortex-M的软件中断

在Cortex-M系列中svc和swi不再一样,svc的被调用后,就需要cpu立刻执行,如果svc不能得到相应就会产生一个hardfault,所以像在svc中或者nmi中调用svc都会产生hardfault。swi,是一个和其他外设中断一样的地位,我们可以通过一些空闲的中断号或者是PendSV中断来是实现软件中断。

当然也有一些其他的软件中断实现方式,常见的软件触发中断方式如下。

  • 定时器方式触发,在STM32开发中,我们可以开启一个定时器,计时的count可以设置为0,也就是会立刻触发更新中断,然后在中断中关闭这个定时器,通过这种方式,我们也可以实现软件中断。

  • 外部中断软件触发,外部中断在配置和初始化后,也是可以手动触发的,在HAL库中,就有对应的接口函数可以做到,当然EXTI中也有寄存器SWIER可软件触发。

  • 在空闲中断号中设置软件中断,在Cortex-M系列内核中中断资源号应该有256,除去内核占用的16个中断号,按理应该还有240个中断资源号,但是并不是所有的芯片都实现这240个中断,在stm32f103c8t6中,仅有0-42中断号可用,43以上的中断号,并未实现在这mcu中。如果有空闲的中断号,或者不使用的外设中断号,我们可用将之作为软件中断,像普通中断一样,把这个中断设置优先级和使能中断后,我们可用通过向NVIC->STIR中写入中断号,来主动触发软件中断。

  • 使用SVC或者PendSV

    • 在操作系统中,SVC和PendSV往往是被操作系统给占用,用于调度task,所以不推荐在有操作系统的项目中使用这两个中断资源
    • 在裸机开发中,这两个中断资源往往是闲置的,非常推荐使用这两个中断资源,使用SVC中断,相当于使用临界区,而且通过汇编语句对CPU的合理设置我们可以将系统调用函数做出有返回值和入参的函数,这就使得SVC的可用性大大加强,PendSV,同样也是Cortex内核的保留中断号,但是他的优先级可自行设置,地位相当于普通软件中断,但是相比于软件中断,PendSV的中断号是固定的,这在项目之间进行移植带来了许多便利。
  • 普通外设中断手动触发,其实也是可以通过NVIC->STIR来模拟外设触发中断,执行相应的中断程序。

4. 总结

在通用操作系统中,软件中断作为用户态和内核态的桥梁,是用户调用系统服务的接口。而在嵌入式领域,在有操作系统的项目中软件中断的使用较少,由于有多线程并发操作,和互斥锁及信号量的使用,使得对于并发和全局资源的互斥访问,有更为方便的途径。在裸机项目开发中,软件中断的使用,可以看作中断并发的延申,以及中断之间以及主任务调配资源。这使得软件中断的使用有了一些其他的意义,我们甚至可以参照操作系统的方式使用软件中断,来调配系统任务,实现一个伪操作系统的概念。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32 CubeMX 中,配置 ADC 软件触发可以按照以下步骤进行: 1. 打开 STM32 CubeMX 软件,并选择您正在使用的 STM32 系列型号。 2. 在左侧的菜单栏中,找到“Analog”选项卡,然后选择“ADC”。 3. 在 ADC 配置界面中,选择您想要使用的 ADC 通道。 4. 在 ADC 配置界面中,找到“Regular Conversion”选项卡。 5. 在“Regular Conversion”选项卡中,启用“Software Trigger Conversion”的选项。 6. 在代码中,使用 HAL 库中的函数调用来启动 ADC 软件触发转换。 下面是一个简单的代码示例,用于启动 ADC 软件触发转换: ``` /* 定义 ADC 句柄 */ ADC_HandleTypeDef hadc; /* 启动 ADC 软件触发转换 */ HAL_ADC_Start(&hadc); ``` 需要注意的是,ADC 的初始化和配置也需要在代码中进行。例如,使用 HAL 库中的函数调用来初始化 ADC: ``` /* 初始化 ADC 句柄 */ hadc.Instance = ADC1; hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.ScanConvMode = DISABLE; hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc.Init.LowPowerAutoWait = DISABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.NbrOfConversion = 1; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc.Init.DMAContinuousRequests = DISABLE; hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; hadc.Init.OversamplingMode = DISABLE; if (HAL_ADC_Init(&hadc) != HAL_OK) { Error_Handler(); } ``` 请根据您的需求进行相应的 ADC 初始化和配置,并使用 HAL 库中的函数调用来启动 ADC 软件触发转换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值