Best way to have more than one WKUP GPIO pins?

What would be the best way to configure more than one WKUP GPIO pins on a PICO or SC13048Q?

How do I configure PA2 or PC13 for WKUP in addition to PA0?

We added this feature to the next release,
For SC20xxx: PA0, PA2, PC1, PC13, PI8, PI11. Use can chose any of those pins. Default isPA0.
For SC13xxx: PA0 and PA2 only. Default is PA0.

User can’t select multiple pins, some thing like PA0 | PA2 will not work, of course.

We will document this, but here is the way, this is only for next release. Version 2.2.0.5100 doesn’t work with this.

            var wakeupPinAddress = (IntPtr)8; // 8 is special marshal address for wakeup pin
            Marshal.WriteInt32(wakeupPinAddress, SC20260.GpioPin.PA0);

            Power.WakeupEdge = WakeupEdge.Rising;
            Power.Shutdown(true, DateTime.Now.AddSeconds(20));

Thanks! That will work !

PA0 and PA2 only on SC13xxx makes sense.
Those are the only GPIO pins exposed that support WKUP.

Do you have a rough estimate of when to expect the next release ?

Dat,
So … how do we configure both PA0 & PA2 for WKUP ?
Or customer specifically requires two different wakeup pins.

The original question was:
“What would be the best way to configure more than one WKUP GPIO pins on a PICO or SC13048Q?”

Developer team is ready, we are waiting the approval for the date, but it will be soon, hopefully it will be this week.

Only one pin at the time, why do you need multiple pins at the same time?

We have multiple external devices that will trigger a process wakeup from shutdown.

The STM32L4x2 support up to 5 WKUP pins.
Power control register 3 (PWR_CR3)

ok, we just added that.

if you want multi pins:

var wakeupPinAddress = (IntPtr)8; // 8 is special marshal address for wakeup pin
 var wakeupPins = 0x08000000; // special value to detect multi pins
            // PA0: bit 0
            // PA2: bit 1
            // PI8: bit 2 //SC20260 only
            // PC13: bit 3  //SC20xxx only
            // PI11: bit 4  //SC20260 only
            // PC1: bit 5  //SC20xxx only

            wakeupPins |= 0x08000000 | (1 << 0); // PA0
            wakeupPins |= 0x08000000 | (1 << 0) | (1 << 1); // PA0, PA2
            wakeupPins |= 0x08000000 | (1 << 0) | (1 << 1) | (1 << 2); // PA0, PA2,  PI8
            wakeupPins |= 0x08000000 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3); // PA0, PA2,  PI8, PC13
            wakeupPins |= 0x08000000 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4); // PA0, PA2,  PI8, PC13, PI11
            wakeupPins |= 0x08000000 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5); // PA0, PA2,  PI8, PC13, PI11, PC1

 Marshal.WriteInt32(wakeupPinAddress, wakeupPins);

Fantastic !
Thanks

if wakeup is config as multi pins, all pins must be config same state before enter shudown. Example, you can’t tie PA0 to low and PA2 to high then enter shutdown mode.

Dat,
We have finally got around to implementing the “2 wake-up pins” change your made for the SC13048Q.
But unfortunately, it does not seem to work.

Using the following code as an example:

