Wake FT90x with GPIO

General discussion on mikroC PRO for FT90x.
Post Reply
Author
Message
gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Wake FT90x with GPIO

#1 Post by gtsoftware » 02 Nov 2016 18:01

I'm trying to put the FT90x to sleep and awaken when a GPIO goes low.

The hardware is HMI-43 screen (FT812 and FT900) with attached HMI-BB for access to a GPIO pin.

I've chosen a HMI-BB ethernet LED as the input which is FT900 GPIO pin 4.

Using a wire from GND with a current limiting resistor, I can touch the wire to the first pin on the connector.
When the pin goes low, the ethernet LED lights up, which is good visual feedback.

Taking incremental steps:

GPIOs connected

The code can set up GPIO as an input and read it, duplicating it on GPIO 5 in order to light the other ethernet LED on the HMI-BB

Configuring the two GPIOs as input and output is easy. Before the main loop:

Code: Select all

  // Configure GPIO 4 as an input for a wake up interrupt
  GPIO_Pin_Config(GPIO_PIN4, _GPIO_DIR_INPUT, _GPIO_CFG_PULL_NONE);

  // Configure GPIO 5 as an output to control the LED on the RJ45
  GPIO_Pin_Config(GPIO_PIN5, _GPIO_DIR_OUTPUT, _GPIO_CFG_PULL_NONE);
  GPIO_Pin_Write(GPIO_PIN5, _GPIO_PIN_VALUE_1);
In the main loop, the following code replicates GPIO 4 input on the output LED attached to GPIO 5

Code: Select all

    {
         char rd = GPIO_Pin_Read(GPIO_PIN4);
    
         if (_GPIO_PIN_VALUE_1 == rd || _GPIO_PIN_VALUE_0 == rd)
         {
            GPIO_Pin_Write(GPIO_PIN5, rd);
         }
    }
it proves that the hardware is connected.

GPIO interrupt

The code can set up the GPIO as an interrupt that turns on the LED.
This code replaces the pin read code shown above.

The interrupt handler:

Code: Select all

void interrupt() iv IVT_GPIO_IRQ
{
        // Turn on LED to prove there was an interrupt
        GPIO_Pin_Write(GPIO_PIN5, _GPIO_PIN_VALUE_0); // I wouldn't usually use a high level pin write like this in an ISR!
        
        // Clear interrupt flag 
        GPIO_INT_PEND4_bit = 1;
}
Using visual TFT and a visual element's click handler to enable the interrupt.

The code enabling the interrupt, based on the external interrupt example code:

Code: Select all

        // Enable all interrupts
        IRQ_CTRL.B31 = 0;
                       
        // Set falling edge to detect interrupt
        GPIO04_CFG0_bit = 0;

        // Interrupt capable
        GPIO04_CFG1_bit = 1;

        // Enable interrupt
        GPIO_INT_EN4_bit = 1;
Again, touching the wire/resistor to the GPIO input pin causes the LED to light, indicating that the interrupt was successfully triggered.

Waking from sleep

Now to the real goal, waking the FT90x from sleep.

Just adding a call to PWR_PowerDownMCU with parameters selecting a GPIO wake based on a falling pin 4.

Code: Select all

        // Enable all interrupts
        IRQ_CTRL.B31 = 0;
                       
        // Set falling edge to detect interrupt
        GPIO04_CFG0_bit = 0;

        // Interrupt capable
        GPIO04_CFG1_bit = 1;

        // Enable interrupt
        GPIO_INT_EN4_bit = 1;
                
        PWR_PowerDownMCU(_PWR_WAKEUP_GPIO_YES|_PWR_WAKEUP_GPIO_ON_FALL, GPIO_PIN4);
The screen stops responding, so it is a safe bet that the FT900 has gone to sleep.
Sadly, touching the resistor/wire to the pin does not trigger the interrupt routine to make the LED light up, nor make the screen respond again.
It takes a power cycle to get out of the sleep state.

I've searched for other uses of PWR_PowerDownMCU without success. Does anyone have an example that successfully awakens the FT90x?

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#2 Post by gtsoftware » 03 Nov 2016 17:52

I've still not had any luck awkening the FT90x

Looking at the disassembly in PWR_PowerDownMCU, I can see that the GPIO is being set up and PMCFG is being written to.
I tried the minimum code to replace the call. The app note (AN_324_FT900_User_Manual.pdf) mentions a delay before setting, so I tried a long 5ms delay.

