已经实现  ,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. NodeJs -- express 快速建站

    直接上干货 1.新建一个目录来存放我们即将要做的东西: 2.win+R打开小黑框:进入到我们的目录下: 3.首先我们要全局安装Express框架:**在这一步之前要确保你本机上安装了node:** n ...

  2. sublime text插件推荐

    time: 2016-05-23 13:00 --- 用了Sublime Text有一段时间了,之前被周围的几个前端小伙伴灌输的思想就是,牛b的前端程序员都是手写代码的,用代码提示啥的都low,然而上 ...

  3. 在已配置成功的opencv3.2.0下配置opencv_contrib模块

    简介: 之前在Ubuntu下配置OpenCV时,因为对opencv3..0不是特别了解,没有把opencv_contrib进行安装,这里提醒大家尽量要一次性安装完毕,减少不必要的麻烦. .0文件夹 ( ...

  4. ulimit命令&pthread_create() error: Resource temporarily unavailable

    http://www.ibm.com/developerworks/cn/linux/l-cn-ulimit/ https://my.vertica.com/docs/5.0/HTML/Master/ ...

  5. 自己搭建云盘 – 简单的PHP网盘程序

    自己搭建云盘 – 简单的PHP网盘程序 Veno File Manager 2.6.3 汉化版 相信大家都比较熟悉或使用过 Owncloud 网盘程序,Owncloud 虽强大,不过太过于臃肿,而 V ...

  6. 2java.lang.NoClassDefFoundError异常

    1.错误信息 2.错误分析: JVM读到程序的第三行,会在当前路径 "D:\java" 下寻找com.yangquan.aolun这个包路径下的Cat类,但当前路径下根本就没有co ...

  7. hibernate的延迟加载和抓取策略

    一,延迟加载 1.实体类延迟加载 通过代理机制完成,由javassist类库实现运行时代理,修改实体类的字节码实现了运行时代理     <class lazy="true|false& ...

  8. MySQL上机实习报告(一)

    一.实习内容    利用wamp进行MySQL上机实习,建立数据库和一个学生信息表,并能对建的表进行数据插入.修改.查询和删除等内容. 二.实习目的 能将课堂上所学的内容运用到实际的上机操作中,进一步 ...

  9. openweathermap-免费的天气预报接口

    openweathermap-免费的天气预报接口 其官方网址为:http://www.openweathermap.org/api 静态截图: 具备以下的一些特点: 1. Current weathe ...

  10. 静态代码分析工具sonarqube+sonar-runner的安装配置及使用

    配置成功后的代码分析页面: 可以看到对复杂度.语法使用.重复度等等都做了分析,具体到了每一个方法和每一句代码. 四种使用方式: sonarqube + sonar-runner sonarqube + ...