Main Site Documentation

Problem w/ Interrupt.Install(WDT_IRQn, ... in RLP


#1

This problem relates to my previous post: More Complete G120 Custom Watchdog

I managed to capture, in RLP, the watchdog warning interrupt, which triggers WDINT. However for some reason the systems hangs up after the interrupt is triggered.

I spent long hours trying to figure out the problem but I gave up.

So any help from the community will be greatly appreciated.

My Managed Code:

namespace SWB
{
    public class Program
    {
        public static void Main()
        {
            Debug.Print("System Started.");
            RLP_ Rlp     = new RLP_();
            WDT Watchdog = new WDT(30); // secs - A minimum of 30 secs is required.
            Thread.Sleep(Timeout.Infinite);
        }
    }
}

    public class RLP_
    {
        public RLP_() // Constructor
        {
            // Get ELF file into byte array from resources
            byte[] elf_file = Resources.GetBytes(Resources.BinaryResources.RLP);

            // This method loads the "Load Region" into RAM
            RLP.LoadELF(elf_file);

            // This method Initializes BSS region to zeros using the default addresses declared in the GHI RLP examples linker script
            // "__bss_start__" and "__bss_end__"
            RLP.InitializeBSSRegion(elf_file);
            //or in a customized way
            //RLP.InitializeBSSRegion(elf_file, "__bss_start__", "__bss_end__");

            RLP.Procedure Init = RLP.GetProcedure(elf_file, "Init");
            RLP.Procedure StartLEDBlink = RLP.GetProcedure(elf_file, "StartLEDBlink");

            // We don't need elf_file anymore
            elf_file = null;
            Debug.GC(true);

            GHI.Premium.Native.RLP.RLPEvent += new RLPEventHandler(RLP_Event);

            Init.Invoke();
            // Make sure to connect the correct pin number here!!!
            StartLEDBlink.Invoke((uint)Pin.P1_5, false);
        }

        static void RLP_Event(uint v, DateTime TimeStamp) // Invoked when WDINT is triggred in RLP
        {
            Watchdog2.ResetCounter();
            Debug.Print("Event from RLP - v: " + v);
        }

My Native Code:

// https://www.ghielectronics.com/downloads/man/Library_Documentation_v4.2/Premium/html/84e9776b-381c-0c5e-94c6-0e7f9f9de231.htm

 #include "incl\type.h"
 #include "incl\LPC177x_8x.h"
 #include "incl\RLP.h"

RLP_Task Task1;
unsigned pin;
unsigned state;

void WDINT_ISR(void* arg)
{
	RLPext->PostManagedEvent(55);
}

void Init(void)
{
	unsigned r = RLPext->Interrupt.Install(WDT_IRQn, WDINT_ISR, NULL);
	RLPext->PostManagedEvent(r);
	r = RLPext->Interrupt.IsEnabled(WDT_IRQn);
	RLPext->PostManagedEvent(r);
	//r = RLPext->Interrupt.Enable(WDT_IRQn); // No need, already enabled as verified above
	//RLPext->PostManagedEvent(r);
}

// Used only for testing purpose
void Task1Callback(void *arg)
{
	// change the pin's state
	state = !state;
	RLPext->GPIO.WritePin(pin, state);

	// reschedule after 500 milliseconds
	RLPext->Task.ScheduleTimeOffset(&Task1, 500 * 1000); // us
}

// Used only for testing purpose
int StartLEDBlink(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
	pin = *(unsigned char*)args[0];
	state = *(unsigned char*)args[1];

	RLPext->GPIO.EnableOutputMode(pin, state);

	RLPext->Task.Initialize(&Task1, Task1Callback, 0, RLP_FALSE);

	// start the task
	RLPext->Task.Schedule(&Task1);

	return 0;
}

#2

I modified my WDTINT_ISR as follows, but it made no difference!
Thinking that not clearing the flag will cause the interrupt to be re-triggered again and again!

void WDINT_ISR(void* arg)
{
	// clear WDINT - Bit 3: WDINT (Watchdog interrupt flag. Set when the timer reaches the value in WDWARNINT)
	LPC_WDT->WARNINT |= 0x08; // set bit 3 to 1 (cleared by writing a 1 to this bit)
	RLPext->PostManagedEvent(55);
}

#3

الله أكبر ولله الحمد (God Almighty is great and I am thankful to him)

Behold! My stupid Bug was found and annihilated!

The last modification I made was in the right direction, but I used the wrong register!

The corrected code:

void WDINT_ISR(void* arg)
{
	// For testing purpose
	//RLPext->Task.Abort(&Task1);
	//RLPext->GPIO.WritePin(pin, state);
	//RLPext->Delay(100000); // 100ms
	//state = !state;
	//RLPext->GPIO.WritePin(pin, state);
 
	// Reset the WDT to prevent reoccurrence of this ISR and to give us more time to signal managed code to do graceful shutdown
	// Give us only 5 more seconds before RESET
	LPC_WDT->TC = 5 * 125000; // 1000 / 4 * 500 = 125000
	LPC_WDT->FEED = 0xAA;
	LPC_WDT->FEED = 0x55;
 
	// clear WDINT - MOD Bit 3: WDINT (Watchdog interrupt flag. Set when the timer reaches the value in WDWARNINT)
	LPC_WDT->MOD |= 0x08; // set bit 3 to 1 (cleared by writing a 1 to this bit)
 
	// Another way to do same as above (writing itself in the flag that is set to 1 will clear it!)
	//uint32_t n = LPC_WDT->MOD;
	//LPC_WDT->MOD = n;

In case you couldn’t see it quickly: I used WARNINT instead of the MOD register to clear the WDINT flag!

I suspected that the interrupt was repeatedly invoked and very quickly, which gave the appearance of system lockup because my LED stopped flashing/toggling. What made it easy to prove this, not having access to native code debugger yet, is the commented code at the top of the WDINT_ISR. The Native code is setup to flash/toggle the LED on board of the G120HDR every 500ms to indicate that the native code is live and running! The inserted code, but commented out now, at the top of the ISR stops the flashing timer for good and then it flashes the LED at 100ms rate instead, but just once. So if the ISR is repeatedly invoked the LED will flash at 100ms, which is faster than the original/nominal 500ms rate. So I knew there was something wrong with my clearing of the WDINT flag!

Modified:
For Version 2 of the entire code/project check: More Complete G120 Custom Watchdog + RLP

Happy Coding!


#4

Man!

I am the only one talking to myself in this post!

I must be loosing it!

Or everyone else is talking to himself/herself too?!

My Dad once told me: nowadays half of Earth’s population are insane and the other half are on the way!

Einstein also said: Insanity is doing the same thing over and over again and expecting different results!

:slight_smile: :smiley: ;D :frowning: :open_mouth: ??? ::slight_smile: :stuck_out_tongue:


#5

Have you seen arguing with myself? :slight_smile: I think it is the best

Good job on finding the problem


#6

Thanks Gus!

Can you please give me your opinion on my request of the recent codeshare post before I waste anymore time unnecessarily?

Warm Regards


#7

Link?


#8

@ Sambo - Even though the watchdog code is MCU dependent; your higher level code (C#) for the event and corresponding set-up in your C code, is a great example! – Definitely something I’ve seen other folks struggle with. Now we have a great place to point them to. Thanks!


#9

@ Gus - it’s @ the end of my post#2 above!

You see how I know who’s reading to the end?

:think:


#10

@ Jeff - Thanks for the complement!

But you must be inferring by your statement: “Even though the watchdog code is MCU dependent” that an external WDT is more reliable than an internal one! I happen to disagree. Now if you a mean a soft watchdog implemented with pure software (issue a restart with an instruction) then we do agree!

I don’t see but one advantage of an external WDT over an internal one, which is implemented on-board of almost all recent advanced MCUs! Most hardware designers are not aware of it, and if they are, they will not use that advantage for a simple reason I’ll come to it in a minute!

The WDT in the NXP LPC178x/7x of G120 is no exception! I’ve used external WDTs in the past and they all dependent on the MCU to frequently probe them indicating that it’s up and running! The only difference is that MCU manufacturers, in effort of more integration, brought in this vital external hardware module/peripheral, placed it on-board of the MCU, and threw in some extra features.

Hardware wise, an on-board WDT is totally independent of the MCU. Once it kicks in, it performs a hard reset to the CPU as if you pressed the reset button and activated the RESET input! In the case of the LPC178x/7x of G120, it has its own independent CLK; once enabled, it can’t be accidentally disabled by s/w. It can generate a warning interrupt so one can perform a graceful shutdown: closing files and flushing them to permanent storage.

The only real advantage I know of is that an external watchdog can be designed, as I am planning with my current design, not just to hard reset the CPU but also to recycle the power of the entire system. Obviously, this is dangerous to opened files, exactly like on a PC/laptop! Where we sometimes or the O/S have to check the HD(s) for corruption after an abrupt shutdown, especially when based on FAT/FAT32.

NT format and recent MS operating systems made have progressed a long way in that regard. I don’t see lost clusters/corruption as much. As a matter of fact since NT, MS Windows rarely freezes compared to old MSDOS and early Windows (those of my age remember the 3 finger salute: CTRL+ALT+DEL!). BTW MS has just decided to make their early versions open source:
Microsoft makes source code for MS-DOS and Word for Windows available to public

I know Apple/Macintosh is another story but never used them much; so I can’t give an opinion. I hear a lot, however, that they have had much more robust OSes than MS! My iPhone is a proof!

Sorry for the long story and to make it short: My objective is to design a reliable commercial instrument based on GHI’s hardware and MS .NETMF! My current project is a low cost but precise and robust Air Quality Monitoring System.

For many years, as an EECE my background have been developing around intel / TI / Freescale, and PIC UCs and of course the legendary PC! Now it’s time for ARM!

Happy ARM coding!


#11

@ Gus -

I am taking my questions to where they belong:

Project - More Complete G120 Custom Watchdog + RLP

I hope you or one of your colleagues would have a chance to give me an opinion of the request discussed at the above link.

Thanks.


#12

I looked and it is a project brut a question! I replied too the question you just add there.


#13

@ Jeff - please accept my apology!

I read your post and my response again by chance, and just realized what you meant by “the watchdog code is MCU dependent” in the native section. I must have been excessively tired that night as usual!

I agree it’s dependent on G120’s NXP MCU, and the native code should be modified or rewritten to accommodate other type MCUs.


#14

But your response, using the plus and minuses of internal vs external, was educational for me; so, thank you!