芯片复制采用svc模式可以将SDK(API)和Application分离, 也可以省略很多重复的代码,比如在bootload中用到了usb, 然后在application中想复用的话,可以用svc
原理: 类似软件中断,中添加了一个软件中断源,通过中断源表明调用的函数接口
芯片复制源程序如下:
- #ifndef NRF_SVC__
- #define NRF_SVC__
- #ifdef SVCALL_AS_NORMAL_FUNCTION
- #define SVCALL(number, return_type, signature) return_type signature
- #else
- #ifndef SVCALL
- #if defined (__CC_ARM)
- #define SVCALL(number, return_type, signature) return_type __svc(number) signature
- #elif defined (__GNUC__)
- #define SVCALL(number, return_type, signature) \
- _Pragma("GCC diagnostic ignored \"-Wunused-function\"") \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \
- __attribute__((naked)) static return_type signature \
- { \
- __asm( \
- "svc %0\n" \
- "bx r14" : : "I" (number) : "r0" \
- ); \
- } \
- _Pragma("GCC diagnostic pop")
- #elif defined (__ICCARM__)
- #define PRAGMA(x) _Pragma(#x)
- #define SVCALL(number, return_type, signature) \
- PRAGMA(swi_number = number) \
- __swi return_type signature;
- #else
- #define SVCALL(number, return_type, signature) return_type signature
- #endif
- #endif // SVCALL
- #endif // SVCALL_AS_NORMAL_FUNCTION
- #endif // NRF_SVC__
- void C_SVC_Handler(uint8_t svc_num, uint32_t * p_svc_args)
- {
- switch (svc_num)
- {
- case NRF_SEC_SVC_HASH:
- p_svc_args[0] = nrf_sec_hash((nrf_sec_data_t *) p_svc_args[0],
- (uint8_t *) p_svc_args[1],
- (nrf_sec_hash_func_t) p_svc_args[2]);
- break;
- case NRF_SEC_SVC_VERIFY:
- p_svc_args[0] = nrf_sec_verify((nrf_sec_data_t *) p_svc_args[0],
- (nrf_sec_ecc_point_t *) p_svc_args[1],
- (nrf_sec_ecc_signature_t *) p_svc_args[2],
- (nrf_sec_algo_t) p_svc_args[3]);
- break;
-
- default:
- p_svc_args[0] = NRF_ERROR_SVC_HANDLER_MISSING;
- break;
- }
- }