Code: Select all

        // Enable all interrupts
        IRQ_CTRL.B31 = 0;
                       
        // Set falling edge to detect interrupt
        GPIO04_CFG0_bit = 0;

        // Interrupt capable
        GPIO04_CFG1_bit = 1;

        // Enable interrupt
        GPIO_INT_EN4_bit = 1;

        PMCFG = 0;
        
        /*
        This bit should be cleared after the system wakes up or at least 60-100us 
        prior to setting it 1 again
        */
        delay_ms(5);
        
        PMCFG = (1 << PM_PWRDN);
Are there any other app notes or datasheets explaining how to power down and wake the FT90x to save power?

User avatar
Aleksandar.Mitrovic
mikroElektronika team
Posts: 1697
Joined: 11 Mar 2015 12:48

Re: Wake FT90x with GPIO

#3 Post by Aleksandar.Mitrovic » 04 Nov 2016 18:00

Hi,

I would like to take a look at your whole project example code.

You should be able to wake up from "Sleep"/Power Down Mode with GPIO pin which you set as interrupt.
And on the wake up you should clear PM_PWRDN_bit.

http://www.ftdichip.com/Support/Documen ... Manual.pdf

Kind regards,
Aleksandar

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#4 Post by gtsoftware » 07 Nov 2016 11:47

Hi Aleksandar,

Attached is a complete mikroC for FT90x project with a single 'go to sleep' button.

It runs on HMI-43 (capacitive) connected to HMI-BB. GPIO 4 is used as the interrupt input to awaken the FT900. GPIO 5 is an output to prove that the interrupt routine attached to GPIO 4 works.

When I run this and touch the button, UART debug says "Go to sleep" (good) but then causing an interrupt does not awaken the FT900 - at least the ISR is not run and neither is the following UART "awake" debug.

Code: Select all

/// \brief Put the FT90x to sleep and wake on a GPIO interrupt
void SleepUntilInterrupt(void)
{
     PWR_PowerDownMCU(_PWR_WAKEUP_GPIO_YES|_PWR_WAKEUP_GPIO_ON_FALL, GPIO_PIN4);
     
     // If the code PMCFG = 0; follows then it wakes immediately
}

Code: Select all

void btnGoToSleepOnClick() {
     UART1_Write_Text("Go to sleep\n");

     SleepUntilInterrupt();

     UART1_Write_Text("Awake\n");
}
If the power down call is followed by

Code: Select all

PMCFG = 0;
which clears the power down request, then the FT900 awakens immediately.

I've tried five

Code: Select all

asm NOP;
statements before

Code: Select all

PMCFG=0;
to help fill any FT900 prefetch buffer but that didn't help.

Regards,
Colin
Attachments
DemoPowerDown.zip
Complete project to show power down code. A single button kicks off power down. Nothing wakes it.
Runs on HMI-43 connected to HMI-BB using Ethernet LED pins (GPIOs 4 and 5, 4 as input, 5 as output)
(363.44 KiB) Downloaded 178 times

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#5 Post by gtsoftware » 08 Nov 2016 14:40

I've noticed a little detail - touching the wire/resistor to the input GPIO 4, the power drawn increases.

While showing a big bright [Go to sleep] button, the HMI-43 board draws 204mA at 4.91V
(the slightly lower voltage is because I have a passive USB hub. Usually I plug directly in to the laptop in order to get the full 5V)

After I press the button, the FT900 powers down and the board draws 165mA at 4.94V (the code is simplified to not power down the FT812, so the power is higher than in another post)

When I touch the wire/resistor to input GPIO 4 the power draw goes back up to 202mA at 4.92V

So I think the FT900 must be running again but in a strange state.

Maybe there is a different vector for wakeup?

Colin

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#6 Post by gtsoftware » 08 Nov 2016 15:06

I found a PM interrupt vector

Code: Select all

void interruptPM() iv IVT_PM_IRQ
{
     // Clearing power management
     PMCFG = 0;
}
Now flicking the GPIO input with a wire/resistor does have an effect, allowing code to carry on running.

I haven't worked out if the NOPs are useful yet..

Code: Select all

/// \brief Put the FT90x to sleep and wake on a GPIO interrupt
void SleepUntilInterrupt(void)
{
     PWR_PowerDownMCU(_PWR_WAKEUP_GPIO_YES|_PWR_WAKEUP_GPIO_ON_FALL, GPIO_PIN4);

     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
     asm NOP;
}

Code: Select all

void btnGoToSleepOnClick() {
     UART1_Write_Text("Go to sleep\n");

     SleepUntilInterrupt();
     
     UART1_Init(115200);
     UART1_Write_Text(".Awake\n");
     UART1_Write_Text("WideAwake\n");
}

A terminal on the debug uart shows some junk, so maybe clocks are getting up to speed again

Code: Select all

