|
第24章 RTX低功耗之tickless模式
本章节为大家讲解RTX本身支持的低功耗模式tickless实现方法,tickless低功耗机制是当前小型RTOS所采用的通用低功耗方法,比如embOS,FreeRTOS和uCOS-III(类似方法)都有这种机制。
本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。
24.1 tickless低功耗模式介绍
24.2 RTX实现tickless模式的框架
24.3 tickless模式的API函数
24.4 实验例程说明
24.5 总结
24.1 tickless低功耗模式介绍
tickless低功耗机制是当前小型RTOS所采用的通用低功耗方法,比如embOS,FreeRTOS和uCOS-III(类似方法)都有这种机制。
RTX的低功耗也是采用的这种方式,那么tickless又是怎样一种模式呢,仅从字母上看tick是滴答时钟的意思,less是tick的后缀,表示较少的,这里的含义可以表示为无滴答时钟。整体看这个字母就是表示滴答时钟节拍停止运行的情况。
反映在RTX上,tickless又是怎样一种情况呢?我们都知道,当用户任务都被挂起时,最低优先级的空闲任务会得到执行。那么STM32支持的睡眠模式,停机模式就可以放在空闲任务里面实现。为了实现低功耗最优设计,我们还不能直接把睡眠或者停机模式直接放在空闲任务就可以了。进入空闲任务后,首先要计算可以执行低功耗的最大时间,也就是求出下一个要执行的高优先级任务还剩多少时间。然后就是把低功耗的唤醒时间设置为这个求出的时间,时间到后系统会从低功耗模式被唤醒,继续执行多任务。这个就是所谓的tickless模式。从上面的讲解中可以看出,实现tickless模式最麻烦是低功耗可以执行的时间如何获取。关于这个问题,RTX已经为我们做好了,调用函数os_suspend即可。
24.2 RTX实现tickless模式的框架
RTX实现低功耗tickless模式的代码框架如下:
- __task void os_idle_demon (void) {
- uint32_t sleep;
-
- ...
- /* 第1步:配置系统深度睡眠模式 */
- ...
-
- /* 第2步:通过函数os_suspend获取系统可以处于低功耗模式的时钟节拍个数,此函数会关闭调度器 */
- for (;;) {
- sleep = os_suspend ();
-
- if (sleep) {
- ...
- /* 第3步:创建一个新的定时器,专门用于将系统从低功耗模式唤醒,并将唤醒时间设置为
- 函数os_suspend返回值sleep */
- ...
-
- /* 第4步:调用低功耗指令进入低功耗模式 */
- __WFE ();
-
- /* 第5步:系统从低功耗模式唤醒,调整系统实际处于低功耗状态的时钟节拍个数*/
- /* Adjust actual sleep time (in case of any event) */
- sleep = ...
- }
- /* 第6步:重新使能调度器并调整系统时间,继续多任务的执行 */
- os_resume (sleep); /* OS Resume */
- }
- }
复制代码
24.3 tickless模式的API函数
使用如下2个函数可以实现RTX的tickless模式:
u os_suspend
u os_resume
关于这两个函数的讲解及其使用方法可以看教程第3章3.3小节里面说的参考资料rlarm.chm文件
下面我们也对这2个函数依次进行讲解:
24.3.1 函数os_suspend
函数原型:
函数描述:
函数os_suspend用于获取系统可以处于低功耗模式的时钟节拍个数。此函数必须配套函数os_resume一起使用。调用了函数os_suspend后,此函数会关闭调度器,即关闭任务切换,调用了函数os_resume会恢复任务调度。
u 函数返回系统可以处于低功耗模式的时钟节拍个数。
使用这个函数要注意以下问题:
1. 只能在空闲任务里面调用这个函数。
2. 当系统进入到低功耗模式后,系统滴答定时器停止运行,因为调用了函数os_suspend,此函数会关闭滴答定时器。
使用举例:
下面举的例子是RTX官方提供的基于STM32F2的低功耗设计代码,用于STM32F4也是可以,因为STM32F2和STM32F4的RTX时钟基本一样。下面的例子是通过RTC的低功耗唤醒功能实现。
- #include <rtl.h>
-
- __task void os_idle_demon (void) {
- 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 */
- }
- }
复制代码
24.3.2 函数os_resume
函数原型:
- void os_resume (
- U32 sleep_time ); /* 系统处于低功耗模式的时钟节拍个数 */
复制代码 函数描述:
函数os_resume用于恢复任务调度器的运行。此函数必须配套函数os_suspend一起使用。调用了函数os_suspend后,此函数会关闭调度器,即关闭任务切换,调用函数os_resume会恢复任务调度。
u 参数填写系统处于低功耗模式的时钟节拍个数。
使用这个函数要注意以下问题:
1. 只能在空闲任务里面调用这个函数。
2. 当系统进入到低功耗模式后,系统滴答定时器停止运行,因为调用了函数os_suspend,此函数会关闭滴答定时器。
使用举例:
参考上面函数os_suspend的举例。
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配置向导详情如下:
u Task Configuration
l Number of concurrent running tasks
允许创建4个任务,实际创建了如下四个任务:
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
在休眠模式下,无法动态的查看任务的调试信息。下面的是单步调试时状态查看:
程序设计:
u 任务栈大小分配:
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类型数据运算会出问题。
u 系统栈大小分配:
u 外设初始化:
注意新加的函数初始化函数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(); /* 初始化按键 */
- }
复制代码 u RTX初始化:
- /*
- *********************************************************************************************************
- * 函 数 名: main
- * 功能说明: 标准c程序入口。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- int main (void)
- {
- /* 初始化外设 */
- bsp_Init();
-
- /* 创建启动任务 */
- os_sys_init_user (AppTaskStart, /* 任务函数 */
- 4, /* 任务优先级 */
- &AppTaskStartStk, /* 任务栈 */
- sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
- while(1);
- }
复制代码 u 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)); /* 任务栈大小,单位字节数 */
- }
复制代码 u tickless模式在空闲任务实现,即配置向导文件RTX_Conf_CM.c文件中
u 信号量的创建:
- static OS_SEM semaphore;
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建信号量计数值是0, 用于任务同步 */
- os_sem_init (&semaphore, 0);
- }
复制代码 u 四个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配置向导详情如下:
u Task Configuration
l Number of concurrent running tasks
允许创建4个任务,实际创建了如下四个任务:
AppTaskUserIF任务 :按键消息处理。
AppTaskLED任务 :LED闪烁。
AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
AppTaskStart任务 :启动任务,也是最高优先级任务,这里实现按键扫描。
l Number of tasks with user-provided stack
创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
程序设计:
u 任务栈大小分配:
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类型数据运算会出问题。
u 系统栈大小分配:
u 外设初始化:
注意新加的函数初始化函数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指示灯端口 */
- }
复制代码 u RTX初始化:
- /*
- *********************************************************************************************************
- * 函 数 名: main
- * 功能说明: 标准c程序入口。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- int main (void)
- {
- /* 初始化外设 */
- bsp_Init();
-
- /* 创建启动任务 */
- os_sys_init_user (AppTaskStart, /* 任务函数 */
- 4, /* 任务优先级 */
- &AppTaskStartStk, /* 任务栈 */
- sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
- while(1);
- }
复制代码 u 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)); /* 任务栈大小,单位字节数 */
- }
复制代码 u 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();
- }
- }
复制代码 u 信号量的创建:
- static OS_SEM semaphore;
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppObjCreate
- * 功能说明: 创建任务通信机制
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppObjCreate (void)
- {
- /* 创建信号量计数值是0, 用于任务同步 */
- os_sem_init (&semaphore, 0);
- }
复制代码 u 四个RTX任务的实现:
24.5 总结
本章节主要为大家讲解了RTX本身支持的低功耗tickless模式,对于初学者来说,刚开始学习可能不是特别理解,随着后面自己有了一定的经验后就比较容易理解了,特别是tickless的实现方法。另外tickless模式不限制用户必须采用停机模式,采用睡眠模式也是可以的,官方只是为用户提供了一种参考方法。 |
评分
-
查看全部评分
|