cancel
Showing results for 
Search instead for 
Did you mean: 

Why no VSYNC coming out of STOP mode?

wired
Senior III

I'm trying to use STOP mode on my STM32F469I-DISCO evaluation board in a TouchGFX application. I call a function from the defaultTask that checks if the blue button is pressed, and if so, it enters STOP mode. I set up an event on the LCD_INT line from the touchscreen so that I can wake up when someone interacts with the screen. This all seems to work, but when I come out of Stop mode, the screen is no longer responding to touch. My STOP mode entry and exit code is shown below:

void checkStopMode()
{
 
	if (GPIO_PIN_SET == HAL_GPIO_ReadPin (BLUE_BTN_GPIO_Port, BLUE_BTN_Pin))
	{
		//Turn off display and backlight.
		HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPOFF, 0x00);
		HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x00);
 
		vTaskSuspend( TouchGFXTaskHandle ); // Suspend the TouchGFX task
		HAL_PWREx_EnableFlashPowerDown();
 
		__disable_irq(); //disable so that we don't end up in an ISR until we reconfigure the clocks after wakeup
 
	    // Clear the wakeup flag so we don't wake up right away
	    PWR->CR |= PWR_CR_CWUF;
	    HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE);
 
		/********************   Return from Stop Mode ************************/
		/********   Wait for LCD_INT event from touch controller *************/
 
		SystemClock_Config(); /* Reconfigure the clocks */
 
		// Disable the powerdown of flash when entering Stop Mode.
		HAL_PWREx_DisableFlashPowerDown();
 
		__enable_irq(); // re-enable interrupts now that clocks are reconfigured
 
		vTaskResume( TouchGFXTaskHandle ); // Resume the TouchGFX task
 
	    // Turn on the display and backlight.
	    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPON, 0x00);
	    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x2C);
	}
 
}

I've tried all kinds of different function calls through trial and error, but nothing works. I have a breakpoint right when I come out of STOP mode, and then I set another one in the for loop below at OSWrappers::waitForVSync().

void TouchGFXHAL::taskEntry()
{
    enableLCDControllerInterrupt();
    enableInterrupts();
 
    OSWrappers::waitForVSync();
    backPorchExited();
 
    /* Enable the LCD, Send Display on DCS command to display */
    HAL_DSI_ShortWrite(&hdsi, LCD_OTM8009A_ID, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPON, 0x00);
 
    for (;;)
    {
        OSWrappers::waitForVSync();
        backPorchExited();
    }
}

It breaks there once when I resume from the breakpoint at SystemClock_Config(), but never gets out of the function. Can anyone tell me what I'm missing in my wakeup code? Been trying to get this working for most of a day now...

Also, I should mention that the defaultTask continues to run normally after wakeup.

10 REPLIES 10
wired
Senior III

Still stuck on this after a number of days...

In the TouchGFX and low power modes (st.com) post, @Martin KJELDSEN​ stated that TouchGFX does not care about low power modes. SInce all registers are preserved in STOP mode and clocks are halted, it seems like I should just be able to resume as normal on wakeup. Does anyone know of any working examples of how to prepare for and recover from STOP mode? It would be very helpful if ST actually had some reference material or app note on this. Most handhelds would need to utilize low power modes, I would think. I am not using tickless idle mode for FreeRTOS, but I think that should only pertain to SLEEP mode. Am I incorrect in this assumption?

Martin KJELDSEN
Chief III

We've been given some time to explore and document fully how TouchGFX works best with low power modes. We have several customers who use low power mode, on watches, for instance.

Let me check up on my notes during the week.

/Martin

wired
Senior III

Thank you, Martin! I'll find something else to tear my hair out over in the meantime ;)

FYI, I am mainly concerned about STOP mode, not so much about SLEEP, for my application. I think Sleep mode, if I were to use tickless idle, would probably be more straightforward.

Also, if I comment out the HAL_PWR_EnterSTOPMode() function call, everything continues to work normally, so there must be something disabled by STOP mode that needs to be manually enabled. The reference manual for the '469 doesn't say a lot about awakening from STOP mode.

wired
Senior III

@Martin KJELDSEN​ , one thing I discovered today is that if you have an animation active onscreen when you want to enter STOP mode, you must suspend the TouchGFX task before you issue the DSI commands to turn off the display and backlight, otherwise the display and backlight will remain on while in STOP mode. This should be mentioned or made a standard part of the STOP or STANDBY mode entry process. The display and backlight turn off just fine on a static screen without suspending the task at all.

Also, FYI, I replaced the HAL_PWR_EnterSTOPMode()  with HAL_PWR_EnterSLEEPMode(), and the system resumed normally after a touchscreen press.

wired
Senior III