Nov  8 2016 13:39:40
Go to sleeps▒w▒ke
WideAwake
The screen isn't alive again so there might be some reinitialisation to carry out.
Just calling InitVTFTStack(); on waking up wasn't the answer.

Anyone know any details on IVT_PM_IRQ and what is still alive (in terms of the core and peripherals)?

Colin

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#7 Post by gtsoftware » 11 Nov 2016 17:58

I'm still working on getting the HMI-43 completely woken up.

Using the code in the previous posts, I know that the FT900 wakes up again when the GPIO input is triggered. I know this because the code writes a message to the UART. I tried another test where waking up would repeatedly output text to the UART.

The function to put the FT900 to sleep remains unchanged:

Code: Select all

/// \brief Put the FT90x to sleep and wake on a GPIO interrupt
void SleepUntilInterrupt(void)
{
     PWR_PowerDownMCU(_PWR_WAKEUP_GPIO_YES|_PWR_WAKEUP_GPIO_ON_FALL, GPIO_PIN4);
}
The calling code announces that it is going to sleep, sleeps and then announces that it has woken up. Each output is coded to be separated by a delay of 100ms.

Code: Select all

        UART1_Write_Text("Go to sleep\n");
        Delay_100ms();

        SleepUntilInterrupt();

        Delay_100ms();

        UART1_Init(115200);
        
        {
            int count;
            for (count = 0; count < 10; ++count)
            {
                UART1_Write_Text("123456789\n");
                UART1_Write_Text("WideAwake\n");
                Delay_100ms();
            }
        }
Using a serial port logger that timestamps messages revealed that the messages are 1.4 seconds apart instead of 100 milliseconds.

Code: Select all

[16:30:45:789] Read data (COM9) 
    43 6c 69 63 6b 0a 47 6f 20 74 6f 20 73 6c 65 65   Click.Go to slee 
    70 0a                                             p.               
[16:30:51:191] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:30:52:598] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:30:53:988] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:30:55:394] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:30:56:801] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:30:58:192] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:30:59:598] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:31:01:004] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:31:02:410] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             
[16:31:03:801] Read data (COM9) 
    31 32 33 34 35 36 37 38 39 0a 57 69 64 65 41 77   123456789.WideAw 
    61 6b 65 0a                                       ake.             

I then instrumented InitVTFTStack with a UART message before each action.
Most of them return but not FT812_Audio_SetConfig, FT812_Sound_SetConfig or DrawScreen

I hope that provides a clue.

I wondered if the GPIO interrupt was perhaps looping forever. I made sure the vector cleared the pending interrupt bit but it made no difference. Also, HMI-BB's the LED on GPIO 5 never lit up, so I doubt that the GPIO interrupt ever happens as part of power down and wake up.

I've looked at the FT900 register documentation and I can't find a bit to clear related to the power management vector.

If the system clock was down to a fourteenth of its original speed (100MHz down to 7MHz) then the UART baud rate might have been affected too, but messages still come out legibly. Of course the system clock could be divided down in different ways to peripherals and the core (like Cortex M microcontrollers)

Colin

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#8 Post by gtsoftware » 11 Nov 2016 18:29

Another update in my quest to wake the FT900.

I decided to access the FT812/FT813 directly rather than using the VTFT library functions.

I'd been experimenting with the FTDI EVE Screen Designer to manually build display lists.
Each FT812 command is supported by a mikroC for FT90x library function.

This code draws a green rectangle on a dark background

Code: Select all

        FT812_DL_BeginUpdate();
        FT812_DL_CmdClearColorRGB(0);
        FT812_DL_CmdClear(1,1,1);
        FT812_DL_CmdColorRGB(255<<8);
        FT812_DL_CmdLineWidth(16);
        FT812_DL_CmdBegin(_FT812_GP_RECTS);
        FT812_DL_CmdVertex2f(2832,1584);
        FT812_DL_CmdVertex2f(6032,3184);
        FT812_DL_CmdEnd();
        FT812_DL_EndUpdate();
        FT812_Display_Swap(0);
So after the FT900 power down and wake up, I displayed the green rectangle then a blue one and then a red one:

Code: Select all

