RL-RTX SVC 函数: unprivileged模式下运行的任务如何修改要求privileged权限的寄存器

问题: I have a problem to use NVIC_EnableIRQ when Keil RL-RTX is running. If I call NVIC_EnableIRQ before starting a first task, it work, but if NVIC_EnableIRQ is calling in a task HardFault_Handler happen.

说明:当RTX配置为任务在unprivileged模式下运行时,在任务内直接修改要求privileged权限(即写寄存器的代码必须运行在特权模式下)的寄存器会导致HardFault。SVC函数常用于在任务中修改要求privileged权限的寄存器(通常是系统配置有关的寄存器)。

以下是摘自《RL-ARM User's Guide》的SVC函数的用法:

SVC Functions

Software Interrupt (SVC) functions run in Privileged Handler Mode of the Cortex-M core. SVC functions accept arguments and can return values. The functions are used in the same way as other functions, however, differences are hidden to the user. The ARMCC compiler handles the differences and generates code instructions to call SVC functions. SVC functions are called by executing the SVC instruction. When executing SVC instructions, the controller changes to the Privileged Handler Mode.

Interrupts are not disabled in this mode. To protect SVC function from interrupts, you need to include the disable/enable intrinsic functions __disable_irq() and __enable_irq() in your code.

You can use SVC functions to access protected peripherals, for example, to configure NVIC and interrupts. This is required if you run tasks in unprivileged (protected) mode and you need to change interrupts from the task.

If you want to use SVC functions in your RTX kernel project, you need to:

  1. Copy the SVC_Table.s file to your project folder and include it into your project.
    This file is located in the \Keil\ARM\RL\RTX\SRC\CM folder.
  2. Declare a function with a __svc(x) attribute. Use the first SVC number, starting from 1, that is free.
    void __svc(1)  inc_5bit (U32 *cp);
    
  3. Write a function implementation and convert the function name into a __SVC_x function name. This name is referenced later by the linker from SVC_Table.s module. You need also to disable/enable interrupts.
    void __SVC_1            (U32 *cp) {
      /* A protected function to increment a 5-bit counter. */
      __disable_irq();
      *cp = (*cp + 1) & 0x1F;
      __enable_irq();
    }
    
  4. Add the function __SVC_x to the SVC function table in the SVC_Table.s module.

    First import it from other modules:
    ; Import user SVC functions here.
                    IMPORT  __SVC_1
    
    then add a reference to it into the table:
    ; Insert user SVC functions here. SVC 0 used by RTL Kernel.
                    DCD     __SVC_1                 ; user SVC function
    
  5. Your SVC function should now look like this:
    void __svc(1)  inc_5bit (U32 *cp);
    void __SVC_1            (U32 *cp) {
      /* A protected function to increment a 5-bit counter. */
      __disable_irq();
      *cp = (*cp + 1) & 0x1F;
      __enable_irq();
    }
    

 Note

  • SVC function 0 is reserved for the RTX kernel.
  • Do not leave gaps when numbering SVC functions. They must occupy a continuous range of numbers starting from 1.
  • SVC functions can still be interrupted.
  • RTX must be initialized before SVC functions are called.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值