环境参数: eCos模版:redboot 硬件平台: STM32F103ZET6
1、reset实现的函数调用流程
reset命令对应的函数是:
packages/redboot/current/src/main.c
void do_reset(int argc, char *argv[]) { diag_printf("... Resetting."); CYGACC_CALL_IF_DELAY_US(2*100000); diag_printf("\n"); CYGACC_CALL_IF_RESET(); diag_printf("!! oops, RESET not working on this platform\n"); }
CYGACC_CALL_IF_RESET();宏定义在:
packages/hal/common/current/include/hal_if.h
#define CYGACC_CALL_IF_RESET() CYGACC_CALL_VV0(__call_if_reset_t*, CYGNUM_CALL_IF_RESET)() __call_voidVV0(CYGNUM_CALL_IF_RESET, __call_if_reset_t, void)
并最终调用了static void reset(void)函数:
packages/hal/common/current/include/hal_if.c
static __call_if_reset_t reset; static void reset(void) { CYGARC_HAL_SAVE_GP(); // With luck, the platform defines some magic that will cause a hardware // reset. #ifdef HAL_PLATFORM_RESET HAL_PLATFORM_RESET(); #endif #ifdef HAL_PLATFORM_RESET_ENTRY // If that's not the case (above is an empty statement) there may // be defined an address we can jump to - and effectively // reinitialize the system. Not quite as good as a reset, but it // is often enough. goto *HAL_PLATFORM_RESET_ENTRY; #else #error " no RESET_ENTRY" #endif CYG_FAIL("Reset failed"); CYGARC_HAL_RESTORE_GP(); }
由此函数可知,reset的实现有两种方式:
(1)调用平台提供的HAL_PLATFORM_RESET()函数
(2)直接goto到程序入口地址HAL_PLATFORM_RESET_ENTRY处:
#define HAL_PLATFORM_RESET_ENTRY &hal_reset_vsr
hal_reset_vsr指向程序的主入口函数void hal_reset_vsr( void ),关于该函数,注释说明如下:
//========================================================================== // Main entry point // // Enter here from reset via slot 1 of VSR table. The stack pointer is // already set to the value in VSR slot 0, usually the top of internal // SRAM.
下面着重讲下第一种(1)复位方式,它涉及到芯片的具体操作。
2、reset实现涉及到的硬件操作
参考以下内容时对照该图:
AIRCR:应用程序中断及复位控制寄存器
由AIRCR寄存器定义可知,在Cortex-M3中,有两种方式可以执行软件复位:
(1)通过置位AIRCR的VECTRESET(AIRCR[0]):
该方式下,复位的作用范围覆盖整个CM3,但不影响内核以外的所有其他电路,所以片上外设和其他电路不受影响。
(2)通过置位AIRCR的SYSRESETREQ(AIRCR[2]):
该方式下,复位操作波及整个芯片上的电路。
3、reset在redboot上的实现
HAL_PLATFORM_RESET()宏实现如下:
#define HAL_PLATFORM_RESET() { HAL_WRITE_UINT32(CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_AIRCR, CYGARC_REG_NVIC_AIRCR_KEY| CYGARC_REG_NVIC_AIRCR_SYSRESETREQ ); for(;;); }
HAL_WRITE_UINT32( _register_, _value_ )作用是往制定的寄存器@ _register_赋值@ _value_
在此:
_register_ = CYGARC_REG_NVIC_BASE+CYGARC_REG_NVIC_AIRCR = 0xE000E000 + 0xD0C = 0xE000ED0C _value_ = CYGARC_REG_NVIC_AIRCR_KEY | CYGARC_REG_NVIC_AIRCR_SYSRESETREQ = (0x5FA<<16) + (1<<2)
0x5FA是访问该寄存器的钥匙。
for(;;);死循环保证后面的指令不被执行到。