XMC4700: Restart during communication with Hibernate-domain cause failure in MIRRSTS

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

cross mob
rst
Level 3
Level 3
First solution authored Welcome!
Hi!

I am developing an application for the XMC4700. My application configures the hibernation domain. To do this, it makes 3 writes to 3 registers:
  SCU.HCU.OSCSICTRL = B0;
SCU.HCU.OSCULCTRL = 0;
SCU.HCU.HDCR = 1 << 6 | 1 << 12 | 13 << 16 | 0 << 20;

After that, the content of MIRRSTS becomes equal to: 0xA8. Everything is correct.
After that (as data is transferred to the hibernation domain), the bits of the MIRRSTS register are sequentially reset to 0 one after the other. When all data has been transmitted, then MIRRSTS becomes == 0. Everything is correct.
It takes approximately 1.373 * 3 ms.

But! If make a software reset (System reset or WDT reset) while the contents of MIRRSTS are still not equal to 0 (transmit to the hibernation domain has not finished yet), then after that, at the start of the application, the MIRRSTS register contains the value == 0x10 !!!
And if then execute 3 writes of above registers (see above), then MIRRSTS becomes == 0xBB.
According to the ref.manual, this is an invalid value (bits 0 and 4 must always be 0)!
Also: this value is permanently fixed in the register MIRRSTS. Its bits are not cleared to 0! This means that it is impossible to work with the hibernation domain after that.
In such situation the MIRRSTS register can only be cleared using a PowerOnReset (other types of resets do not clear it).
There is nothing in the Errata Sheet on this subject.

How to solve this problem?
0 Likes
1 Solution
LinglingG_46
Moderator
Moderator
Moderator
500 solutions authored 1000 replies posted 10 questions asked
1: Please follow the Appnote to deal the Hibernate:
https://www.infineon.com/dgdl/DEV_XMC4000_Hibernate_v1_0.pdf?fileId=db3a30433e78ea82013e7f10964707df
2: The HIbernate Mode control register located in the Hibernate Control Unit can be accessed via mirror registers.
Before writing to any of the registers it is required to check if the corresponding status bits in the SCU_MIRRSTS register indicate
that a new access can be accepted.
3: From section "Store Contex Data in Retention Memory", we give the guide that it should be wating “do {
}
while ( SCU_GENERAL->MIRRSTS & \
(SCU_GENERAL_MIRRSTS_RTC_TIM0_Msk | SCU_GENERAL_MIRRSTS_RTC_TIM0_Msk1)); ”
4: So if the software happens during store data in retention Memory, the below way as you said:
"By now I have figure out that these sticked busy-bits in MIRRSTS it is possible to clear using bit "Hibernate Reset" HIBRS (in reg. SCU.RCU.RSTSET / SCU.RCU.RSTCLR).
But such cleaning unfortunately turns off the RTC-watch."
5: I think the right way is to avoid the unexpected software during the "Store Contex Data in Retention Memory" instead of breaking our documentation requirements.

View solution in original post

0 Likes
6 Replies
rst
Level 3
Level 3
First solution authored Welcome!
Is there any solution to this problem? Or not?

