本帖最后由 whong0951 于 2020-4-17 11:19 编辑
因为产品需要通过classb安全认证,所以这两天在把st的 X-CUBE-CLASSB库往工程里添加,因为我们产品使用的是stm105芯片,按照官网说明的X-CUBE-CLASSB version 2.2.0 supports the STM32L0, STM32L1, STM32L4, STM32L4+, STM32F0, STM32F1, STM32F2, STM32F3, STM32F4 and STM32F7 Series
下载了2.2.0版本的库,移植后进行调试时遇到了一些奇怪的问题,我在这里汇总一下:
1.代码优化问题
我把库的源代码抽出有影响部分的放在下面
- #define init_control_flow() CtrlFlowCntInv = ~(CtrlFlowCnt = 0uL)
- #define control_flow_call(a) CtrlFlowCnt += (a)
- #define control_flow_resume(a) CtrlFlowCntInv -= (a)
- /*--------------------------------------------------------------------------*/
- /*------------------- CPU registers and flags self test --------------------*/
- /*--------------------------------------------------------------------------*/
- /* Initialization of counters for control flow monitoring */
- init_control_flow();
- control_flow_call(CPU_TEST_CALLER);
- /* WARNING: all registers destroyed when exiting this function (including
- preserved registers R4 to R11) while excluding stack pointer R13) */
- if (STL_StartUpCPUTest() != CPUTEST_SUCCESS)
- {
- #ifdef STL_VERBOSE_POR
- printf("Start-up CPU Test Failure\n\r");
- #endif /* STL_VERBOSE_POR */
-
- FailSafePOR();
- }
- else /* CPU Test OK */
- {
- control_flow_resume(CPU_TEST_CALLER);
-
- #ifdef STL_VERBOSE_POR
- printf(" Start-up CPU Test OK\n\r");
- #endif /* STL_VERBOSE_POR */
- }
-
函数STL_StartUpCPUTest() 功能是直接对r0~r12寄存器赋值0~12再读回,确认寄存器没有问题,但是在函数返回时却没有将寄存器的值还原。在-O3优化下,在执行control_flow_call(CPU_TEST_CALLER);时会将CtrlFlowCntInv 的地址存入r4寄存器中,但是r4寄存器的值会在执行STL_StartUpCPUTest() 后发生改变,导致执行到control_flow_resume(CPU_TEST_CALLER);时会直接对地址0x0000 0004进行赋值操作,产生HardFault。
2.对函数的返回结果检查问题
在进行RAM测试时,程序
-
- /*--------------------------------------------------------------------------*/
- /* --------------------- Variable memory functional test -------------------*/
- /*--------------------------------------------------------------------------*/
- #ifdef STL_EVAL_MODE
- /* LED_VLM On for debug purposes */
- BSP_LED_On(LED_VLM);
- #endif /* STL_EVAL_MODE */
-
- /* no stack operation can be performed during the test */
- __disable_irq();
-
- /* WARNING: Stack is zero-initialized when exiting from this routine */
- if (STL_FullRamMarchC(RAM_START, RAM_END, BCKGRND) != SUCCESS)
- {
- #ifdef STL_VERBOSE_POR
- /* restore interrupt capability */
- __enable_irq();
对函数STL_FullRamMarchC()的返回结果进行检查时没有使用自定义的枚举类型,而是文件“stm32f1x.h”中的枚举类型
- typedef enum
- {
- SUCCESS = 0U,
- ERROR = !SUCCESS
- } ErrorStatus;
但是函数STL_FullRamMarchC()内的返回结果却是
- STL_FullRamMarchC
- MOVS R4, #0x1 ; Test success status by default
- __FULL_ERR
- MOVS R4,#0 ; error result
- __FULL_RET
- MOVS R0,R4
- BX LR ; return to the caller
与前面枚举结果的定义正好相反,导致检查成功时返回的却是错误的结果,令人疑惑的是这里if (STL_FullRamMarchC(RAM_START, RAM_END, BCKGRND) != SUCCESS)的处理方式与前文 if (STL_StartUpCPUTest() != CPUTEST_SUCCESS)并不一致,明明之前会使用自定义的枚举类型进行检查,到这里怎么又偷懒了?
很难理解一个用于安全认证的库会这么不严谨,我都开始怀疑它真的可以保证产品的安全性能么,还有就是这种安全认证库是否可以直接修改?修改后安全认证还有没有效果?
|