找回密码
 立即注册
查看: 1785|回复: 11

Ai8051U单片机,从入门到精通(9):金山151-RTOS单片机实时多任务操作系统

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-9-13 18:32:08 | 显示全部楼层 |阅读模式
一、简介
(1)金山151-RTOSV1.1(以下简称金山151)是笔者专门为AI8051U单片机8BIT模式写的RTOS。Ai8051U单片机的8BIT模式使用8051指令集,在片上就有32KB的XDATA存储器,特别适合运行RTOS
(2)金山151是为RTOS初学者准备的定制版:它具有5个实时任务,每个任务具有3KB的位于XDATA区域的任务堆栈空间
(3)由于AI8051U只有2KB的EDATA空间,如果在32BIT模式下实现RTOS,全部任务堆栈空间加起来也不能超过2KB的EDATA空间,因此对于AI8051U单片机,只适合使用8BIT模式实现RTOS
(4)金山151是一个完整的功能强大的RTOS操作系统,除了有5个实时任务 外,还有4个前台定时任务,有2个系统定时器中断钩子和一套完整的系统时间部分。
并且为了实现信息的实时显示和RTOS的动态调试(代替静态仿真),金山151内部集成了一个完整的8位数码管显示驱动程序。
(5)金山151-RTOS使用STCIDE作为编写程序和项目管理的IDE软件,使用金水151作为C语言编译器,使用AIAPP-ISP为辅助编程和烧录软件。附录中给出了STCIDE集成开发环境,解压后可以参照其中的说明使用。
二、最小空任务框架

(6)本文关于金山151-RTOS编程方法的第一篇,介绍它在AI8051U实验箱上实现的最小空任务框架。该框架只有显示当前的系统时间和一个心跳灯的功能,其运行效果的视频如下:


(7)金山151-RTOS采用将整个系统封装为OBJ模块的方式提供。
单片机RTOS的运行需要一整套完整的系统来支持,比如系统中断,核心代码、任务程序架构以及系统初始化等等,考虑到AI8051U是一类新的单片机,其上面的的RTOS不能全盘照抄8051单片机上的各种RTOS,同时考虑到初学者需要通过逐渐地学习才能深入地掌握RTOS的理论知识和编程方法,因此金山151-RTOS将各种建立和初始化RTOS的运行环境的程序和单片机启动的“main”函数一起封装,只留下建立用户自己的运行系统的框架供用户填写自己的程序和新增自己的程序

(8)金山151-RTOS最小系统包括以下文件:
Fig_01_系统文件.jpg
其中“main.c”是用户的主程序,“RTOS_FTask.c”是用户的前台定时任务程序,“RTOS_RTask.c”是用户的实时多任务程序,“JS151_Mini_8Bit_V11_18K6T.OBJ”是金山151-RTOS最小系统的二进制模块文件,“JS151_DRV_DIG8_AI8U_V12.c”是专门为AI8051U实验箱的8位数码管写得动态刷新函数。

(9)金山151-RTOS程序文件的开头声明部分如下:
Fig_02_系统声明.jpg
上面图中第17行是一个固定格式的单片机类型模式声明,用来指导编译器按给的的单片机类型模式将C语言编译成为对应的机器指令。
定义中“MCU_DEFINE”是一个固定的关键字,表示这一行宏定义程序是一个单片机类型模式定义。17行中的“STC8U_8BIT”指定编译目标是AI8051U单片机的8BIT模式代码。17行中的“32000”是指定编译器可使用的XDATA空间上限,这个上限之上的XDATA空间编译器不得使用,留给用户自己做特殊用途。
(10)金水151编译器是一个面向模块的编译器,意思是每一个源程序文件对应一个模块,对于不同的模块,可以指定的目标单片机类型模式。因此使用金水151编译器时,每一个源程序的开头都要有上面17行那样的单片机类型模式定义语句。
比如你想让某个数码管驱动程序模块同时支持AI8051U单片机和STC8H单片机,那么单片机类型模式就应该指定为“INTEL_8051”模式,这样金水151编译出的代码就不会出现MDU32和TFPU32加速器的指令,在两种类型的单片机上都可以使用。
(11)金山151-RTOS系统主函数“JS151_main()”是系统提供的用于进行用户设置的钩子函数,类似于“Arduino”编程中的“setup()”函数。系统从单片机主函数“main()”开始执行,进行了RTOS系统的建立与设置后,调用这个“JS151_main()”函数后,就启动多任务调度系统,RTOS正式开始运行。

