怎么去确定RTOS中ucos任务堆栈大小栈的大小和ucos任务堆栈大小的优先级

后使用快捷导航没有帐号?
请完成以下验证码
查看: 2093|回复: 1
怎么去确定RTOS中任务栈的大小和任务的优先级.
在线时间0 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 2, 距离下一级还需 3 积分
一粒金砂(初级), 积分 2, 距离下一级还需 3 积分
大家好,怎么去确定一个任务的栈的大小和任务的优先级.比如在nucleus,rex或者threadX里面. 我是做手机开发的,这一方面一直没有想明白.是不是通过经验和实验和选择合适的栈的大小和任务的优先级呢. 比如先给新建的任务一个比较充裕的栈空间和估计的优先级,然后让任务在RTOS中跑起来,统计各种极限下栈的使用情况,和任务间的调度情况,最终修订栈的大小和优先级.& &这是我的猜想,唯一可以自己做的东西让人给外包了.呵呵.
在线时间0 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
一般如果是应用而且实时性不高的话,优先级不必太高,否则会抢占其他的实时性要求高的任务。至于栈的大小,个人觉得1K~5K就非常足够了(针对Nucleus而言),除非定义了很多变量和很深层次的调用,另外最好不要用递归。
例如,对于5K的Stack,理论上可以容纳5*0个32bit的变量。
在各个Function里,局部数组不要定义很大,例如
char m_buf[1024*5];就很危险。
个人一点的经验。
如果需要大的Buffer或者大的structure,应该用Malloc从系统堆上分配。
实验和经验还是最重要的。
EEWORLD 官方微信
Powered byFreeRTOS编程指南pdf下载_爱问共享资料
FreeRTOS编程指南.pdf
FreeRTOS编程指南.pdf
FreeRTOS编程指南.pdf
简介:本文档为《FreeRTOS编程指南pdf》,可适用于IT/计算机领域,主题内容包含FreeRTOS使用指南繁星电子开发团队制作作为一个轻量级的操作系统FreeRTOS提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理、符等。
侵权或盗版
*若权利人发现爱问平台上用户上传内容侵犯了其作品的信息网络传播权等合法权益时,请按照平台要求书面通知爱问!
赌博犯罪类
在此可输入您对该资料的评论~
添加成功至
资料评价:没有更多推荐了,
不良信息举报
举报内容:
freeRTOS计算任务堆栈使用情况:
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!FreeRTOS 在STM32上的移植 V1.0
作为开源的轻量级实时性操作系统,不仅实现了基本的实时调度、、队列和存储管理,而且在商业应用上不需要授权费。
FreeRTOS的实现主要由list.c、queue.c、croutine.c和tasks.c 4个文件组成。list.c 是一个链表的实现,主要供给内核调度器使用;queue.c 是一个队列的实现,支持中断环境和信号量控制;croutine.c 和task.c是两种任务的组织实现。对于croutine,各任务共享同一个堆栈,使RAM的需求进一步缩小,但也正因如此,他的使用受到相对严格的限制。而task则是传统的实现,各任务使用各自的堆栈,支持完全的抢占式调度。
FreeRTOS的主要功能可以归结为以下几点:
1) 优先级调度、相同优先级任务的轮转调度,同时可设成可剥夺内核或不可剥夺内核
2) 任务可选择是否共享堆栈(co-routines & tasks),并且没有任务数限制
3) 消息队列,二值信号量,计数信号量,递归互斥体
4) 时间管理
5) 内存管理
与UC/OSII一样,FreeRTOS在的大致由3个文件实现,一个.h文件定义编译器相关的数据类型和中断处理的宏定义;一个.c文件实现任务的堆栈初始化、系统心跳的管理和任务切换的请求;一个.s文件实现具体的任务切换。
在本次移植中,使用的编译软件为IAR EWARM 5.2。
一、各文件关键部分的实现:
1、PORTMACRO.H 宏定义部分
1)定义编译器相关的各种数据类型
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned portLONG
#define portBASE_TYPE long
2)架构相关的定义
Cortex-M3的堆栈增长方向为高地址向低地址增长
#define portSTACK_GROWTH ( -1 )
每毫秒的心跳次数
#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )
访问SRAM的字节对齐
#define portBYTE_ALIGNMENT 8
3)定义用户主动引起内核调度的2个函数
强制上下文切换,用在任务环境中调用
#define portYIELD() vPortYieldFromISR()
强制上下文切换,用在中断处理环境中调用
#define portEND_SWITCHING_ISR( xSwitchRired ) if( xSwitchRequired ) vPortYieldFromISR()
4)定义临界区的管理函数
中断允许和关闭
#define portDISABLE_INTERRUPTS() vPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask()
临界区进入和退出
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
用于在中断环境的中断允许和关闭
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;vPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask();(void)x
2、PORT.C C接口部分
1)堆栈初始化
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
*pxTopOfStack = portINITIAL_XPSR; /* 程序状态寄存器 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxC /* 任务的入口点 */
pxTopOfStack--;
*pxTopOfStack = 0; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvP /* 任务的参数 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfS
2)启动任务调度
portBASE_TYPE xPortStartScheduler( void )
让任务切换中断和心跳中断位于最低的优先级,使更高优先级可以抢占mcu
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
设置并启动系统的心跳时钟
prvSetupTimerInterrupt();
初始化临界区的嵌套的个数
uxCriticalNesting = 0;
启动第一个任务
vPortStartFirstTask();
执行到vPortStartFirstTask函数,内核已经开始正常的调度
3)主动释放mcu使用权
void vPortYieldFromISR( void )
触发PendSV系统服务中断,中断到来时由汇编函数xPortPendSVHandler()处理
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
进入临界区时,首先关闭中断;当退出所以嵌套的临界区后再使能中断
void vPortEnterCritical( void )
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
void vPortExitCritical( void )
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
portENABLE_INTERRUPTS();
4)心跳时钟处理函数
void xPortSysTickHandler( void )
unsigned portLONG ulD
如果是抢占式调度,首先看一下有没有需要调度的任务
#if configUSE_PREEMPTION == 1
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
{ 通过task.c的心跳处理函数vTaskIncrementTick(),进行时钟计数和延时任务的处理
vTaskIncrementTick();
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
3、PORTASM.S 汇编处理部分
1)请求切换任务
xPortPendSVHandler:
保存当前任务的上下文到其任务控制块
mrs r0, psp
ldr r3, =pxCurrentTCB 获取当前任务的任务控制块指针
ldr r2, [r3]
stmdb r0!, {r4-r11} 保存R4-R11到该任务的堆栈
str r0, [r2] 将最后的保存到任务控制块的pxTopOfStack
stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0
切换任务的上下文,pxCurrentTCB已指向新的任务
bl vTaskSwitchContext
mov r0, #0
msr basepri, r0
ldmia sp!, {r3, r14}
恢复新任务的上下文到各寄存器
ldr r1, [r3]
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers. */
msr psp, r0
任务切换的示意图如下:
2.)中断允许和关闭的实现,通过BASEPRI屏蔽相应优先级的中断源
vPortSetInterruptMask:
push { r0 }
mov R0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr BASEPRI, R0
pop { R0 }
vPortClearInterruptMask:
PUSH { r0 }
MOV R0, #0
MSR BASEPRI, R0
POP { R0 }
3)直接切换任务,用于vPortStartFirstTask第一次启动任务时初始化堆栈和各寄存器
ldr r3, =pxCurrentTCB
ldr r1, [r3]
ldr r0, [r1]
ldmia r0!, {r4-r11}
msr psp, r0
mov r0, #0
msr basepri, r0
orr r14, r14, #13
4)启动第一个任务的汇编实现
vPortStartFirstTask
通过中断向量表的定位堆栈的地址
ldr r0, =0xE000ED08 向量表偏移量寄存器 (VTOR)
ldr r0, [r0]
ldr r0, [r0]
msr msp, r0 将堆栈地址保存到主堆栈指针msp中
触发SVC软中断,由vPortSVCHandler()完成第一个任务的具体切换工作
FreeRTOS内核调度器启动的流程如下:
以上3个文件实现了FreeRTOS内核调度所需的底层接口,相关代码十分精简。
二、创建测试任务:
下面创建第一个测试任务,测试
int main( void )
设置系统时钟,中断向量表和LED使用的GPIO
使用stm32的固件包提供的初始化函数,具体说明见相关手册
prvSetupHardware();
通过xTaskCreate()创建4个LED任务vLEDFlashTask(),
每个任务根据各自的频率闪烁,分别对应开发板上的4个LED
vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );
o 创建一个IDLE任务后,通过xPortStartScheduler启动调度器
vTaskStartScheduler();
调度器工作不正常时返回
portTASK_FUNCTION()是FreeRTOS定义的函数声明,没特殊作用
static portTASK_FUNCTION( vLEDFlashTask, pvParameters )
……省略……,具体为计算各LED的闪烁频率
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
vParTestToggleLED( uxLED );
vTaskDelayUntil()的延时时间xFlashRate,是从上一次的延时时间xLastFlashTime算起的,
相对vTaskDelay()的直接延时更为精准。
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
vParTestToggleLED( uxLED );
FreeRTOS的任务创建与UC/OSII差异不大,主要参数为任务函数,堆栈大小和任务的优先级。如:
xTaskCreate( vLEDFlashTask, ( signed portCHAR * ) "LEDx", STACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL );
下面再创建一个LCD显示任务,以最低优先级运行:
xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
void vLCDTask( void *pvParameters )
……省略……
vTaskDelay(1000);
printf("%c ", usDisplayChar);
该任务很简单,每隔1000个ticks(就是1000ms),从LCD上刷新一个数字。
原文链接:
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点

我要回帖

更多关于 ucos任务堆栈大小 的文章

 

随机推荐