非安全区代码调用安全区的代码,需要通过NSC的代码做中介。
1.代码存放位置与特点
NSC的代码,是在安全区的工程中"secure_nsc.c"文件中创建的。在这个文件中的创建函数,并且需要以CMSE_NS_ENTRY
作为前缀创建函数。如下面的代码所示。
CMSE_NS_ENTRY void SECURE_change_exit_secure(uint8_t flag)
{
if(flag == 0x30){
NVIC_DisableIRQ(EXTI13_IRQn);
HAL_EXTI_ConfigLineAttributes(EXTI_LINE_13,EXTI_LINE_NSEC);
NVIC_SetTargetState(EXTI13_IRQn);
NVIC_EnableIRQ(EXTI13_IRQn);
}else if(flag == 0x31){
NVIC_DisableIRQ(EXTI13_IRQn);
HAL_EXTI_ConfigLineAttributes(EXTI_LINE_13,EXTI_LINE_SEC);
NVIC_ClearTargetState(EXTI13_IRQn);
NVIC_EnableIRQ(EXTI13_IRQn);
}
}
CMSE_NS_ENTRY是编译器的一个保留字,原型为__attribute((cmse_nonsecure_entry)) 。这个关键字用于声明一个入口函数,这个入口函数就可以提供给非安全区的代码进行调用。
我们可以在这个入口函数中编写一些只能在安全区进行的操作,比如retarget中断,正如上面的代码所示,将EXIT13中断的执行函数从安全区切换到非安全区,或者反过来。
2.NSC的代码是怎么体现给非安全区的代码的
在安全区编译代码的时候会将"secure_nsc.c"编译成库,输出.o的文件。同时非安全区的代码引入其头文件,这样就可以调用"secure_nsc.c"文件中的函数了。
3.非安全区调用安全区的函数,能否传递参数和获取返回值
写在NSC的安全区代码是可以包含参数和返回值的。但是参数是有限制的,参数必须是通过寄存器传递的,而不能通过栈传递。所以函数的参数个数不能超过4个,而且数据不能过大,否则就会放到栈上,造成无法传递。为什么不能将栈中的数据传递呢?因为安全区和非安全的寄存器是隔离的,安全区和非安全区都有自己的SP寄存器,因此当从非安全区切换到安全区时,是不能访问到非安全区的栈顶指针的。
想传递多个参数怎么办?可以通过指针的形式传递一个数组或结构体。因为指针指向的是内存的区域,而且安全区是可以访问非安全区的数据的。
非安全区也是可以获得安全区代码的返回值的。