24.4 实验例程说明
24.4.1 STM32F103开发板实验配套例子: V4-424_RTX实验_低功耗(tickless模式) 实验目的: 1. 学习RTX的低功耗(tickless模式)。 2. tickless模式低功耗的实现采用了停机模式,使用RTC的闹钟中断进行唤醒。 3. tickless模式的实现在源文件RTX_Conf_CM.C文件中的空闲任务os_idle_demon函数里面。 实验内容: 1.K1按键按下,串口打印。 2.K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro。 任务AppTaskMsgPro接收到消息后进行消息处理。 3.各个任务实现的功能如下: AppTaskUserIF任务 :按键消息处理。 AppTaskLED任务 :LED闪烁。 AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的信号量同步信号。 AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。 设计低功耗主要从以下几个方面着手: 1. 用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式可以使用的低功耗方式有休眠模式,待机模式,停机模式。 2. 选择了低功耗方式后就是关闭可以关闭的外设时钟。 3. 降低系统主频。 4. 注意I/O的状态。 如果此I/O口带上拉,请设置为高电平输出或者高阻态输入; 如果此I/O口带下拉,请设置为低电平输出或者高阻态输入; a.在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。 b.在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。 c.在待机模式下,所有的I/O引脚处于高阻态,除了以下的引脚: ● 复位引脚(始终有效)。 ● 当被设置为防侵入或校准输出时的TAMPER引脚。 ● 被使能的唤醒引脚。 5.注意I/O和外设IC的连接。 6.测低功耗的时候,一定不要连接调试器,更不能边调试边测电流。 RTX配置: RTX配置向导详情如下:
Task Configuration Number of concurrent running tasks 允许创建4个任务,实际创建了如下四个任务: AppTaskUserIF任务 :按键消息处理。 AppTaskLED任务 :LED闪烁。 AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。 AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。 Number of tasks with user-provided stack 创建的4个任务都是采用自定义堆栈方式。 RTX任务调试信息: 在休眠模式下,无法动态的查看任务的调试信息。下面的是单步调试时状态查看:
程序设计: 任务栈大小分配: staticuint64_t AppTaskUserIFStk[512/8]; /* 任务栈 */ staticuint64_t AppTaskLEDStk[256/8]; /* 任务栈 */ staticuint64_t AppTaskMsgProStk[512/8]; /* 任务栈 */ staticuint64_t AppTaskStartStk[512/8]; /* 任务栈 */ 将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。 系统栈大小分配:
外设初始化: 注意新加的函数初始化函数DBGMCU_Config(DBGMCU_STOP, ENABLE);保证停机模式下调试器正常连接使用。
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_Init
- * 功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
- * 全局变量。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_Init(void)
- {
- /* 保证停机模式下调试器继续可以连接使用 */
- DBGMCU_Config(DBGMCU_STOP, ENABLE);
-
- /* 优先级分组设置为4, 优先配置好NVIC */
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
-
- bsp_InitUart(); /* 初始化串口 */
- bsp_InitLed(); /* 初始LED指示灯端口 */
- bsp_InitKey(); /* 初始化按键 */
- }
复制代码
RTX初始化:
- /*
- *********************************************************************************************************
- * 函 数 名: main
- * 功能说明: 标准c程序入口。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- int main (void)
- {
- /* 初始化外设 */
- bsp_Init();
-
- /* 创建启动任务 */
- os_sys_init_user (AppTaskStart, /* 任务函数 */
- 4, /* 任务优先级 */
- &AppTaskStartStk, /* 任务栈 */
- sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
- while(1);
- }
复制代码
RTX任务创建:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskCreate
- * 功能说明: 创建应用任务
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppTaskCreate (void)
- {
- HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF, /* 任务函数 */
- 1, /* 任务优先级 */
- &AppTaskUserIFStk, /* 任务栈 */
- sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
-
- HandleTaskLED = os_tsk_create_user(AppTaskLED, /* 任务函数 */
- 2, /* 任务优先级 */
- &AppTaskLEDStk, /* 任务栈 */
- sizeof(AppTaskLEDStk)); /* 任务栈大小,单位字节数 */
-
- HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro, /* 任务函数 */
- 3, /* 任务优先级 */
- &AppTaskMsgProStk, /* 任务栈 */
- sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
- }
复制代码
tickless模式在空闲任务实现,即配置向导文件RTX_Conf_CM.c文件中
信号量的创建:
- static OS_SEM semaphore;
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建信号量计数值是0, 用于任务同步 */
- os_sem_init (&semaphore, 0);
- }
复制代码
四个RTX任务的实现:
24.4.2 STM32F407开发板实验配套例子: V5-424_RTX实验_低功耗(tickless模式) 实验目的: 1. 学习RTX的低功耗(tickless模式)。 2. tickless模式低功耗的实现采用了停机模式,使用RTC的唤醒中断进行唤醒。这个和前面STM32F1开发板采用的闹钟中断唤醒不同。 3. tickless模式的实现在源文件RTX_Conf_CM.C文件中的空闲任务os_idle_demon函数里面。 实验内容: 1.K1按键按下,串口打印。 2.K2键按下,直接发送信号量同步信号给任务AppTaskMsgPro。 任务AppTaskMsgPro接收到消息后进行消息处理。 3.各个任务实现的功能如下: AppTaskUserIF任务 :按键消息处理。 AppTaskLED任务 :LED闪烁。 AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的信号量同步信号。 AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。 设计低功耗主要从以下几个方面着手: 1. 用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式可以使用的低功耗方式有休眠模式,待机模式,停机模式。 2. 选择了低功耗方式后就是关闭可以关闭的外设时钟。 3. 降低系统主频。 4. 注意I/O的状态。 如果此I/O口带上拉,请设置为高电平输出或者高阻态输入; 如果此I/O口带下拉,请设置为低电平输出或者高阻态输入; a.在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。 b.在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。 c.在待机模式下,所有的I/O引脚处于高阻态,除了以下的引脚: ● 复位引脚(仍可用)。 ● RTC_AF1 引脚 (PC13)(如果针对入侵、时间戳、 RTC 闹钟输出或 RTC 时钟校准输出进行了配置)。 ● WKUP 引脚 (PA0)(如果使能)。 5.注意I/O和外设IC的连接。 6.测低功耗的时候,一定不要连接调试器,更不能边调试边测电流。 RTX配置: RTX配置向导详情如下:
Task Configuration Number of concurrent running tasks 允许创建4个任务,实际创建了如下四个任务: AppTaskUserIF任务 :按键消息处理。 AppTaskLED任务 :LED闪烁。 AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。 AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。 Number of tasks with user-provided stack 创建的4个任务都是采用自定义堆栈方式。 RTX任务调试信息:
程序设计: 任务栈大小分配: staticuint64_t AppTaskUserIFStk[512/8]; /* 任务栈 */ staticuint64_t AppTaskLEDStk[256/8]; /* 任务栈 */ staticuint64_t AppTaskMsgProStk[512/8]; /* 任务栈 */ staticuint64_t AppTaskStartStk[512/8]; /* 任务栈 */ 将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。 系统栈大小分配:
外设初始化: 注意新加的函数初始化函数DBGMCU_Config(DBGMCU_STOP, ENABLE);保证停机模式下调试器正常连接使用。
- /*
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_Init
- * 功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
- * 全局变量。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_Init(void)
- {
- /* 保证停机模式下调试器继续可以连接使用 */
- DBGMCU_Config(DBGMCU_STOP, ENABLE);
-
- /* 优先级分组设置为4, 优先配置好NVIC */
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
-
- bsp_InitUart(); /* 初始化串口 */
- bsp_InitKey(); /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
- bsp_InitLed(); /* 初始LED指示灯端口 */
- }
复制代码
RTX初始化:
- /*
- *********************************************************************************************************
- * 函 数 名: main
- * 功能说明: 标准c程序入口。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- int main (void)
- {
- /* 初始化外设 */
- bsp_Init();
-
- /* 创建启动任务 */
- os_sys_init_user (AppTaskStart, /* 任务函数 */
- 4, /* 任务优先级 */
- &AppTaskStartStk, /* 任务栈 */
- sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
- while(1);
- }
复制代码
RTX任务创建:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskCreate
- * 功能说明: 创建应用任务
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppTaskCreate (void)
- {
- HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF, /* 任务函数 */
- 1, /* 任务优先级 */
- &AppTaskUserIFStk, /* 任务栈 */
- sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
-
- HandleTaskLED = os_tsk_create_user(AppTaskLED, /* 任务函数 */
- 2, /* 任务优先级 */
- &AppTaskLEDStk, /* 任务栈 */
- sizeof(AppTaskLEDStk)); /* 任务栈大小,单位字节数 */
-
- HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro, /* 任务函数 */
- 3, /* 任务优先级 */
- &AppTaskMsgProStk, /* 任务栈 */
- sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
- }
复制代码
tickless模式在空闲任务实现,即配置向导文件RTX_Conf_CM.c文件中
- /*----------------------------------------------------------------------------
- * Global Functions
- *---------------------------------------------------------------------------*/
- #include "stm32f4xx.h"
- extern void SetSysClock(void);
- void RTC_WKUP_IRQHandler (void) {
- EXTI->PR = (1 << 22); /* Clear pending EXTI interrupt */
- RTC->CR &= ~RTC_CR_WUTE; /* Disable wakeup timer */
- }
-
- /*--------------------------- os_idle_demon ---------------------------------*/
-
- __task void os_idle_demon (void) {
- // /* The idle demon is a system task, running when no other task is ready */
- // /* to run. The 'os_xxx' function calls are not allowed from this task. */
- uint32_t sleep;
-
- SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; /* Configure Cortex-M3 for deep sleep */
- PWR->CR &= ~PWR_CR_PDDS; /* Enter Stop mode when in deepsleep */
- PWR->CR |= PWR_CR_LPDS; /* Voltage regulator in low-power */
-
- /* Enable LSI clock and wait until ready */
- RCC->CSR |= RCC_CSR_LSION;
- while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
-
- /* Enable power interface clock */
- RCC->APB1ENR |= RCC_APB1ENR_PWREN;
-
- /* Disable backup domain write protection */
- PWR->CR |= PWR_CR_DBP;
-
- /* Select LSI as clock source for RTC and enable RTC */
- RCC->BDCR &= ~RCC_BDCR_RTCSEL;
- RCC->BDCR |= RCC_BDCR_RTCSEL_1;
- RCC->BDCR |= RCC_BDCR_RTCEN;
-
- /* Disable the write protection for RTC registers */
- RTC->WPR = 0xCA;
- RTC->WPR = 0x53;
-
- /* Configure RTC auto-wakeup mode */
- RTC->ISR &= ~RTC_ISR_WUTF; /* Clear wakeup timer flag */
- RTC->CR &= ~RTC_CR_WUCKSEL; /* Set RTC clock to 2kHz */
- RTC->CR |= RTC_CR_WUTIE; /* Enable RTC wakeup timer interrupt */
-
- /* Configure EXTI line 22 for wakeup on rising edge */
- EXTI->EMR |= (1 << 22); /* Event request is not masked */
- EXTI->RTSR |= (1 << 22); /* Rising trigger enabled */
-
- NVIC_EnableIRQ (RTC_WKUP_IRQn); /* Enable RTC WakeUp IRQ */
-
- for (;;) {
- /* HERE: include optional user code to be executed when no task runs. */
- sleep = os_suspend (); /* OS Suspend */
-
- if (sleep) {
- RTC->ISR &= ~RTC_ISR_WUTF; /* Clear timer wakeup flag */
- RTC->CR &= ~RTC_CR_WUTE; /* Disable wakeup timer */
- while ((RTC->ISR & RTC_ISR_WUTWF) == 0);
-
- /* RTC clock is @2kHz, set wakeup time for OS_TICK >= 1ms */
- RTC->WUTR = (sleep * (OS_TICK / 1000) * 2);
-
- RTC->CR |= RTC_CR_WUTE; /* Enable wakeup timer */
- __WFE (); /* Enter STOP mode */
-
- /* After Wake-up */
- if ((RTC->ISR & RTC_ISR_WUTF) == 0) {
- sleep = 0; /* We didn't enter Stop mode */
- }
-
- }
- os_resume (sleep); /* OS Resume */
-
- /*
- 下面的代码由用户添加。
- 1、当一个中断或唤醒事件导致退出停止模式时,HSI RC振荡器被选为系统时钟。
- 2、退出低功耗的停机模式后,需要重新配置使用HSE和HSE。
- 3、测试发现时钟配置函数SetSysClock不能放在os_suspend和os_resume,要不会有问题。
- */
- /* Disable IRQs */
- __disable_irq();
-
- SetSysClock();
-
- /* Enable IRQs */
- __enable_irq();
- }
- }
复制代码
信号量的创建:
- static OS_SEM semaphore;
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建信号量计数值是0, 用于任务同步 */
- os_sem_init (&semaphore, 0);
- }
复制代码
四个RTX任务的实现:
|