本范例的“JS151_main()”函数程序如下图:
Fig_03_主函数.jpg
其中第34行到第43行是LOGO和测试程序,取消第36行和43行的注释可以测试软件延迟函数“JS151_Delay_MS”的延时精确性。
第46行到第50行是让5个实时任务都处于就绪状态,等等进行任务调度。
加电是第56行程序将系统时间设置为第0天的“23:59:55”,这样就很容易观察到系统时间的每天进位。

(12)金山151-RTOS系统提供给用户两个硬件中断钩子函数,用户可以在其中编程完成自己的各种任务。下图是这两个钩子函数的接口程序:
Fig_04_钩子函数.jpg
上面图中的“/*{ A351”和“}*/”语句对是表明其中的程序是A351汇编语言程序,免得其他编译器产生错误的理解。必须注意的是每个这种嵌入式汇编语句都需要像C语言一样,用分号做结尾。
(13)金山151-RTOS系统使用定时器0的不可屏蔽中断模式3作为系统中断,系统中断采用8KHz的中断频率,用来进行不可中断的系统任务处理。由于该中断是不可屏蔽的且频率较高,因此用户要避免在第64行开始的钩子函数中放处理时间长的程序。
(14)金山151-RTOS系统使用外中断INT3作为1KHz的系统节拍中断,在每个节拍中进行前台定时任务处理和实时任务调度。前面第66行和第77行程序是测试程序,通过连接P00和P01的LED灯可以测量到这两个中断是否工作正常。

(15)4个前台定时任务的钩子函数在文件“RTOS_FTask.c”中定义:
Fig_05_前台任务.jpg
其中1KHz的钩子函数可以作为1毫秒的计数器使用,500Hz的钩子函数可以作为8位数码管的动态刷新用,40Hz的钩子函数可以作为检测键盘的外设状态用,而4Hz的钩子函数可以作为各个任务的秒信号同步用。

(16)金山151-RTOS预先定义了5个实时任务,这5个实时任务已经预定义在源程序文件“RTOS_RTask.c”,本范例的具体程序见下图:
Fig_06_实时任务.jpg
图中任务0到任务3都是空任务,其中“JS151_OS_Task_Suspend(JS151_PRIO_SELF);”语句的意思是将任务自己挂起。用户将来可以用自己的程序来代替它,实现自己的功能。
(17)RTOS的空闲任务函数很特殊,其程序如果写不好容易造成系统崩溃,因此笔者决定在金山151中空闲任务函数不向用户开放。这样优先级最低的实时任务4就成为用户留守任务,当其他所有任务都都未就绪时执行该任务。
最简单的留守任务就是本范例给出对一个1毫秒的计数变量进行计数,并且利用这个计数变量按1秒钟的周期闪烁生命灯。
附件1:STCIDE-金水151_V22 单片机集成开发环境
附件1_STCIDE-金水151_V22.rar (14.58 MB, 下载次数: 186)
附件2:实验箱AI8051U-SCH-20240820电路图
附件2_实验箱AI8051U-SCH-20240820.pdf (297.14 KB, 下载次数: 115)

附件3:本文范例金山151_空任务_AI8051U_BOX_V12_STCIDE
附件3_金山151_空任务_AI8051U_BOX_V12_STCIDE.rar (130.65 KB, 下载次数: 135)

1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:176
  • 最近打卡:2025-02-19 17:24:49

15

主题

265

回帖

1387

积分

金牌会员

积分
1387
发表于 2024-9-20 08:05:03 | 显示全部楼层
好好学习一番。突击一番。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-17 09:50:59

17

主题

91

回帖

755

积分

高级会员

积分
755
发表于 2024-9-20 09:27:05 | 显示全部楼层
32bit 也可以使用 32K 的Xdata 空间吧?

点评

(1)由于C251将可重入函数堆栈放在EDATA空间,所以受C251编译器的限制,如果要使用RTOS实时多任务操作系统,则每个任务的堆栈空间不能超过EDATA空间的大小。 (2)具体到AI8051U-32BIT模式,如果采用C251编译器,如  详情 回复 发表于 2024-9-20 09:57
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-9-20 09:57:35 | 显示全部楼层
zh*** 发表于 2024-9-20 09:27
32bit 也可以使用 32K 的Xdata 空间吧?

(1)由于C251将可重入函数堆栈放在EDATA空间,所以受C251编译器的限制,如果要使用RTOS实时多任务操作系统,则每个任务的堆栈空间不能超过EDATA空间的大小。
(2)具体到AI8051U-32BIT模式,如果采用C251编译器,如果使用RTOS,那么每个任务的堆栈空间只能少于EDATA的2KB空间。
(3)由于金水151编译器是将可重入函数堆栈放在XDATA空间,AI8051U的8BIT模式与EDATA空间无关,所以金山151-RTOS的每个任务堆栈空间可以设为3KB毫无问题。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-17 09:50:59