@Martin KJELDSEN​  I think I've got it! After digging deep it appears the PLLSAI clock, which is used by the LTDC, must be manually restarted. I also discovered that even though I suspend the TouchGFX task before issue the DSI commands, turning off the display and backlight sometimes failed when the animation was running. I added a delay after the suspension, and that seems to clear it up, but I'm not completely certain this is the correct solution. Nevertheless, I can now dirn off the display and backlight and enter Stop mode, then resume with touchscreen activity and pick up where the GUI left off. I will not declare this as 'the Best Answer", because I'm not sure the HAL_Delay is the correct solution to reliably shuttong the display down. However, see below:

// This function will enter Stop Mode if the Blue button is pressed, and Stop Mode will be exited
// if the touchscreen is touched.
void checkStopMode()
{
 
	if (GPIO_PIN_SET == HAL_GPIO_ReadPin (BLUE_BTN_GPIO_Port, BLUE_BTN_Pin))
	{
		/* We need to suspend the TouchGFX task to be able to shut down the
		 * display and backlight when we are running animations. We also need
		 * to delay after the task is suspended to ensure that no interactions
		 * with the DSI are going on when we try to turn off the display and backlight.
		 */
		vTaskSuspend( TouchGFXTaskHandle ); // Suspend the TouchGFX task
 
		// If this is not here, the following cmds do not always work if animation active.
		HAL_Delay(20);
 
		//Turn off display and backlight.
		HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPOFF, 0x00);
		HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x00);
 
		HAL_PWREx_EnableFlashPowerDown();
 
		__disable_irq(); //disable so that we don't end up in an ISR until we reconfigure the clocks after wakeup
 
	    // Clear the wakeup flag so we don't wake up right away
	    PWR->CR |= PWR_CR_CWUF;
	    HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE);
 
		/********************   Return from Stop Mode ************************/
		/********   Wait for LCD_INT event from touch controller *************/
 
		SystemClock_Config(); /* Reconfigure the clocks */
		__enable_irq(); // re-enable interrupts now that clocks are reconfigured
 
		/* The PLL for the LTDC must be manually restarted after stop mode exited. */
		__HAL_RCC_PLLSAI_ENABLE();
 
		// Disable the powerdown of flash when entering Stop Mode.
		HAL_PWREx_DisableFlashPowerDown();
 
		vTaskResume( TouchGFXTaskHandle ); // Resume the TouchGFX task
 
	    // Turn on the display and backlight.
	    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPON, 0x00);
	    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x2C);
	}
 
}

wired
Senior III

Nope, definitely not best answer. It works most of the time, but I can sometimes get it to:

  1. Not shut down the display and backlight, but resume properly upon a touch.
  2. Not shut down the display, then wake up from touch but no screen updates, and then screen updates and screen off never work again.

When it fails, it is (1) much more often than (2). I think maybe the DSI is in the middle of some operation when the commands are written?

wired
Senior III

@Martin KJELDSEN​ - Well, I have some code that I have been unable to get to fail after 100+ tries. I'm still not sure it is failsafe, nor do I understand completely why it seems to be reliable. I now disable the interrupts for the LTDC and DSI, and then allow the code to run for a bit before globally disabling interrupts and shutting down. My theory is that it gives some time for the LTDC and DSI to finish in-process hardware operations. See code below - I'm interested to know your thoughts on this when you get a chance to work on the low power material. The failure mode always seemed to be that I was waiting forever for a signalVSync() to occur so that the vsync message queue would quit waiting. I'm not sure how or if this corrects that problem.

Also, FYI this function is now called from Model::tick().

void checkStopMode()
{
	if (GPIO_PIN_SET == HAL_GPIO_ReadPin (BLUE_BTN_GPIO_Port, BLUE_BTN_Pin))
	{
		/* We need to suspend the TouchGFX task to be able to shut down the
		 * display and backlight when we are running animations. We also need
		 * to delay after the task is suspended to ensure that no interactions
		 * with the DSI are going on when we try to turn off the display and backlight.
		 */
 
		//Turn off display and backlight.
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPOFF, 0x00));
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x00));
 
		HAL_PWREx_EnableFlashPowerDown();
 
		HAL_NVIC_DisableIRQ(LTDC_IRQn);
		HAL_NVIC_DisableIRQ(DSI_IRQn);
		// Wait for LTDC and DSI to finish any display updates
		HAL_Delay(200);
 
		__disable_irq(); //disable so that we don't end up in an ISR until we reconfigure the clocks after wakeup
 
	    // Clear the wakeup flag so we don't wake up right away
	    PWR->CR |= PWR_CR_CWUF;
	    HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE);
