已经实现  ,2018年11月17日11:56:42,具体 如下:

第一步 : 修改 void vPortSetupTimerInterrupt( void ) 函数 ,修改原来的 systick 定时器初始化 改为  RTC 初始化 

    void vPortSetupTimerInterrupt( void )
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure; /* Enable PWR and BKP clocks */ /* PWR时钟(电源控制)与BKP时钟(RTC后备寄存器)使能 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /* Allow access to BKP Domain */ /*使能RTC和后备寄存器访问 */
PWR_BackupAccessCmd(ENABLE); RCC_LSICmd(ENABLE); /* 使能内部32.768K时钟 */ /* 等待内部32.768K时钟就绪 */
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); /* 选择内部32.768K时钟为RTC时钟 */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); /* Set RTC prescaler: set RTC period to 1 millisecond */
/* suozhang,使用外部32.768K晶振,设置32分频,计数1024次为1S,2018年11月15日09:28:52 */
RTC_SetPrescaler( ); /* Enable the RTC Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configKERNEL_INTERRUPT_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); /* Enable the RTC Alarm Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configKERNEL_INTERRUPT_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); //闹钟中断接到第17线外部中断
EXTI_ClearITPendingBit(EXTI_Line17); EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); /* 使能电源管理时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE); /* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); /* 使能RTC根据选择的时钟源以及分频值的设置产生的定时中断,当做FreeRTOS时钟源 */
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask(); }

第二步:增加 RTC 中断服务函数

void RTCAlarm_IRQHandler( void )
{
//必须加上这个中断服务函数,否则RTC闹钟唤醒后,只能执行中断服务函数,suozhang,2018年11月15日13:47:34
} void RTC_IRQHandler( void )
{ if(RTC_GetITStatus(RTC_IT_SEC)!= RESET)//RTC定时中断
{
RTC_WaitForLastTask();
RTC_ClearITPendingBit(RTC_IT_SEC); //清除RTC定时中断 /* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known - therefore the slightly faster vPortRaiseBASEPRI() function is used
in place of portSET_INTERRUPT_MASK_FROM_ISR(). */
vPortRaiseBASEPRI();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
vPortClearBASEPRIFromISR(); } if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断
{
RTC_WaitForLastTask();
RTC_ClearITPendingBit(RTC_IT_ALR); //清闹钟中断 RTC_WaitForLastTask();
EXTI_ClearITPendingBit(EXTI_Line17); if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
{
RTC_WaitForLastTask();
PWR_ClearFlag(PWR_FLAG_WU); //清自动唤醒中断( AWU )
}
} }

第三步:因为要实现 tickless 模式,因此要实现 void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) 这个函数接口

 void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime; uint32_t exitTime = ; /* 停止RTC产生 1ms 的定时中断 */
RTC_ITConfig(RTC_IT_SEC, DISABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods. */
//根据参数xExpectIdleTime来计算滴答定时器的重载值,进入低功耗之后,计时由滴答定时器计算。
ulReloadValue = xExpectedIdleTime - 1UL ; if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;//上面已经停止RTC了,下面一直到启动RTC闹钟的 程序运行时间补偿,小于1mS,因此这里为0
} /* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
__disable_irq();
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE ); /* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ /* 再次启动 RTC产生 1ms 的定时中断*/
RTC_ITConfig(RTC_IT_SEC, ENABLE); /* Re-enable interrupts - see comments above __disable_irq() call
above. */
__enable_irq();
}
else
{
/* RTC 计数器清0 */
RTC_SetCounter( );
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); /* RTC 计数器清0 */
RTC_SetAlarm( ulReloadValue ); // 设置经过ulReloadValue 计时后,产生闹钟
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); RTC_ClearITPendingBit(RTC_IT_ALR); //清闹钟中断
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); PWR_ClearFlag(PWR_FLAG_WU); //清自动唤醒中断( AWU )
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); /* 启动 RTC 闹钟中断. */
RTC_ITConfig(RTC_IT_ALR, ENABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > )
{
__enable_irq();
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);//进入停止模式
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); /* 关闭 RTC 闹钟中断. */
RTC_ITConfig(RTC_IT_ALR, DISABLE); /* 再次启动 RTC产生 1ms 的定时中断*/
RTC_ITConfig(RTC_IT_SEC, ENABLE); /* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. see comments above
__disable_interrupt() call above. */
__enable_irq();
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE ); /* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar
time. */
__disable_irq();
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE ); /* 读取RTC计数值,用于补偿真正的系统时间,有可能其他事件唤醒,而不是闹钟唤醒,2018年11月16日11:07:31,suozhang */
exitTime = RTC_GetCounter();
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask(); if( exitTime )
vTaskStepTick(exitTime-); //补偿真正的系统时间,进入闹钟定时之前,已经把计数器清0 因此这里减0 /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. */ /* Exit with interrpts enabled. */
__enable_irq();
}
}

