This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123GH6PM: WAKE pin status in Run/Sleep/DeepSleep

Part Number: TM4C123GH6PM

Hi,

Thank you for all the support, this forum has helped me in countless occasions. I have a theorical question:

My setup is the following:

  • I am in run mode, and the \WAKE pin is HIGH, as expected.
  • I assert the \WAKE pin (setting it LOW) through a pushbutton, and no effect occurs. This is expected since I am already awake.

The question is: is there any way for me to read the state of the wake pin in run mode?

I have tried reading with the HIBRIS register (bit 3) while keeping the push button pressed, but I see no change in the register map in CCS8.0.0

I can successfully wake from hibernation through external wake, that is not an issue, but for the purposes of my application I'd like to know the state of the \WAKE pin
also in Run mode. I have also tried setting up an interrupt attached to the external wake pin and pressing the pushbutton, but it also seems to be ignored while in run mode.
Am I missing something?

In essence:
Is it possible to read the  raw state of the \WAKE pin (HIGH or LOW) from any register?

Thanks in advance

Lorenzo Lombardi

  • Hello Lorenzo,

    I can look in more detail when back in the office on Monday but the datasheet implies you can get an interrupt event on the Wake pin when in run mode:

    The WAKE pin can generate interrupts in Run, Sleep and Deep Sleep Mode. The events that can trigger an interrupt are configured by setting the appropriate bits in the Hibernation Interrupt Mask (HIBIM) register. Pending interrupts can be cleared by writing the corresponding bit in the Hibernation Interrupt Clear (HIBIC) register.

    That comment is in Section 7.3.12 Interrupts and Status of the device datasheet. 

    I would review your interrupt configuration. Feel free to post the code so I can look over it as well.

  • Lorenzo Lombardi said:
    Is it possible to read the  raw state of the \WAKE pin (HIGH or LOW) from any register?

    Can you not, 'Gate the \WAKE pin' to a 'spare' GPIO - and read it?    (the 'gating' would (only) be enabled while the MCU was 'AWAKE' (the intent is that the GPIO would not 'become infiltrated' by voltage while the MCU is 'Asleep.'       We'd have to 'play' w/circuit details - yet I believe such is 'do-able.')

  • Hi Ralph,

    Thanks a lot for the quick reply. I interpreted the datasheet as you said, but in practice I am failing to get it.

    Here is a minimum (non) working example of the code I have uploaded:

    //Includes
    #include <stdarg.h>
    #include <stdbool.h>
    #include <stdint.h>
    
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_ints.h"
    //#include "inc/tm4c123gh6pm.h"
    
    #include "driverlib/i2c.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/pwm.h"
    #include "driverlib/uart.h"
    #include "driverlib/timer.h"
    #include "driverlib/fpu.h"
    #include "driverlib/hibernate.h"
    
    #include "utils/uartstdio.h"
    
    #include "gauge.h"
    #include "SM.h"
    
    void HibernateHandler(void);
    
    #define PWM_FREQ_BUZZ           100
    #define HIB_RIS_R               (*((volatile uint32_t *)0x400FC018))
    #define HIB_RTCLD_R             (*((volatile uint32_t *)0x400FC00C))
    #define HIB_RTCM0_R             (*((volatile uint32_t *)0x400FC004))
    
    //declare a variable for the gauge, pointer to the struct it refers to
    bq769x0 bq76920;
    
    //State machine for the overall BMS
    uint8_t BMS_state = INITIALISING;
    
    int main(void)
    {
    
        bool ok = 1;
        bool hybReset = 0; // 1 -> in the main due to hybernation, 0 -> due to cold reset.
        uint32_t ui32HybParams[2] = {0};
        static uint64_t hibregdata = 0;
    
        //Buzzer functions
        uint32_t ui32PWMClock = 0;
        uint32_t ui32PWMLoad = 0;
    
        // Set the clocking to run directly from the external crystal/oscillator. check this is the smart clock to use, keeping in mind te hibernation stage.
        //We should be able to slow this down considerably to reduce consumption
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ);
    
        //Assert a pin for test: PF1
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOF);
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_PIN_0);
    
        //UART for simple debug PD4 and PD5
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOD);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART6);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART6);
        GPIOPinConfigure(GPIO_PD4_U6RX);
        GPIOPinConfigure(GPIO_PD5_U6TX);
        GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5);
        UARTClockSourceSet(UART6_BASE, UART_CLOCK_PIOSC);
        UARTStdioConfig(6, 115200, 16000000);
    
        //Hibernation
        //find out if it is a COLD RESET or back from Hib by checking if the peripheral is enabled.
        hybReset = HibernateIsActive();
    
        //enable the hibernation peripheral anyway
        SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_HIBERNATE)) {;}  //wait for the peripheral to be ready
        HibernateEnableExpClk(SysCtlClockGet());
        HibernateGPIORetentionDisable();                            //unretain GPIO states so that other peripherals can use them
        SysCtlDelay(100000);//64000000);
        HibernateRTCSet(0);                                         //set the RTC start and refresh rate in s
        HibernateRTCEnable();
        HibernateRTCMatchSet(0,60);
    
        //try with the interrupt for hibernation approach
        HibernateIntEnable(HIBERNATE_INT_PIN_WAKE);
        HibernateIntClear(HIBERNATE_INT_PIN_WAKE | HIBERNATE_INT_RTC_MATCH_0);
    
        //Enable the interrupts
        IntMasterEnable();
    
        UARTprintf("Hello world\n");
    
        //now go to sleep
        while(true){
    
            //sleep (or better deep sleep, later)
            SysCtlSleep();
    
        }
    }
    
    void HibernateHandler(void)
    {
    uint32_t ui32Status;
    static uint16_t loopCounterHyb = 0;
    
    //
    // Get the interrupt status and clear any pending interrupts.
    //
    
    ui32Status = HibernateIntStatus(1);
    HibernateIntClear(ui32Status);
    
    UARTprintf("HL\n");
    
    loopCounterHyb++;
    
    }
    

    For completeness I also include the register states: the RTC counter correctly counts up (just a sanity check) and HIBIM correctly reads 0x8:

    I have check on harware level with an oscilloscope and I do pull to GND the \WAKE pin. I have included (and extern prototyped) above the interrupt in the startup_css.c (I have also tried theHibernateIntRegister(HibernateHandler), same lack of result):

    I get no UART print, nor the debugger stops the code if I put a breakpoint, suggesting it never enters the HibernateHandler.

    Thanks for the support,

    Lorenzo

  • Hi,

    Thanks for the support.

    I have considered connecting the wake to pin to the nieghbouring GPIO through a physical wire,
    that is definitely plan B, but I would rather see if I can solve this without touching the hardware.
    See my reply to Ralph for more details on the matter.

    If you are referring to a software Muxing (kind of) functionality, could you provide an example?
    I am not aware of a way to MUX a GPIO to the wake pin.

    Thanks again btw,

    Appreciated.

    Lorenzo

  • Lorenzo Lombardi said:
    If you are referring to a software Muxing (kind of) functionality, could you provide an example?

    Not only did I 'Miss' such a clever technique ... I failed to (even) recognize it!      That admitted - as you (thus far) cannot 'read' \WAKE (under the conditions described) - I doubt that you'd be able to, 'Mirror \WAKE - (even) via inspired software...

    I depart - but once more note that the 'hapless (would-be) helper' (moi) has 'learned' from he/she (you) - 'allegedly seeking insight!'     Such may just 'justify one's presence here' - as 'learning' often flows in (both) directions...

    BTW - no one (both) Thanks & Appreciates ... but for YOU!     Much return 'thanks' to you, Sir.   (I'd mash the **LIKE** button - but it (& MCU's name) have been 'lost in battle'...)

  • Hello Lorenzo,

    For starters to clarify, the code you posted was missing the following to get it to work in Hibernation mode.

    	//
    	// Configure the Hibernate Wake event.
    	//
    	HibernateWakeSet(HIBERNATE_WAKE_PIN);
    
    	//
    	// Re-intializes the Trim which gets modified due to a known issue of
    	// Hibernate register initialization from HIB#01 errata.
    	//
    	HibernateRTCTrimSet(0x7FFF);
    
    	//
    	// Configure MCU interrupts.
    	//
    	IntEnable(INT_HIBERNATE_TM4C123);

    With that, I am able to re-create the situation where /WAKE only triggers an interrupt after a HibernateRequest.

    I am not sure if the documentation is misleading or if there is something else going on here. I am going to have to hand this over to another colleague as I am departing on business travel tomorrow. Maybe they will be able to shed further light on this.

  • Hi again,

    In the example I did not include the part to set up the interrupt from hibernation,
    but thanks for pointing it out. 

    I'll wait for news from you,  I had initially assumed it was possible since it is possible
    to do it with the RTC (example on the driverlib).

    By the wat, I do not necessary need an interrupt, it would be sufficient for a register
    bit to change (e.g. mask) as a result of \WAKE being asserted in RUN mode.

    Thanks for the help,
    Lorenzo

  • Hi,

      Ralph is out of office. I will look into it. 

  • Hi,

      I'm not able to wake when already in run mode. Perhaps we need to clarify this in the document on what operating modes the wake pin is effective. In the meantime, please take cb1's suggestion to route the wake pin to another GPIO if you have a pressing need to find out the state of the wake pin in run mode