17

主题

91

回帖

755

积分

高级会员

积分
755
发表于 2024-9-20 10:02:13 | 显示全部楼层
杨*** 发表于 2024-9-20 09:57
(1)由于C251将可重入函数堆栈放在EDATA空间,所以受C251编译器的限制,如果要使用RTOS实时多任务操作系 ...

你用的是真正的SP堆栈,不是自己模拟的一个数据区
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-17 09:50:59

17

主题

91

回帖

755

积分

高级会员

积分
755
发表于 2024-9-20 10:17:06 | 显示全部楼层
我看了一下你的编译器,你这个工作量可不小啊,大部分语法和Keil一致吧?

点评

研制C351编译器用了十年时间,C351的语法是C51/C251语法的一个子集,最重要的是去掉了malloc之类的内存管理语句,代替的是内存动态分配采用新的可以自动回收废弃空间的VP(虚拟空间指针)方式。以后会逐渐介绍这些高  详情 回复 发表于 2024-9-20 12:13
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-9-20 12:13:14 | 显示全部楼层
zh*** 发表于 2024-9-20 10:17
我看了一下你的编译器,你这个工作量可不小啊,大部分语法和Keil一致吧?

研制C351编译器用了十年时间,C351的语法是C51/C251语法的一个子集,最重要的是去掉了malloc之类的内存管理语句,代替的是内存动态分配采用新的可以自动回收废弃空间的VP(虚拟空间指针)方式。以后会逐渐介绍这些高级语法功能
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-17 09:50:59

17

主题

91

回帖

755

积分

高级会员

积分
755
发表于 2024-9-20 15:53:07 | 显示全部楼层
本帖最后由 zhx 于 2024-9-20 16:03 编辑
杨*** 发表于 2024-9-20 12:13
研制C351编译器用了十年时间,C351的语法是C51/C251语法的一个子集,最重要的是去掉了malloc之类的内存管 ...

单片机上,我一般都是 先静态分配一个大数组,然后在数组上做自己的二次分配,不敢用 malloc
对数组内存的引用,我用指针的指针,就是引用通过一个索引表,索引表里是数据真正的地址,收集碎片就是改变索引表内容,这样外部的引用通过索引表间接完成,只要没有应用引用索引表的数据,我就可以改变数组内数据的内容,而不引起外部引用的变化

点评

(1)对于一般的C语言编译器,这是一种迫不得已的正确方法,FreeRTOS等RTOS都采用这种方法来满足建立/移除任务和数据缓冲区的需求。 (2)金水151是一个使用了多种新技术的C语言编译器,对于函数堆栈使用了“BP+VP  详情 回复 发表于 2024-9-20 17:34
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-9-20 17:34:10 | 显示全部楼层
本帖最后由 杨为民 于 2024-9-20 17:47 编辑
zh*** 发表于 2024-9-20 15:53
单片机上,我一般都是 先静态分配一个大数组,然后在数组上做自己的二次分配,不敢用 malloc
对数组内存的引 ...

(1)对于一般的C语言编译器,这是一种迫不得已的正确方法,FreeRTOS等RTOS都采用这种方法来满足建立/移除任务和数据缓冲区的需求。

(2)金水151是一个使用了多种新技术的C语言编译器,对于函数堆栈使用了“BP+VP”的双指针技术,所以无论是否使用RTOS,都可以实现动态数据区域分配和自动回收,不会留下碎片和空隙,也就不再需要数据堆管理。
(3)目前金水151的所有需要数据缓冲区的库函数都使用了这种方法,既保证了除了“scanf”和“printf”这两个函数外,所有库函数都是可重入的,又不需要引入堆空间管理功能。
(4)采用“BP+VP”的双指针技术的目的为各种大规模DSP数据处理程序使用的,等到有“DPU32”等指令的新单片机出来后,会专文介绍其用法。
(5)由于采用“BP+VP”的双指针技术的,所以金山151-RTOS在进行任务切换时都要保存/恢复这两个指针(见下图),这是与论坛中其他采用C51编译器的RTOS的重大区别:
Fig_001_双堆栈指针.jpg


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:372
  • 最近打卡:2025-05-01 10:53:48

12

主题

125

回帖

1685

积分

金牌会员

积分
1685
发表于 2024-10-10 20:28:20 | 显示全部楼层
强烈围观    虽然不懂高深技术,但是强烈支持,STCIDE完全可以升级周立功的TKStudio IDE,代码编辑,菜单等使用很方便,
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 19:50 , Processed in 0.156446 second(s), 114 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表