最后  有 两个 函数 说明一下:

         configPRE_SLEEP_PROCESSING( xModifiableIdleTime );  // 进入低功耗之前 要执行的函数,用户可自定义!
         configPOST_SLEEP_PROCESSING( xExpectedIdleTime );   // 退出低功耗 第一个 执行的函数,用户可自定义!
 
最后测试一下: 测试代码 如下
void vLedTask( void *pvParameters )
{ for(;;)
{ //PC13 LED1
bsp_LedToggle(); vTaskDelay( * ); }
}

功耗测试结果 如下:  5S 高电流 即 LED 点亮时间, 5S低电流 是 13uA  正好达到裸机 进入 STOP 模式 的电流!

 

STM32中用 stop 模式 配合低功耗模式下的自动唤醒(AWU) 能否实现FreeRTOS tickless 模式的更多相关文章

  1. FreeRTOS 低功耗之 tickless 模式

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 本身支持的低功耗模式 tickless 实现方法,tickless 低功 ...

  2. jlink RTT 打印 BUG , FreeRTOS 在开启 tickless 模式下 无法使用的问题

    一开始我以为是 jlink 的问题,后面发现是 tickless 模式搞鬼 tickless 模式下 ,内核 会 根据任务需求,会停止工作,这个时候 jlink rtt 打印就会失效!!! 不过 NR ...

  3. SQL Server SQL性能优化之--数据库在“简单”参数化模式下,自动参数化SQL带来的问题

    数据库参数化的模式 数据库的参数化有两种方式,简单(simple)和强制(forced),默认的参数化默认是“简单”,简单模式下,如果每次发过来的SQL,除非完全一样,否则就重编译它(特殊情况会自动参 ...

  4. 设计模式 State模式 机器的情况下用自己的主动性

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/26350617 状态模型给我眼前一亮的感觉啊,值得学习~ 看看定义:改变一个对象的 ...

  5. php cli模式和浏览器访问下加载php.ini文件的注意事项[架构篇]

    使用wampserver或Xampp时,会将配置文件放在一个统一的目录中去调用,这时如果都使用浏览器访问,自然是没有问题的,但是如果换成cli命令行模式运行,则会出现加载了的扩展无法使用的问题. 案例 ...

  6. 用C#实现C/S模式下软件自动在线升级

    用C#实现C/S模式下软件自动在线升级 1 前言 长期以来,广大程序员为到底是使用Client/Server,还是使用Browser/Server结构争论不休,在这些争论当中,C/S结构的程序可维护性 ...

  7. windows下上传shell脚本不能运行—将dos模式修改为unix 文件格式

    windows下上传shell脚本至linux,其格式将为dos.dos模式的shell脚本将不能再linux下正确运行,需要修改文件模式为unix. 1 查看文件模式方法 linux服务器上,用vi ...

  8. 痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法. 我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRT ...

  9. eclipse在debug模式下总是自动进入到ThreadPoolExecutor类中

    当我们将web项目发布到tomcat服务器中,并且以debug模式启动的时候,总是自动跳转到 ThreadPoolExecutor 类中,如下: 解决办法 在eclipse中点击Window-> ...

随机推荐

  1. java多线程3种方式

    Java多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...

  2. 【Android】Retrofit 2.0 的使用

    一.概述 Retrofit是Square公司开发的一个类型安全的Java和Android 的REST客户端库.来自官网的介绍: A type-safe HTTP client for Android ...

  3. struts2 开发模式

    在struts.xml中增加: <constant name="struts.devMode" value="true" />

  4. windows域渗透实战

    测试环境 域控: 192.168.211.130 已经控制的机器: 192.168.211.133 获取网络信息 查看机器的网络信息 ipconfig /all # 查看 网卡信息,获取dns 服务器 ...

  5. maven 项目目录图与web 应用结构图对比

    web应用结构图 -war | | | |++++META-INF | | |----WEB-INF | | |-classes | | |com/baidu/controller/Controlle ...

  6. oracle 闪回功能详解

    Oracle的闪回技术提供了一组功能,可以访问过去某一时间的数据并从人为错误中恢复.闪回技术是Oracle 数据库独有的,支持任何级别的恢复,包括行.事务.表和数据库范围.使用闪回特性,您可以查询以前 ...

  7. C# 队列(Queue) 和堆栈(Stack)

    队列 (Queue)                                                                                          ...

  8. makedown 软件

    windows上的新手使用makedownpad 很适合的 下载之后你需要激活makedownpad MarkdownPad 2 Pro 注册码(邮箱+许可密钥) 邮箱 Soar360@live.co ...

  9. Nav 切换

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. How HashMap works in Java

    https://www.javainterviewpoint.com/hashmap-works-internally-java/ How a HashMap Works internally has ...