Perform Reset PSOC5 with a flag displaying a custom reset cause

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
user_352521
Level 1
Level 1

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

0 Likes
7 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Welcome in the forum.

   

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

   

 

   

Bob

0 Likes
user_352521
Level 1
Level 1

Hi Bob,

   

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

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

Sander,

   

If programming EEPROM seems annoying, there is a ready-to-use component to do so:

   

http://www.cypress.com/forum/psoc-community-components/myeeprom-component-saverecall-application-set....

0 Likes
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

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

0 Likes

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!

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

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.name) {

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

            break ;

        }

        i++ ;

    }

    return( command_list.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.name) {

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

        print(str) ;

        print(command_list.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

0 Likes