//	    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE);
 
		/********************   Return from Stop Mode ************************/
		/********   Wait for LCD_INT event from touch controller *************/
 
		SystemClock_Config(); /* Reconfigure the clocks */
 
		/* The PLL for the LTDC must be manually restarted after stop mode exited. */
		__HAL_RCC_PLLSAI_ENABLE();
 
		__enable_irq(); // re-enable interrupts now that clocks are reconfigured
 
		// Must be enabled after global enable.
		HAL_NVIC_EnableIRQ(DSI_IRQn);
		HAL_NVIC_EnableIRQ(LTDC_IRQn);
 
		// Disable the powerdown of flash when entering Stop Mode.
		HAL_PWREx_DisableFlashPowerDown();
 
	    // Turn on the display and backlight.
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPON, 0x00));
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x2C));
	}
 
}

wired
Senior III

Update to the last code I posted. I added SLEEP mode for the display, and the delays were placed in different sequences in the DSI communications after looking at page 242 of the OTM8009A datasheet. Putting the Display in SLEEP mode reduced the 3V3 current in STOP mode from ~45mA to ~24 mA. Note that I have removed SB8 and SB2 jumpers, and am supplying 3V3 from CN6 Pin 4, and 5V from CN6 Pin 5 using two separate external supplies.

// This function will enter Stop Mode if the Blue button is pressed, and Stop Mode will be exited
// if the touchscreen is touched. Blue button GPIO is configured as an EXTI event source.
void checkStopMode()
{
	if (GPIO_PIN_SET == HAL_GPIO_ReadPin (BLUE_BTN_GPIO_Port, BLUE_BTN_Pin))
	{
		/* We need to suspend the TouchGFX task to be able to shut down the
		 * display and backlight when we are running animations. We also need
		 * to delay after the task is suspended to ensure that no interactions
		 * with the DSI are going on when we try to turn off the display and backlight.
		 */
 
		// Prepare to turn off the display, per OTM8009A datasheet sequence defined on pg 242.
		// Turn off display, wait 120ms, then enter sleep mode and turn off backlight.
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPOFF, 0x00));
		HAL_Delay(125);
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_SLPIN, 0x00));
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x00));
 
		HAL_PWREx_EnableFlashPowerDown();
 
		HAL_NVIC_DisableIRQ(LTDC_IRQn);
		HAL_NVIC_DisableIRQ(DSI_IRQn);
 
		// Calling the function below reduces the stop mode current measured at IDD (JP5) on the
		// STM32F469i-DISCO board by 3mA, from ~9 to ~6 mA, but when this is called and the accompanying
		// call to exit ULPM is called, a touch will result in the first frame being displayed as garbage,
		// so a swipe will have a quick flash of garbage followed by a normal display, but a touch will
		// leave the garbage on the display.  Am not sure why stop mode current is so high on the uC.
		// Also, the 3V3 current is ~24mA in STOP mode without ULPM calls, ~21 with calls.  Why this current
		// is so high is unknown, but am theorizing it is because the display in not powered off (there is no
		// separate power supply with enable for the display).
//		HAL_DSI_EnterULPM(&hdsi);
 
		__disable_irq(); //disable so that we don't end up in an ISR until we reconfigure the clocks after wakeup
 
		// Turn off all LEDs on 3V3 bus (NOTE: only RENDER_TIME and VSYNC_FREQ are not application-specific).
		HAL_GPIO_WritePin(PR_DOCKED_LED_GPIO_Port, PR_DOCKED_LED_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(RENDER_TIME_GPIO_Port, RENDER_TIME_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(VSYNC_FREQ_GPIO_Port, VSYNC_FREQ_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_SET);
 
	    // Clear the wakeup flag so we don't wake up right away
	    PWR->CR |= PWR_CR_CWUF;
	    HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE);
 
		/********************   Return from Stop Mode ************************/
		/********   Wait for LCD_INT event from touch controller *************/
 
		SystemClock_Config(); /* Reconfigure the clocks */
 
		/* The PLL for the LTDC must be manually restarted after stop mode exited. */
		__HAL_RCC_PLLSAI_ENABLE();
 
		__enable_irq(); // re-enable interrupts now that clocks are reconfigured
 
//		HAL_DSI_ExitULPM(&hdsi);
 
		// Must be enabled after global enable.
		HAL_NVIC_EnableIRQ(DSI_IRQn);
		HAL_NVIC_EnableIRQ(LTDC_IRQn);
 
		// Disable the powerdown of flash when entering Stop Mode.
		HAL_PWREx_DisableFlashPowerDown();
 
	    // Exit sleep mode, wait 120ms for display controller to initialize, then turn on backlight
		// followed by display ON and Memory Write. Per OTM8009A datasheet page 242.
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_SLPOUT, 0x00));
		HAL_Delay(125);
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_WRCTRLD, 0x2C));
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPON, 0x00));
		while (HAL_BUSY == HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_RAMWR, 0x00));
 	}
}

wired
Senior III

Disabling the ADC before entering STOP mode dropped the MCU IDD to ~4 mA, and total 3V3 current to ~18 mA. Still not sure where this current is going.