|
1、SWI
软件中断作为底层接口,使用不同的功能号区分不同的功能函数。用软中断作为操作系统的底层接口就需要在 C 语言中使用 SWI 指令。也就是说: 引用:
[blockquote]软件的上层应用,有时需要对系统进行一些底层操作,但是上层应用所使用的 C语言又无法进行这样的操作。所以,需要有一个接口,利用这个接口才能碰触到系统的底层,而这个接口就是--SWI 。SWI就像一个中间人,负责上层应用 和 操作系统底层之间传递一些命令与数据。[/blockquote]在 ADS 中,有一个关键字 __swi ,用它声明一个不存在的函数,调用这个函数就在调用这个函数的地方插入一条 SWI 指令,并且可以指定功能号。同时,这个函数也可以有参数和返回值,其传递规则同一般的函数。
比如声明这么一个函数:
__swi(0x02) void OS_ENTER_CRITICAL(void);
OS_ENTER_CRITICAL(void) --->这个函数在 C 中是不存在的。当你在 C 中调用这个函数时,那么就在调用的地方插入 SWI 0x02 这个指令。当编译器识别了这个指令后,并从功能号为 0x02 这里找到入口.
2、SWI 执行的过程是这样的
当执行了上面被 __swi 声明的函数后,开始调用 SWI,引发中断,程序从中断向量表处找到软中断的中断服务程序的入口处(同时也进入到管理模式)。SWI 中断处理程序是:SoftwareInterrupt
程序代码为:
LDR SP, StackSvc ; 重新设置堆栈指针
STMFD SP!, {R0-R3, R12, LR}
MOV R1, SP ; R1指向参数存储位置
MRS R3, SPSR
TST R3, #T_bit ; 中断前是否是Thumb状态
LDRNEH R0, [LR,#-2] ; 是: 取得Thumb状态SWI号
BICNE R0, R0, #0xff00
LDREQ R0, [LR,#-4] ; 否: 取得arm状态SWI号
BICEQ R0, R0, #0xFF000000
; r0 = SWI号,R1指向参数存储位置
CMP R0, #1
LDRLO PC, =OSIntCtxSw
LDREQ PC, =__OSStartHighRdy ; SWI 0x01为第一次任务切换
BL SWI_Exception
LDMFD SP!, {R0-R3, R12, PC}^
StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)
;因为是满递减,所以要-4.比如 SvcStackSpace =0x04, SVC_STACK_LEGTH = 3
;SvcStackSpace + SVC_STACK_LEGTH * 4 等于0x10, 减 4 后为 0x0c,如有数据
;进栈,则数据是写入0x0f,0x0e,0x0d,0x0c 这 4 个字节单元中. |
|