- void vPortSetupTimerInterrupt( void )
- {
- /* Calculate the constants required to configure the tick interrupt. */
- #if( configUSE_TICKLESS_IDLE == 2 )
- {
- ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
- xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
- ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ /
- configSYSTICK_CLOCK_HZ );
- }
- #endif /* configUSE_TICKLESS_IDLE */
- /* Stop and clear the SysTick. */
- portNVIC_SYSTICK_CTRL_REG = 0UL;
- portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- /* Configure SysTick to interrupt at the requested rate. */
- portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
- portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT |
- portNVIC_SYSTICK_ENABLE_BIT );
- }
重写 vPortSuppressTicksAndSleep 函数。 在进入 LPSLEEP 前,会停止 systick,在休眠完成
后,需要补偿系统 tick 值,示例中使用 LPTIM 计时来补偿系统 tick 值。 在进入 LPSLEEP 前先进
行状态检查,只要有以下情况,都不进入低功耗模式:
a) 触摸事件产生: nosleep_**
b) DMA2D busy 状态: isDMAbusy_a()
c) DSI refreshing 状态: displayRefreshing
d) 渲染完成,请求 DSI 刷新: refreshRequested
- void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
- {
- uint32_t xMaximumPossibleSuppressedTicks,ulReloadValue, ulCompleteTickPeriods,ulCount;
- xMaximumPossibleSuppressedTicks=portMAX_16_BIT_NUMBER * configTICK_RATE_HZ / lptim_CLOCK_HZ;
- if(nosleep_** || isDMAbusy_a() || displayRefreshing || refreshRequested) {
- if(!isDMAbusy_a() && !displayRefreshing && !refreshRequested) {
- if(osKernelSysTick() > nosleep_**_t0 + nosleep_time)
- nosleep_** = 0;
- }
- return;
- }
- if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) {
- xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
- }
- portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
- HAL_SuspendTick();
- ulReloadValue = (lptim_CLOCK_HZ * (xExpectedIdleTime - 1UL)/configTICK_RATE_HZ);
- __DSB();
- __ISB();
- LPTIM_ReloadMatch_flag=pdFALSE;
- if( eTaskConfirmSleepModeStatus() == eAbortSleep ) {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- portNVIC_SYSTICK_LOAD_REG = configCPU_CLOCK_HZ/configTICK_RATE_HZ - 1UL;
- HAL_ResumeTick();
- } else {
- MX_LPTIM1_Init(LPTIM_PRESCALER_DIV2, ulReloadValue);
- if( xExpectedIdleTime > 0 ) {
- __DSB();
- enter_lpsleep();
- __ISB();
- }
- ulCount = HAL_LPTIM_ReadCounter(&Lptim1);
- HAL_LPTIM_TimeOut_Stop_IT(&Lptim1);
- HAL_ResumeTick();
- if( LPTIM_ReloadMatch_flag != pdFALSE ) {
- ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
- } else {
- ulCompleteTickPeriods = (ulCount * configTICK_RATE_HZ)/ lptim_CLOCK_HZ;
- }
- portENTER_CRITICAL();
- uwTick += ulCompleteTickPeriods;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- portNVIC_SYSTICK_LOAD_REG = configCPU_CLOCK_HZ/configTICK_RATE_HZ - 1UL;
- portEXIT_CRITICAL();
- }
- }
TouchGFX 渲染过程包括两部分, CPU 渲染和 DMA2D 渲染。在 CPU 渲染过程中, TouchGFX
任务处于执行状态,系统不会主动调度 Idle 任务。而在 DMA2D 渲染过 TouchGFX 会让出
CPU,此时可能会切换到 Idle 任务执行,因此需要对 DMA2D 是否正在渲染进行判断。 对
DMA2D 是否在渲染的判断如下:
- extern "C" uint8_t isDMAbusy_a()
- {
- return ((TouchGFXHAL*)(touchgfx::HAL::getInstance()))->isDMAbusy();
- }
- uint8_t TouchGFXHAL::isDMAbusy()
- {
- bool dma_qe = dma.isDmaQueueEmpty();
- bool dma_run = dma.isDMARunning();
- return (uint8_t)(!dma_qe || dma_run);
- }