By now I have figure out that these sticked busy-bits in MIRRSTS it is possible to clear using bit "Hibernate Reset" HIBRS (in reg. SCU.RCU.RSTSET / SCU.RCU.RSTCLR). But such cleaning unfortunately turns off the RTC-watch. :(:(:(
Which is very bad and does not fit for me (RTC-watch may stop and real time will be lost).
Does anyone know a good solution? Really no one faced such a problem???
0 Likes
LinglingG_46
Moderator
Moderator
Moderator
500 solutions authored 1000 replies posted 10 questions asked
As my understanding:
When operate the hibernate domain, the MIRRSTS register will be changed by hardware.
If software reset happens when the MIRRSTS not zero, the only way to let the MIRRSTS to zero is to reset the hibernate domain. Just like you said you configure the corresponding bit.
0 Likes
rst
Level 3
Level 3
First solution authored Welcome!
GLLing wrote:
If software reset happens when the MIRRSTS not zero, the only way to let the MIRRSTS to zero is to reset the hibernate domain.

But in this case, I will lose the contents of the RTC (which contain real time). 😞
0 Likes
LinglingG_46
Moderator
Moderator
Moderator
500 solutions authored 1000 replies posted 10 questions asked
Could you give me a simple steps to reproduce your issue?

I want to confirm that: now the only issue you want to resolve is that the WDT reset happens in the MIRRSTS not equally to zero.

Could you accept that I terminate hibernate operation when receiving WDT pre-warning interrupt, waiting the MIRRSTS to reset before WDT reset?
0 Likes
rst
Level 3
Level 3
First solution authored Welcome!
GLLing wrote:
Could you give me a simple steps to reproduce your issue?

See main()-function:
#define B0  0x00000001ul
#define B1 0x00000002ul
#define B2 0x00000004ul
#define B3 0x00000008ul
#define B4 0x00000010ul
#define B5 0x00000020ul
#define B6 0x00000040ul
#define B7 0x00000080ul
#define B8 0x00000100ul
#define B9 0x00000200ul
#define B10 0x00000400ul
#define B11 0x00000800ul
#define B12 0x00001000ul
#define B13 0x00002000ul
#define B14 0x00004000ul
#define B15 0x00008000ul
#define B16 0x00010000ul
#define B17 0x00020000ul
#define B18 0x00040000ul
#define B19 0x00080000ul
#define B20 0x00100000ul
#define B21 0x00200000ul
#define B22 0x00400000ul
#define B23 0x00800000ul
#define B24 0x01000000ul
#define B25 0x02000000ul
#define B26 0x04000000ul
#define B27 0x08000000ul
#define B28 0x10000000ul
#define B29 0x20000000ul
#define B30 0x40000000ul
#define B31 0x80000000ul

enum {
RTC_STATE_OFF = 0,
RTC_STATE_INI = 1
};
static u8 volatile rtcState = RTC_STATE_OFF;
//Init Hibernation domain
void HIBinit()
{
#if INTERNAL_WDT
enum {SCU_HCU_HDCR = B6 | B12 | 13 << 16 | 0 << 20};
#else //INTERNAL_WDT
enum {SCU_HCU_HDCR = B6 | 0 << 16 | 0 << 20};
#endif //INTERNAL_WDT
uint i = RTC_STATE_INI;
if (!(SCU.PCU.PWRSTAT & B0)) {
SCU.PCU.PWRSET = B0;
i = RTC_STATE_OFF;
}
SCU.RCU.RSTSET = B8;
if (i == RTC_STATE_OFF || SCU.MIRRSTS || (SCU.RCU.RSTSTAT & B9)) {
SCU.RCU.RSTSET = B9;
i = SCU.RCU.RSTSET;
SCU.RCU.RSTCLR = B9;
i = SCU.RCU.RSTCLR;
i = RTC_STATE_OFF;
}
while (SCU.MIRRSTS);
if (SCU.HCU.OSCSICTRL != B0 || SCU.HCU.OSCULCTRL || SCU.HCU.HDCR != SCU_HCU_HDCR) i = RTC_STATE_OFF;
SCU.HCU.HDCLR = B0 | B1 | B2 | B3;
SCU.HCU.OSCSICTRL = B0;
SCU.HCU.OSCULCTRL = 0;
SCU.HCU.HDCR = SCU_HCU_HDCR;
rtcState = i;
RTC.MSKSR = 0;
RTC.CLRSR = RTC.RAWSTAT;
}

/*
//Waiting for all busy bits in SCU.MIRRSTS to be cleared (with timeout).
static void WaitMIRRSTS_Alt()
{
#define WAITMAX 0.1 //[sec] max. waiting time for clearing all busy bits in SCU.MIRRSTS
for (u32 i = GetCpuTimer(); SCU.MIRRSTS; ) if (GetCpuTimer() - i > (u32)(WAITMAX * CPUCLK_MH)) break;
#undef WAITMAX
}
*/

static void ResetPrepareAlt()
{
// WaitMIRRSTS_Alt();
SCU.RCU.RSTCLR = B0;
IntCpuDis();
FaultCpuDis();
__DSB();
}

//Reset MC via NVIC.AIRCR.
__noreturn void ResetCoreAlt()
{
ResetPrepareAlt();
NVIC.AIRCR = 0x5FA << 16 | B2;
while (1);
}

//Reset MC via WDT.
__noreturn void ResetWdtAlt()
{
ResetPrepareAlt();
SCU.CCU.CLKSET = B5;
PeripheralOn(SCU_PERIPH_WDT);
WDT.CTR = B0;
__DSB();
WDT.SRV = B0;
while (1);
}

__noreturn void main()
{
FaultCpuDis();
IntCpuDis();
BSPinit();
FaultCpuEna();
InitHCRC();
sysTimer = 0;

#ifdef LOG
LogInit(LOG_RATE);
#endif

uint j = SCU.RCU.RSTSTAT;
if (j != B3 && j != B5) {
//executes after power on. Branch 1.
LogsCR0(COL_PURPLE "Restarted will be later.");
while (!LogEmptyOut0()) WDItoggleWin();
HIBinit();
ResetCoreAlt();
//ResetWdtAlt();
}
//executes after ResetCoreAlt(). Branch 2.
if (j = SCU.MIRRSTS) {
//Branch 3.
LogCR0(COL_RED "SCU.MIRRSTS = " COL_BLACK " %08X." COL_TEAL " Wait...", j);
while (SCU.MIRRSTS);
}
...
}


After power on, the execution goes along the "Branch 1". Inside the function HIBinit(), a write to the hibernation domain is started. And immediately a system reset is done ResetCoreAlt() (without waiting for a reset SCU.MIRRSTS).
After a system reset, execution continues via "Branch 2". In this case, SCU.MIRRSTS != 0, execution goes along branch 3 and loops infinitely (since the SCU.MIRRSTS! = 0 frozen permanently).
The output stream of this loop:
=============================
5222.attach
=============================
From here it can be seen that when the device starts up, the SCU.MIRRSTS contains an invalid value == 0x10.
When trying to write something to the hibernation domain, other invalid bit values appear in the register. And it never becomes 0.

If uncomment the WaitMIRRSTS_Alt() inside the function ResetPrepareAlt(), then after that everything starts working normally.
Thus: performing a reset with the bits set inside the register SCU.MIRRSTS leads to a hang operations with SCU.MIRRSTS.

PS: Can replace the system reset with a reset through the WDT (ResetCoreAlt() -> ResetWdtAlt() inside "Branch 1"), nothing will change from this.
PPS: CPU operates at 144 MHz from internal flash.
0 Likes
LinglingG_46
Moderator
Moderator
Moderator
500 solutions authored 1000 replies posted 10 questions asked
1: Please follow the Appnote to deal the Hibernate:
https://www.infineon.com/dgdl/DEV_XMC4000_Hibernate_v1_0.pdf?fileId=db3a30433e78ea82013e7f10964707df
2: The HIbernate Mode control register located in the Hibernate Control Unit can be accessed via mirror registers.
Before writing to any of the registers it is required to check if the corresponding status bits in the SCU_MIRRSTS register indicate
that a new access can be accepted.
3: From section "Store Contex Data in Retention Memory", we give the guide that it should be wating “do {
}
while ( SCU_GENERAL->MIRRSTS & \
(SCU_GENERAL_MIRRSTS_RTC_TIM0_Msk | SCU_GENERAL_MIRRSTS_RTC_TIM0_Msk1)); ”
4: So if the software happens during store data in retention Memory, the below way as you said:
"By now I have figure out that these sticked busy-bits in MIRRSTS it is possible to clear using bit "Hibernate Reset" HIBRS (in reg. SCU.RCU.RSTSET / SCU.RCU.RSTCLR).
But such cleaning unfortunately turns off the RTC-watch."
5: I think the right way is to avoid the unexpected software during the "Store Contex Data in Retention Memory" instead of breaking our documentation requirements.
0 Likes