using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.Rtc;
using GHIElectronics.TinyCLR.Native;
using GHIElectronics.TinyCLR.Pins;
using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace Pico_Shutdown_Tests
{
    internal class Program
    {
        static GpioPin _Blue_LED;
        static GpioPin _Wakeup_0;
        static GpioPin _Wakeup_2;
        static RtcController rtc;

        static void Main()
        {

            rtc = RtcController.GetDefault();
            rtc.Now = new DateTime(2023, 4, 12);
            SystemTime.SetTime(rtc.Now);


            // Status LED
            _Blue_LED = GpioController.GetDefault().OpenPin(SC13048.GpioPin.PA8);
            _Blue_LED.SetDriveMode(GpioPinDriveMode.Output);

            // Wakeup - PA0
            _Wakeup_0 = GpioController.GetDefault().OpenPin(SC13048.GpioPin.PA0);
            _Wakeup_0.SetDriveMode(GpioPinDriveMode.Input);
            _Wakeup_0.ValueChanged += _Wakeup_0_ValueChanged;

            // Wakeup - PA2
            _Wakeup_2 = GpioController.GetDefault().OpenPin(SC13048.GpioPin.PA2);
            _Wakeup_2.SetDriveMode(GpioPinDriveMode.Input);
            _Wakeup_2.ValueChanged += _Wakeup_2_ValueChanged;

            // Slow blink the Blue LED 5 times to show the CPU has woken up
            for (int x = 0; x < 5; x++)
            {
                Thread.Sleep(500);
                _Blue_LED.Write(GpioPinValue.High);
                Thread.Sleep(500);
                _Blue_LED.Write(GpioPinValue.Low);
            }

            var wakeupPinAddress = (IntPtr)8; // 8 is special marshal address for wakeup pin
            var wakeupPins = 0x08000000; // special value to detect multi pins
            // PA0: bit 0
            // PA2: bit 1
            wakeupPins |= 0x08000000 | (1 << 0) | (1 << 1); // PA0, PA2
            Marshal.WriteInt32(wakeupPinAddress, wakeupPins);


            // ALWAYS fails with System.NotSupportedException when wkupPin=true
            // UNLESS you specify the Power.WakeupEdge = WakeupEdge.Rising;
            Power.WakeupEdge = WakeupEdge.Rising;
            Power.Shutdown(true, rtc.Now + TimeSpan.FromSeconds(30));
        }

        // Detect Wake-Up from PA0
        private static void _Wakeup_0_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
        {
            // Blink the Blue LED 3 times very fast to show that the 
            // _Wakeup_0_ValueChanged() was caught
            for (int x = 0; x < 3; x++)
            {
                Thread.Sleep(50);
                _Blue_LED.Write(GpioPinValue.High);
                Thread.Sleep(100);
                _Blue_LED.Write(GpioPinValue.Low);
            }
        }

        // Detect Wake-Up from PA2
        private static void _Wakeup_2_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
        {
            // Blink the Blue LED 10 times very fast to show that the 
            // _Wakeup_2_ValueChanged() was caught
            for (int x = 0; x < 10; x++)
            {
                Thread.Sleep(50);
                _Blue_LED.Write(GpioPinValue.High);
                Thread.Sleep(100);
                _Blue_LED.Write(GpioPinValue.Low);
            }
        }
    }
}

The CPU wakes up fine from PA0, PA2, and rtc. But, after waking up one time from PA2, it will never go back into shutdown mode. The CPU immediately wakes up every time shutdown is called.

Can you help us figure out what is wrong?

We are using this simple circuit with a PICO for testing.

Wakeup-Test -Circuit

Sure, could you add this to github, we will take a look in shortly

Sure,
Which repository? I don’t see a repository for TinyCRL firmware.

We added and will work on it shortly

Check Wakeup multipin on SC13 · Issue #1340 · ghi-electronics/TinyCLR-Libraries (github.com)

Ah … TinyCLR-Libraries !

Thanks

Hi,

try to add code below can fix the issue for now, check // GHI added

......
// ALWAYS fails with System.NotSupportedException when wkupPin=true
// UNLESS you specify the Power.WakeupEdge = WakeupEdge.Rising;
Power.WakeupEdge = WakeupEdge.Rising;

// Clear wakup flag
const uint PWR_SCR = 0x40000000U + 0x7000U + 0x18; // GHI added
Marshal.WriteInt32((IntPtr)PWR_SCR, 0x7FFFFFFF); // GHI added


Power.Shutdown(true, rtc.Now + TimeSpan.FromSeconds(30));
.....

We will fix firmware in next release

Yep !
That fixed it. Thanks for the quick reply and fix !

2 Likes

Also, code below is not right. You can see the led blink because the device reset and boot so fast, faster than your action (releasing the pin), so it generated new interrupt.

Add delay 1, 2 second at main() to delay the device start code, you can see what I am talking about. The led should not blink and this is correcrt. After woke up from shutdown, GPOI interrupt should be cleared.

So, do not rely on gpio event to detect wakeup by gpio. It will be reset and the event won’t be fired.


// add delay
Thread.sleep(2000);

// Wakeup - PA0
 _Wakeup_0 = GpioController.GetDefault().OpenPin(SC13048.GpioPin.PA0);
_Wakeup_0.SetDriveMode(GpioPinDriveMode.Input);
_Wakeup_0.ValueChanged += _Wakeup_0_ValueChanged;

            // Wakeup - PA2
            _Wakeup_2 = GpioController.GetDefault().OpenPin(SC13048.GpioPin.PA2);
            _Wakeup_2.SetDriveMode(GpioPinDriveMode.Input);
            _Wakeup_2.ValueChanged += _Wakeup_2_ValueChanged;

Oh, I didn’t realize that. Glad you pointed it out.

How do I know who generated the wake-up interrupt ?