- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Labels:
-
PSoC 5LP
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Welcome in the forum.
Easiest solution would be to write the reset cause into eeprom and check its contents at startup.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Bob,
That is a solution that I thought of as well but I was trying to avoid using the eeprom.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sander,
If programming EEPROM seems annoying, there is a ready-to-use component to do so:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Coincidentally I was studying and writing a sample for
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
About the sample program
schematic
pins
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