uCOS-II

/****************************************************/

**关于移植,ucos官网上给的有template,主要思想是实现任务切换的两个函数(任务级别切换函数和中断级别切换函数)、禁止中断、使能中断、创建任务时的堆栈初始化函数。

**在stm32上,systick用来作为系统时钟,所以systick的中断需要配置到timetick上,这步和上面的pendsv中断都可以放到stm32的启动文件的中断向量表中。

##关于操作系统的理解,操作系统就是一个裸机程序,掌控所有被赋予的硬件的控制权,利用硬件资源为软件提供运行效率、编程底层建筑(中断、DMA、任务锁、临界段)和使用方法(APIs)的优化。

/************************************************/

2018年7月24日 19:44 

OS_EventTaskRdy这个函数位于 os_core.c 文件中,很重要,是连接任务控制块和事件控制块的重要函数,当任务从阻塞态到就绪态时,需要调用它,他将任务在任务就绪表中就绪,设置任务控制块的状态信息,最后从事件控制块中删除掉该任务。

所有基于事件控制块的通信机制都是基于此,比如 MBox、Mqueue、semaphore,他们最终都要调用到 Event Control (事件管理)模块。应该可以这样理解,时间管控模块被嵌入到了基于事件驱动的通信中,也有点类似基类(父类)和扩展类(子类)的关系。

对了 这里涉及到两个链表,任务控制块链表和事件控制块链表,类似Linux,都是这样组织系统的,这些东西都放在内存中。

好了,吃饭,已经做好了。miantiao,tomato,

-----------------------------------

2018年07月30日 13:15

拿semaphore举例,看看优先级、任务控制表、事件控制表之间的关系,

1. pevent->OSEventTbl[] 的初始化。每创建一个资源(semaphore、mbox、mutex、queue etc)就需要从链表上申请一个事件控制块。

注意,这里的 pevent->OSEventTbl[] 是个事件控制块结构体里的一个成员,也就是说,不同的semaphore、Mbox、queue、里的pevent->OSEventTbl[]都是相互独立的,没有任何关系。虽然这个表也是用来表示该资源的调度位图用的,但是它有很多个,不像任务就绪表只有一个,因为不同的资源的pevent->OSEventTbl[]肯定是相互独立的。

 事件控制块结构体

2. 对于每个等待某个资源的任务,都在该资源的 pevent->OSEventTbl[] 里排队,调度算法完全和任务调度算法一样,数据结构也是一样的,都有就绪表和就绪组。

 

 

/***********************************************************************************************************************/

2018年07月24日   00:08   by Mapleay 

uCOS-II是一个多任务、实时性、可抢占内核,它由唯一的任务优先级来标识。它只实现了任务的管理(任务管理的实现的数据结构、任务切换)、通信(任务间对硬件资源的合理分配)。

 

在单核计算机的世界里,一个任务运行时,他的运行时环境由一些特定的资源组成,如CPU的寄存器、RAM中的资源(比如局部变量)、其他硬件状态资源等。

 

uCOS-II必须保证任务间无缝地切换,即这个单核runtime environment的seamless地切换,也可以说是必须要要无缝地切换这些资源(CPU寄存器、RAM变量)。

 

uCOS-II是怎么样实现任务的管理的呢?

答:是通过“OSTCBPrioTbl”这个表(或者数组,一个存放指向OSTCB类型结构体的指针),他的原型是,OS_TCB*  OSTCBPrioTbl[OS_LOWEST_PRIO + 1u];  和它密切相关的自然是实际存放任务状态、资源记录等信息的任务块,“OSTCBTbl”(存放任务块结构体的数组),原型是,OS_TCB  OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];

 

         uCOS-II是怎么实现任务调度的呢?

为了更快地,固定时间地实现任务调度和切换,uCOS-II使用了位图算法(OSUnMapTbl)、一些全局变量(OSTCBCur、OSTCBHighRdy;OSRdyGrp、OSRdyTbl;OSPrioCur、OSPrioHighRdy等)。任务调度先通过位图算法处理OSRdyGrp、OSRdyTbl数据,找到最高的就绪优先级,通过OSTCBPrioTbl找到OSTCBTbl里的任务控制块,如果需要切换,那么就利用之前移植好的代码做切换(中断级别的上下文切换和任务级别的上下文切换)。

 

