This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Soft Reset

I have an STM32F205 processor in a battery backed up circuit.
The battery is normally non connected, it can be connected via switch or GPIO.
The problem is that if the IWD (Independent Watch Dog) fires whilst the system is running on battery, the GPIO goes low, the battery gets disconnected and the system turns off.

So, I'd like a soft reset, leave the GPIO high, but reset everything else.
The IWG will fire after 16 seconds, I've setup a standard timer to run for 15 seconds, both get reset by the standard WD kick.
This all works fine, But I now need the timer ISR to do this software reset.

I've tried duplicating the standard 'Reset_Handler' as 'SoftReset_Handler', adding SP init at start. This works ok, runs through SystemInit, runs through main().
Then it encounters os_sys_init_user() that calls os_set_env() all registers and all values in os_set_env() are the same between hard and soft reset with hard, BX LR ends up in SVC_Handler with soft, BX LR ends up in HardFaultHandler

Within the ISR, I've disabled all interrupts in NVIC and cleared all pending interrupts in NVIC.

Because I'm kicking this off from ISR, I'm in 'Handler' Mode instead of 'Thread' Mode, but this is the only difference I can see, other than doing something horrible like putting address of SoftResetHandler on stack and returning, I can't find a way of changing this.

Any ideas?

Parents
  • Here is the "Secret Sauce" (I am not suggesting that it is a good idea to do this, but I have done much worse.)

    __asm void _SoftwareReset(uint32_t VectorBaseAddress)
    {
        LDR     R4,[R0]         ; R4 is the Reset Stack Pointer
        LDR     R5,[R0,#4]      ; R5 is the Reset Program Counter
        MOV     R0,#0           ;
    
        MOV     R6, #0x01000000 ; xSPR Just thumb mode set
        STMDB   R4!, {R5,R6}    ; push xSPR and PC
        MOV     R1, R0
        MOV     R2, R0
        MOV     R3, R0
        STMDB   R4!, {R0-R3}   ;
        STMDB   R4!, {R0,R1}   ; Push 6 "0"'s. Restore R0-R4,R12,LR to 0
        MOV     SP, R4         ; Starting Stack Pointer -32.
                               ; Will Be Start Stack Pointer after RTI
        MVN     LR, #:NOT:0xFFFFFFF9; // Return to Thread mode using MSP
        BX      LR             ; Now do it
    }
    

    Call this from your "Terminal" Handler as when this is done, you will be at Running the Reset Handler In Thread Mode with the Stack pointer equal to the VectorBase address 0 value. The state of the devices when you call this routine will still be intact.You probably want to disable as many as you can, maybe even just leaving the 1 GPIO port that you still need.

    Before you call this, you should disable all interrupts and clear pending interrupts.

    Turn off the SysTick and and Running Timers. They will get re enabled after reset.

    You can put different values for the Saved R0-R3,R12,LR and use these to indicate that it is a software reset.

    ; You may want to add something like this at the start of the Reset Handler
    
     LDR    R4,=WasSoftwareReset
     LDR    R4,[R4]
     STR    R0,[R4] ; Store Startup R0 in Global WasSoftwareReset variable.
                      will be 0 if not your routine
                      What ever you set it too if it was
    

Reply
  • Here is the "Secret Sauce" (I am not suggesting that it is a good idea to do this, but I have done much worse.)

    __asm void _SoftwareReset(uint32_t VectorBaseAddress)
    {
        LDR     R4,[R0]         ; R4 is the Reset Stack Pointer
        LDR     R5,[R0,#4]      ; R5 is the Reset Program Counter
        MOV     R0,#0           ;
    
        MOV     R6, #0x01000000 ; xSPR Just thumb mode set
        STMDB   R4!, {R5,R6}    ; push xSPR and PC
        MOV     R1, R0
        MOV     R2, R0
        MOV     R3, R0
        STMDB   R4!, {R0-R3}   ;
        STMDB   R4!, {R0,R1}   ; Push 6 "0"'s. Restore R0-R4,R12,LR to 0
        MOV     SP, R4         ; Starting Stack Pointer -32.
                               ; Will Be Start Stack Pointer after RTI
        MVN     LR, #:NOT:0xFFFFFFF9; // Return to Thread mode using MSP
        BX      LR             ; Now do it
    }
    

    Call this from your "Terminal" Handler as when this is done, you will be at Running the Reset Handler In Thread Mode with the Stack pointer equal to the VectorBase address 0 value. The state of the devices when you call this routine will still be intact.You probably want to disable as many as you can, maybe even just leaving the 1 GPIO port that you still need.

    Before you call this, you should disable all interrupts and clear pending interrupts.

    Turn off the SysTick and and Running Timers. They will get re enabled after reset.

    You can put different values for the Saved R0-R3,R12,LR and use these to indicate that it is a software reset.

    ; You may want to add something like this at the start of the Reset Handler
    
     LDR    R4,=WasSoftwareReset
     LDR    R4,[R4]
     STR    R0,[R4] ; Store Startup R0 in Global WasSoftwareReset variable.
                      will be 0 if not your routine
                      What ever you set it too if it was
    

Children
No data