GoupOS内核基础
GoupOS内核基础
1. 内核简介
内核是操作系统最基础也是最重要的部分。下图为GoupOS内核架构图,内核处于硬件层之上,内核部分包括内核库、实时内核实现。
内核库是为了保证内核能够独立运行的一套小型的类似C库(c库:也叫C运行库(C Runtime Library),它提供了类似strcpy、memcpy等函数,有些也会包括printf、scanf函数的实现。GoupOS内核用到的一小部分C库函数实现。)的函数实现子集。这部分根据编译器的不同,自带C库的情况也会有些不同,当使用GNU、GCC编译器时,会携带更多的标准C库实现。
实时内核的实现包括:对象管理、线程管理及调度器、线程间通信、时钟管理及内存管理等。
1. 线程调度
线程是GoupOS操作系统中最小的调度单位,线程调度算法是基于优先级的全抢占式多线程调度算法,即在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码不可抢占之外,系统的其他部分都是可以抢占的,包括线程调度器自身。支待32个线程优先级,0优先级代表最高优先级,最低优先级留给空闲线程使用;同时它也支持创建多个具有相同优先级的线程,相同优先级的线程间采用时间片的轮转调度算法进行调度,使每个线程运行相同时间;另外调度器在寻找那些处于就绪状态的具有最高优先级的线程时,所经历的时间是恒定的,系统也不限制线程数量的多少,线程数目只和硬件平台的具体内存相关。
2. 时钟管理
GoupOS的时钟管理以时钟节拍为基础, 时钟节拍是操作系统中最小的时钟单位。GoupOS的定时器提供两类定时器机制:第一类是单次触发定时器, 这类定时器在启动后只会触发一次定时器事件, 然后定时器自动停止。 第二类是周期触发定时器,这类定时器会 周期性地触发定时器事件, 直到用户手动停止定时器, 否则将永远待续执行下去。
另外, 根据超时函数执行时所处的上下文环境,GoupOS的定时器 可以设置为HARD_TIMER模式或者SOFT_TIMER模式。
通常使用定时器定时回调函数(即超时函数), 完成定时服务。 用户根据自己对定时处理的实时性要求选择合适类型的定时器。
3. 线程间同步
GoupOS采用信号量、互斥量与事件集实现线程间同步。 线程通过对信号量、互斥量的获取与释放进行同步;互斥量采用优先级继承的方式解决了实时系统常见的优先级翻转问题。 线程同步机制支持线程按优先级等待或按先进先出方式获取信号量或互斥量。 线程 通过对事件的发送与接收进行同步;事件集支待多事件的 ”或触发” 和 ”与触发”,适合线 程等待多个事件的情况。
4. 线程间通信
GoupOS目前只支持支持邮箱通信机制。 邮箱中一封邮件能够接收非固定长度的消息。并把邮件缓存在自己的内存空间中。邮箱的发送动作可安全用于中断服务例程中。 通信机制支持线程按优先级等待或按先进先出方式获取。
5. 内存管理
GoupOS目前只支持静态内存池管理。当静态内存池具有可用内存时,系统对内存块分配的时间将是恒定的;当静态内存池为空时,系统将申请内存块的线程挂起或阻塞掉(即线程等待一段时间后仍未获得内存块就放弃申请并返回,或者立刻返回。等待的时间取决千申请内存块时设置的等待时间参数),当其他线程释放内存块到内存池时,如果有挂起的待分配内存块的线程存在的话,则系统会将这个线程唤醒。
2. GoupOS启动流程
要了解一份代码大多从启动部分开始,这里也采用这种方式,先寻找启动的源头。以MDK-ARM为例,MDK-ARM的用户程序入口为main()函数,位于main.c文件中。系统启动后先从汇编代码startup_stm32f429_439xx.s开始运行,然后跳转到C代码,进行GoupOS系统功能初始化,最后进入用户程序入口main()。启动流程如下图所示。
这部分启动代码大致可以分为4个部分:
(1) 初始化与系统相关的硬件;
(2) 初始化系统内核对象,例如定时器、调度器、信号;
(3) 创建main线程,在main线程中对各类模块依次进行初始化;
(4) 初始化定时器线程、空闲线程,并启动调度器。
3. GoupOS程序内存分布
一般MCU包含的存储空间有片内Flash与片内RAM,RAM相当于内存,Flash相当于硬盘。编译器会将一个程序分类为好几个部分,分别存储在MCU不同的存储区。
Keil工程在编译完之后,会有相应的程序所占用的空间提示信息,如下图
图中提到Program Size包含以下几部分:
(1) Code:代码段,存放程序的代码部分。
(2) RO-data:只读数据段,存放程序中定义的常量。
(3) RW-data:读写数据段,存放初始化为非0值的全局变最。
(4) ZI-data: 0数据段,存放未初始化的全局变最及初始化为0的变最。
程序编译完成后会生成一个.map文件,该文件说明了各个函数占用的尺寸和地址,在该文件的最后几行也说明了上面几个字段的关系:
Total RO Size (Code + RO Data) 13840 ( 13.52kB)
Total RW Size (RW Data + ZI Data) 28272 ( 27.61kB)
Total ROM Size (Code + RO Data + RW Data) 13964 ( 13.64kB)
(1) RO Size包含了Code及RO-data,表示程序占用Flash空间的大小;
(2) RW Size包含了RW-data及ZI-data,表示运行时占用的RAM的大小;
(3) ROM Size包含了Code、ROData以及RWData,表示烧写程序所占用的Flash空间的大小。
程序运行之前,需要有文件实体被烧录到STM32的Flash中,一般是bin或者hex文件,该被烧录文件称为可执行映像文件。
4. GoupOS内核对象管理架构
GoupOS采用内核对象管理系统来访问/管理所有内核对象, 内核对象包含内核中绝大部分设施, 这些内核对象可以是静态分配的静态对象。
通过这种内核对象的设计方式,GoupOS做到了不依赖于具体的内存分配方式, 系统的灵活性得到了极大的提高。
GoupOS内核对象包括线程、信号景、互斥量、事件、邮箱、消息队列和定时器等。对象容器中包含每类内核对象的信息,包括对象类型、大小等。对象一个链表,所有的内核对象都被链接到该链表上,GoupOS的容器给每类内核对象分配了,目前该部分功能预留,未完成后续开发完成该功能。
5. GoupOS内核配置示例
GoupOS的一个重要特性是高度可裁剪性,支待对内核进行精细调整,对组件进行灵活拆卸。其配置主要通过修改工程目录下的GoupOSconfig.h文件来进行,用户可以通过打开/关闭该文件中的宏定义来对代码进行条件编译,最终达到系统配置和裁剪的目的,如下所示。
- GoupOS内核部分。
GoupOSconfig.h 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117/*系统自述*/
#define OS_SPLITLINE "----------------------------------------------------------------------------------\n"
#define OS_NAME "本套嵌入式系统名称: GoupOS 、Goup_OS 、Goupos\n"
#define OS_AUTHOR_MAIL "author:XGM mailbox:xgmcreate@foxmail.com\n"
#define OS_VERSION "version:V1.111(版本号说明主版本号、子版本号、修正版本号、开发版本号)\n"
#define OS_INFO "本嵌入式系统正在规模测试中,如果使用遇到任何问题,请发邮件到作者邮箱中,作者会及时解决\n"
/**
* @brief 定义预备,防止移植代码缺失该部分定义
* 关键字的宏定义,
*
*/
#define __IO volatile /*!< Defines 'read / write' permissions */
#define weak __attribute__((weak)) /*<!弱定义宏*/
/**
* @brief 系统的启动流程,以及任务信息
*
*/
#define OS_STARTUPINFO 1
/**
* @brief OS的使能与关闭
*/
#define OS_ENABLE (1)
#define OS_DISABLE (0)
/* System time base. to configure */
/*<!系统时钟*/
#define CPU_CLOCK_HZ (180000000)
/*<!系统每秒钟滴答次数*/
#define OS_1S_TICKS (1000)
/*<!系统时基*/
#define OS_TIME_BASE (CPU_CLOCK_HZ/OS_1S_TICKS)
/*<!系统最小时间单位*/
#define OS_SYSTICK_MS (1)
/*<!滴答次数*/
#define TICKS_PER_SEC (1000/OS_SYSTICK_MS)
/* 系统内部配置区域 */
//目前支持最大的优先级数量 位图目前也只支持32
#define TINYOS_PRO_COUNT (32) /*<!优先级*/
/*<!关于优先级的宏定义,建议不要修改*/
#define OS_PRI (0)
/*<!0:不压缩系统 1:压缩系统(暂时不可使用)时间换空间*/
#define SMALL_OS (0)
/**
* @brief 判断芯片是否有FPU功能,如果有FPU功能:启动或者关闭FPU功能
* OS_ARM_FPU_ENABLE: OS_ENABLE 启动FPU功能
* OS_DISABLE关闭FPU功能
* 启动FPU功能时,keil同时设置 Floating Point Hardware :Single Precision
*/
#define OS_ARM_FPU_ENABLE OS_ENABLE
/*<!Thread FAULT off or on*/
#define THREAD_FAULT (0)
/*<!delay mode select 0:独立保存延时时间,1:递增的延时队列(更快)*/
#define DELAY_MODE (0)
/*1:OS build add Security code; 0:OS build do not add Security code*/
#define OS_ADD_SECURITY_CODE (1)
/**
* @brief 要求实时性高,那么只会启动部分安全代码;实时性要求不高,可以启动全部安全代码,也可以不全部启动
* 1:启动高实时性,部分安全代码关闭,
* 0:关闭高实时性但是添加全部安全代码,导致代码增大
*/
#define OS_HIGH_REAL_TIME (1)
/**
* @brief 所有组件名称长度,默认情况下使用“OS_ALLNAME_LENGTH”宏,如果长度不够可自行定义
* 该部分宏定义,不能删除,否则可能系统出错
*/
#define OS_ALLNAME_LENGTH (32) /*<!待修改*/
#define OS_SEMNAME_LENGTH OS_ALLNAME_LENGTH /*<!信号量名称长度*/
#define OS_TASKNAME_LENGTH OS_ALLNAME_LENGTH /*<!任务名称长度*/
#define OS_MAILNAME_LENGTH OS_ALLNAME_LENGTH /*<!邮箱任务名称长度*/
#define OS_FLAGGROUP_LENGTH OS_ALLNAME_LENGTH /*<!邮箱任务名称长度*/
#define OS_MUTEX_LENGTH OS_ALLNAME_LENGTH /*<!互斥信号量名长度*/
#define OS_TIMERNAME_LENGTH OS_ALLNAME_LENGTH /*<!定时器名长度*/
/**
系统的空闲任务配置
*/
#define OS_IDLETASK_STACK_SIZE (1024)
/**
* @brief 定时器任务的线程栈
* 启动中断定时器
* 启动软件定时器
* 定时器任务优先级不能与空闲线程任务优先级相同,不然空闲定时器与空闲任务是在最低优先级运行而且是按照时间片运行
*/
#define OS_TIMERMODULE_INIT (1)
#define OS_STARTHARD_TIMER (1)
#define OS_STARTSOFT_TIMER (1)
#define OS_TIMERTASK_STACK_SIZE (1024)
#define OS_TIMERTASK_PRIO (1)
/**
* @brief 内核模块裁剪
* 1:打开相应的功能模块
* 0:关闭相应的功能模块
*/
/*<!控制是否裁剪信号量功能模块*/
#define GOUPOS_ENABLE_SEM (1)
/*<!控制是否裁剪邮箱功能模块*/
#define GOUPOS_ENABLE_MAILMSG (1)
/*<!控制是否裁剪内存功能模块*/
#define GOUPOS_ENABLE_MEMBLOCK (1)
/*<!控制是否裁剪事件标志组功能模块*/
#define GOUPOS_ENABLE_EVENTFLAGGROUP (1)
/*<!控制是否裁剪互斥锁功能模块*/
#define GOUPOS_ENABLE_MUTEX (1)
/*<!控制是否裁剪定时器功能模块*/
#define GOUPOS_ENABLE_TIMER (1)
/*<!控制是否裁剪CPU使用率功能模块*/
#define GOUPOS_ENABLE_CPUUSAGE_STAT (1)
/*<!控制是否裁剪钩子函数功能模块*/
#define GOUPOS_ENABLE_HOOKS (1)
6. GoupOS常用宏定义说明
GoupOS实时操作系统暂时无该部分宏定义,后续可能扩展,保留当前章节。