void TestSleep(void)
{
        UART1_Write_Text("Go to sleep\n");
        Delay_100ms();

        SleepUntilInterrupt();

        Delay_100ms();

        FT812_DL_BeginUpdate();
        FT812_DL_CmdClearColorRGB(0);
        FT812_DL_CmdClear(1,1,1);
        FT812_DL_CmdColorRGB(255<<8);
        FT812_DL_CmdLineWidth(16);
        FT812_DL_CmdBegin(_FT812_GP_RECTS);
        FT812_DL_CmdVertex2f(2832,1584);
        FT812_DL_CmdVertex2f(6032,3184);
        FT812_DL_CmdEnd();
        FT812_DL_EndUpdate();
        FT812_Display_Swap(0);

        Delay_100ms();

        FT812_DL_BeginUpdate();
        FT812_DL_CmdClearColorRGB(0);
        FT812_DL_CmdClear(1,1,1);
        FT812_DL_CmdColorRGB(255);
        FT812_DL_CmdLineWidth(16);
        FT812_DL_CmdBegin(_FT812_GP_RECTS);
        FT812_DL_CmdVertex2f(2832,1584);
        FT812_DL_CmdVertex2f(6032,3184);
        FT812_DL_CmdEnd();
        FT812_DL_EndUpdate();
        FT812_Display_Swap(0);

        Delay_100ms();

        FT812_DL_BeginUpdate();
        FT812_DL_CmdClearColorRGB(0);
        FT812_DL_CmdClear(1,1,1);
        FT812_DL_CmdColorRGB(255<<16);
        FT812_DL_CmdLineWidth(16);
        FT812_DL_CmdBegin(_FT812_GP_RECTS);
        FT812_DL_CmdVertex2f(2832,1584);
        FT812_DL_CmdVertex2f(6032,3184);
        FT812_DL_CmdEnd();
        FT812_DL_EndUpdate();
        FT812_Display_Swap(0);
}
This works, which suggests that most of the system is still in a good state after wakeup.

The 100ms delays are still 1.4s seconds. Presumably the function calls are slower too.
The FT812 itself is likely to still be processing the display list at full speed.

While I would like to work out why there is an issue reinitialising the VTFT stack, I can live without the VTFT stack if I can directly access the FT812/FT813. I do want to get the clock speed back up though.

Colin

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#9 Post by gtsoftware » 07 Dec 2016 13:55

I can confirm that after wake up, running FT900 code that interacts with the FT812 does run more slowly than before the sleep.

I used a GPIO to trigger an external logic analyser

Code: Select all

void Box(int32_ft8 colour)
{
    GPIO_Pin_Write(GPIO_PIN5, _GPIO_PIN_VALUE_0);       // GPIO output for timing
    
    FT812_DL_BeginUpdate();
    FT812_DL_CmdClearColorRGB(0);
    FT812_DL_CmdClear(1,1,1);
    FT812_DL_CmdColorRGB(colour);
    FT812_DL_CmdLineWidth(16);
    FT812_DL_CmdBegin(_FT812_GP_RECTS);
    FT812_DL_CmdVertex2f(2832,1584);
    FT812_DL_CmdVertex2f(6032,3184);
    FT812_DL_CmdEnd();
    FT812_DL_EndUpdate();
    FT812_Display_Swap(0);
    
    GPIO_Pin_Write(GPIO_PIN5, _GPIO_PIN_VALUE_1);
}
Before putting the FT900 to sleep, the function ran in 638us. After wake up the function took 976us.

A call to delay 100ms takes 100ms before the FT900 is put to sleep and 1.4s after waking up.

The function taking longer might be due to a repeating interrupts stealing cycles or perhaps the SPI peripheral now has a different clocking speed or perhaps the FT900 is now running at a slower rate.

Looking at the 100ms delay function, the assembly shows a tight counter loop decrementing a register to zero. Stepping through in the debugger (mikroProg) didn't show any interrupts happening (but sometimes debuggers have settings to suppress them, so I'm not sure). This makes me think that the FT900 processor is truly running at a slower speed after wake up. The Box function might be less affected because it has little code to run and spends more time waiting for the SPI peripheral to complete.

I tried nudging the clock in case that helps

Code: Select all

        FT812_Core_ClockSource(_FT812_CLK_SOURCE_EXTERNAL);
        FT812_Core_SetFrequency(VTFT_FT812_CONFIG_DISPLAY.Frequency);
the timing remained at about 976us

Anyone know what controls the FT900 clock speed? (that might be affected by having gone to sleep)

gtsoftware
Posts: 17
Joined: 24 Oct 2016 11:12
Location: Cambridge, UK

Re: Wake FT90x with GPIO

#10 Post by gtsoftware » 07 Dec 2016 17:40

The answer is back in the vector clearing the power config bits.

Code: Select all

void interruptPM() iv IVT_PM_IRQ
{
     // Clearing power management
     
     // Note that completely clearing the PMCFG register 
     // leaves the processor running slowly (1/14 speed)
     // PMCFG = 0;
     
     // Just clearing PM_PWRDN
     PMCFG &= (~(1 << PM_PWRDN));
}
Now the processor comes up at full speed again.

Post Reply

Return to “mikroC PRO for FT90x General”