任务在运行时,需要协同也会涉及到资源的竞争分配等问题,如何协同?如何合理的使用CPU,涉及到事件控制块派生出的信号量、消息队列、邮箱等概念。

好晚了,去睡觉了。哈。

/***********************************************************************************************************************/

1. 

RTOS的调度算法以及系统任务如何协同运行

OS_EXT OS_PRIO OSRdyGrp;
OS_EXT OS_PRIO OSRdyTbl[OS_RDY_TBL_SIZE]; 

OS_EXT OS_EVENT *OSEventFreeList; 
OS_EXT OS_EVENT OSEventTbl[OS_MAX_EVENTS];

如果优先级个数小于64,定义 OS_PRIO INT8U,否则默认为256个优先级 定义为INT16U。

#if OS_LOWEST_PRIO <= 63u
typedef INT8U OS_PRIO;
#else
typedef INT16U OS_PRIO;
#endif

uCOS-II中设计了一个优先级表OSxxxTbl表中的每个bit定义对应一个优先级,该优先级就绪则该bit置1,否则置0,有多少个位就有多少个优先级,优先级按照位的顺序排列。

 

OS_PRIO  OSxxxGrp和OS_PRIO OSxxxTbl[OS_xxx_TBL_SIZE]配合起来使用;系统有(OS_xxx_TBL_SIZE x (SizeofBits(OS_PRIO)))个优先级,也就是 SizeofBits(OSxxxTbl[OS_xxx_TBL_SIZE])。

 

设Grpx 为就绪组中优先级最高的那个组,MaxPrio为就绪组中最高优先级

Grpx   = OSUnMapTbl [OSxxxGrp]

MaxPrio = OSUnMapTbl[OSxxxTbl[Grpx]]

 

OSUnMapTbl的含义是,在8个位(8个优先级任意状态),即 28 =256种情况中,确定优先级最高的就绪位。所以64个优先级,需要先确定8个组中优先级最高的那个组,再确定组中优先级最高的那个位。

#############非重要话题

/* 关于底层 keil stm32f407, 0x08000000 ,FLSAH, 0x20000000 RAM*/

1. 全局变量, 全局变量的初始化和不初始化,都存放在RAM中,怎么存放的RAM中的?(这不是UOCS的重点)

   1.1 全局常量

   extern  INT8U   const     OSUnMapTbl[256];          /* Priority->Index    lookup table   */

   const 指定存储属性,全局只读变量,全局常量。在map文件中的位置如下:

      OSUnMapTbl                               0x0800190a   Data         256  os_core.o(.constdata)

   1.2 全局变量如何初始化?

    参考,AN241 - ARM Compiler C Library Startup and Initialization   Application Note 241, URL, http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0241b/index.html,      

            data和.bss是在__main里进行初始化的。对于gcc汇编文件startup_stm32f10x_hd.s里面Reset_Handler已经对.data和.bss进行了初始化。

                                                                

   __scatterload

Application code and data can be in a root region or a non-root region. Root regions have the same load-time and execution-time addresses. Non-root regions have different load-time and execution-time addresses. The root region contains a region table output by the ARM linker.

The region table contains the addresses of the non-root code and data regions that require initialization. The region table also contains a function pointer that indicates what initialization is needed for the region, for example a copying, zeroing, or decompressing function.

__scatterload goes through the region table and initializes the various execution-time regions. The function:  !!!这里类似 uboot 里的启动,这类代码叫boot代码。这个函数的作用就是把ZI等加载地址和执行地址不一致的变量重定位一下。

?         Initializes the Zero Initialized (ZI) regions to zero

?         Copies or decompresses the non-root code and data region from their load-time locations to the execute-time regions.

__main always calls this function during startup before calling __rt_entry.

    __rt_entry

__main calls __rt_entry to initialize the stack, heap and other C library sub systems. __rt_entry calls various initialization functions and then calls the user-level main()

 

posted @ 2018-07-13 12:04  mapleay  Views(368)  Comments(0Edit  收藏  举报