7 Replies Latest reply on Mar 2, 2020 11:39 PM by MoTa_728816

    Perform Reset PSOC5 with a flag displaying a custom reset cause

    user_352521

      Dear Cypress community,

         

      I want to software-reset my device at a certain point and provide a custom reset cause (which can be used as a flag for a part of the initialization code). My idea was to use RESET_SR0: 0x400046FA or CYREG_PHUB_CFGMEM23_CFG1: 0x400076BC for this because bit 4 (0x10) seems to be unused. The code I wrote to do this is simple:

         

      void sw_reset_with_custom_reset_cause() {
          uint8 currentValue = CY_GET_REG8(CYREG_RESET_SR0);
          currentValue |= 0x10;
          CY_SET_REG8 (CYREG_RESET_SR0, currentValue);
          CySoftwareReset();
      }

         

      The problem is that it does not work as expected (reset cause is always 0x20 after calling the SW reset). My hope would of course be to get a reset cause that is equal to 0x30. I've tried with both above mentioned registers but with no luck. 

         

      What am I doing wrong here?

         

      Best regards,

         

      Sander

        • 1. Re: Perform Reset PSOC5 with a flag displaying a custom reset cause
          JoMe_264151

          Welcome in the forum.

             

          Easiest solution would be to write the reset cause into eeprom and check its contents at startup.

             

           

             

          Bob

          • 2. Re: Perform Reset PSOC5 with a flag displaying a custom reset cause
            user_352521

            Hi Bob,

               

            That is a solution that I thought of as well but I was trying to avoid using the eeprom.

            • 3. Re: Perform Reset PSOC5 with a flag displaying a custom reset cause
              JoMe_264151

              I was trying to avoid using the eeprom Why? it is there, it is not too difficult to use and it survives a power loss. You may even record with time-stamps any errors etc.

                 

               

                 

              Bob

              • 5. Re: Perform Reset PSOC5 with a flag displaying a custom reset cause
                BoTa_264741

                Though a bit late, there seems to be another way to preserve variables between resets:

                   

                http://www.cypress.com/blog/psoc-hacker-blog/recovering-watchdog-reset

                • 6. Re: Perform Reset PSOC5 with a flag displaying a custom reset cause
                  StKr_1203736

                  I am trying to do something similar.. I would like to be able to detect a watchdog timeout, so that I can distinguish between power-on reset and watchdog timeout reset.

                   

                  I put this code at the start of main()

                  // NOTE we cannot read the RESET_SR0 register directly, because it is clear-after-read
                  // and it is read as part of the reboot process
                  uint8 ResetReason = CyResetStatus;      // save cause of reset for later processing

                   

                  ResetReason is ALWAYS 0xA0, which indicates Software Reset + GPIO1

                   

                  I added this code so that a subsequent startup execution could detect 'we have already been here..'

                  // if this is a COLD start, change the Reset Reason for subsequent resets to indicate WATCHDOG
                  // CyResetStatus does not correctly indicate Watchdog resets, so we us CY_RESET_GPIO0 to indicate completion of cold start
                  ResetReason |= CY_RESET_GPIO0;
                  CY_SET_REG8(CYREG_RESET_SR0, ResetReason);

                     

                  // update the stored copy of RESET_SR0
                  CyResetStatus = CY_GET_REG8(CYREG_RESET_SR0);

                   

                  Now CyResetStatus is 0xC0

                   

                  Subsequent code causes the system to hang, and watchdog reset occurs.

                  But the result is as above: ResetReason is 0xA0, despite the absence of any software resets.

                   

                  Is there ANY way to do this? EEPROM is NOT suitable, because I need the "we have been here before" state to be cleared by a power cycle. And because I cannot distinguish between power cycle resets and watchdog resets, I cannot clear the flag in software.

                   

                  I have searched the Cypress website and 'Community' extensively, and found two types of information:

                  1. direction to existing documentation that is clearly wrong

                  2. unanswered questions

                   

                  Consider this not-too-helpful text from the System Reference Manual, Preservation of Reset Status:

                   

                  To retain user-defined status that persists through many resets, use the CY_RESET_GP0 and
                  CY_RESET_GP1 bits in the RESET_SR0 register. The CyResetStatus variable is used to obtain value of
                  these bits after a device reset. These bits are used by Bootloader and Bootloadable projects and cannot
                  be used by user.

                   

                  This contains a blatant contradition: You can use these bits, except that you can't.

                   

                  Someone please provide some meaningful insight here!

                  • 7. Re: Perform Reset PSOC5 with a flag displaying a custom reset cause
                    MoTa_728816

                    Hi,

                     

                    Coincidentally  I was studying and writing a sample for

                    PSoC 5LP WDT Reset Detection

                     

                    What I learned are

                    (1) To reference the value of RESET_SR0

                    We need to use CYREG_PHUB_CFGMEM23_DFG1

                    (2) To modify the reset value (for gpsw_s = bit[7:6])

                    We need to modify RESET_SR0 which is defined as CYREG_RESET_SR0 (= 0x400046FA).

                     

                    And with this question, I think that we should use Bit7 and Bit6 as these bits are dedicated for the "General purpose status for user software".

                     

                    So I modified my previous sample and added usr0, usr1, usr2, usr3 functions.

                    usr1 sets bit6,

                    usr2 sets bit7,

                    usr3 sets both bit6 and bit7.

                     

                    As these bits are sticky we need to manually clear them, so I prepared

                    usr0 clear all bits in RESET_SR0.

                     

                    I created my sample with CY8CKIT-059.

                     

                    Tera Term log

                    At first I used "cls" to clear my screen then typed "help" to show the commands.

                    Then I typed

                    "soft" to cause the software reset.

                    "wdt" to cause watch dog reset

                    "usr1" to set custom bit (bit6) and software reset, the result showed Software Reset and USER01

                    "usr0" to clear custom bit and cause software reset, the result showed only Software Reset

                    "usr3" to set both bit6 and bit7 and software reset, the result showed both Software Reset, USER01 and USER10

                    "usr0" to clear them again

                    010-TeraTerm-log.JPG

                    About the sample program

                     

                    schematic

                    011-schematic.JPG

                    pins

                    012-pins.JPG

                    main.c

                    ===============

                    #include "project.h"

                    #include "stdio.h"

                    #include "tty_utils.h"

                     

                    #ifndef PM_WDT_CFG

                    #define PM_WDT_CFG (uint8_t *)0x40004383

                    #endif

                    #ifndef PM_WDT_CR

                    #define PM_WDT_CR (uint8_t *)0x40004383

                    #endif

                     

                    #define BIT_CTW_RESET  0x80

                    #define BIT_WDR_EN     0x10

                     

                    typedef void (*func_ptr)(void) ;

                     

                    typedef struct _cmd_func_st_ {

                        char *name ;

                        func_ptr func ;

                        char *description ;

                    } command_func_type ;

                     

                    void do_help(void) ;

                    void do_software_reset(void) ;

                    void do_wdt(void) ;

                    void do_usr0(void) ;

                    void do_usr1(void) ;

                    void do_usr2(void) ;

                    void do_usr3(void) ;

                     

                    command_func_type command_list[] = {

                        { "help", do_help, "Help message" },

                        { "soft", do_software_reset, "Cause Software Reset" },

                        { "wdt",  do_wdt, "Start WatchDog" },

                        { "usr0", do_usr0, "Clear Custom Reset Bit(s)" },

                        { "usr1", do_usr1, "Custom Reset User 01" },

                        { "usr2", do_usr2, "Custom Reset User 10" },

                        { "usr3", do_usr3, "Custom Reset User 11" },

                        { "cls",  cls, "Clear Screen" },

                        { 0, 0, 0 },

                    } ;

                     

                    func_ptr get_func(char *cmd)

                    {

                        int i = 0 ;

                        while(command_list[i].name) {

                            if (strcmp(cmd, command_list[i].name) == 0) {

                                break ;

                            }

                            i++ ;

                        }

                        return( command_list[i].func ) ;

                    }

                     

                    void init_hardware(void)

                    {

                        CyGlobalIntEnable; /* Enable global interrupts. */

                        tty_init() ;

                    }

                     

                    void enable_wdt(void)

                    {

                       *PM_WDT_CFG |= BIT_WDR_EN ;

                    }

                     

                    void feed_wdt(void)

                    {

                        *PM_WDT_CR = 0x01 ;

                    }

                     

                    void do_command(char *cmd)

                    {

                        func_ptr func ;

                       

                        func = get_func(cmd) ;

                        if (func) {

                            func() ;

                        } else {

                            do_help() ;

                        }

                    }

                     

                    #define BIT_LVID_RESET  0x01

                    #define BIT_LVIA_RESET  0x02

                    #define BIT_HVIA_RESET  0x04

                    #define BIT_WDT_RESET   0x08

                    #define BIT_SOFT_RESET  0x20

                    #define BIT_USR01_RESET 0x40

                    #define BIT_USR10_RESET 0x80

                     

                    void print_reset_status(void)

                    {

                        uint8_t reset_status =     *((uint8_t *)CYREG_PHUB_CFGMEM23_CFG1) ;

                        snprintf(str, STR_BUF_LEN , "CYREG_PHUB_CFGMEM23_DFG1: 0x%02X : ", reset_status) ;

                        print(str) ;

                        if (reset_status & BIT_LVID_RESET) {

                            print("LVID ") ;

                        }

                        if (reset_status & BIT_LVIA_RESET) {

                            print("LVIA ") ;

                        }

                        if (reset_status & BIT_HVIA_RESET) {

                            print("HVIA ") ;

                        }

                        if (reset_status & BIT_WDT_RESET) {

                            print("WDT ") ;

                        }

                        if (reset_status & BIT_SOFT_RESET) {

                            print("Software Reset ") ;

                        }

                        if (reset_status & BIT_USR01_RESET) {

                            print("USER01 ") ;

                        }

                        if (reset_status & BIT_USR10_RESET) {

                            print("USER10 ") ;

                        }

                        print("\n\r") ;

                    }

                     

                    int main(void)

                    {

                        init_hardware() ;

                     

                        snprintf(str, STR_BUF_LEN, "Reset Test (%s %s)\n\r", __DATE__, __TIME__) ;

                        print(str) ;

                               

                        print_reset_status() ;

                       

                        prompt() ;

                        while(1) {

                            if (get_line()) {

                                do_command(str) ;

                                prompt() ;

                            }

                        }

                    }

                     

                    void do_help(void)

                    {

                        int i = 0 ;

                       

                        print("=== commands ===\n\r") ;

                        while(command_list[i].name) {

                            snprintf(str, STR_BUF_LEN, "%6s : ", command_list[i].name) ;

                            print(str) ;

                            print(command_list[i].description) ;

                            print("\n\r") ;

                            i++ ;

                        }

                        print("================\n\r") ;

                    }

                     

                    void do_software_reset(void)

                    {

                        CySoftwareReset() ;

                    }

                     

                    void do_wdt(void)

                    {

                        enable_wdt() ;

                    }

                     

                    void do_usr0(void)

                    {

                        *((uint8_t *)CYREG_RESET_SR0) = 0x00 ;

                        CySoftwareReset() ;

                    }

                     

                    void do_usr1(void)

                    {

                        *((uint8_t *)CYREG_RESET_SR0) = BIT_USR01_RESET ;

                        CySoftwareReset() ;

                    }

                     

                    void do_usr2(void)

                    {

                        *((uint8_t *)CYREG_RESET_SR0) = BIT_USR10_RESET ;

                        CySoftwareReset() ;

                    }

                     

                    void do_usr3(void)

                    {

                        *((uint8_t *)CYREG_RESET_SR0) = (BIT_USR10_RESET | BIT_USR01_RESET) ;

                        CySoftwareReset() ;   

                    }

                    ===============

                     

                    NOTE: I cheated by using my tty_utils library to make uart handling easier.

                    tty_utils a utility sample for CLI type program

                     

                    moto