STM32F103C8T6基于HAL库移植uC/OS-III实现多任务

前言

学习嵌入式实时操作系统(RTOS),以uc/OS为例,将其移植到stm32F103上,构建至少3个任务(task):其中两个task分别以1s和3s周期对LED灯进行点亮-熄灭的控制;另外一个task以2s周期通过串口发送“hello uc/OS”。记录详细的移植过程。

一、简介

1、计算机操作系统

从用户的角度来看操作系统(Operation System,OS)的作用主要有:

作用 具体说明
作用1 ①对计算机底层硬件进行封装和功能的扩充②操作系统对硬件进行了封装和隔离,只对用户提供一个简单有效的抽象接口,即用户与计算机之间的接口。
作用2 ①管理计算机资源;②程序运行时可使用的软、硬件环境统称为资源; ③硬件:资源可以CPU、寄存器和1/0设备; ④软件:资源可以是一个变量、一个结构或一个数组等。

操作系统主要有五大管理功能

  1. 进程管理(CPU管理)
    进程控制;任务调度;任务同步;任务通信;目标:公平、非阻塞、优先级
  2. 存储管理
    包括:内存分配、内存保护、地址映射和内存扩充。嵌入式操作系统:实模式和保护模式。
  3. 设备管理
    进行缓冲管理、设备分配和处理等管理,目的是屏蔽不同设备的差异性
  4. 文件管理
    为用户提供文件存储空间的存储管理、目录管理、文件的读/写管理以及文件的共享与保护等功能
  5. 作业管理 (接口管理)
    用户通过操作系统提供的接口来访问计算机的硬件资源。 主要有命令接口、程序接口和图形用户接口GUI等。

2、嵌入式操作系统

嵌入式操作系统(Embedded Operating System,EOS)是指
用于嵌入式系统的操作系统。
一般会有一个内核(Kernel),内核是指系统的一个组件,包含了操作系统的最基本、最主要功能,比如任务管理、存储管理、I/O设备管理等。
嵌入式操作系统常见的有:
VxWorks、uC/OS-III、RTOS、QNX、embOs、FreeRTOS、WinCE、Linux 、Android、iOS

μTenux
μTenux [1] 是一款开源免费的硬实时嵌入式操作系统,开发团队来自大连,主要针对ARM Cortex M0-M4系列的微控制器。其内核采用上世纪80年代就出现的μT-Kernel。在全球嵌入式最发达的日本,μT-Kernel拥有60%的占有率。同时tecoss中国开源社区还推出了Tenux,针对ARM Cortex的R系列和A系列。目前,悠龙软件是世界知名公司ARM的合作伙伴,还是Ti、ATMEL、ST、T-Engine、Neusoft、Tianfusoftwarepark、TEG、Parasoft etc.芯片厂商的合作伙伴。目前,官方提供的μTenux稳定版代码为V1.5.00r160。
DJYOS
DJYOS是一个嵌入式实时操作系统,没有考虑在通用计算机/服务器上与windows、linux、unix竞争。
DJYOS操作系统是以事件为核心进行调度的,这种调度策略使程序员可以按人类认知事物的习惯而不是计算机的习惯来编程。
普通操作系统中,调度是以线程为核心的,事件被作为线程的数据,标榜为“事件触发”的软件模型,也是由线程在一旁候着,待特定事件发生时线程恢复运行并把它作为输入数据加以处理。
以事件为核心的调度,则像设备和内存一样,把线程虚拟机作为处理事件所需要的资源看待,当某事件需要处理时,分配或者创建一个线程虚拟机给该事件,并启动该线程虚拟机处理事件。
在嵌入式领域,DJYOS要与非实时操作系统如linux、wince竞争,以及实时操作系统如vxworks、qnx等竞争。
DJYOS的目标,是改变中国无(有影响力的)操作系统局面,在不久的将来,世界上流行的操作系统中,有一个来自中国。
VxWorks
VxWorks是美国WindRiver公司的产品,是目前嵌入式系统领域中应用很广泛,市场占有率比较高的嵌入式操作系统。
VxWorks实时操作系统由400多个相对独立、短小精悍的目标模块组成,用户可根据需要选择适当的模块来裁剪和配置系统;提供基于优先级的任务调度、任务间同步与通信、中断处理、定时器和内存管理等功能,内建符合POSIX(可移植操作系统接口)规范的内存管理,以及多处理器控制程序;并且具有简明易懂的用户接口,在核心方面甚至可以微缩到8 KB。
μC/OS-II
μC/OS-II是在μC-OS的基础上发展起来的,是美国嵌入式系统专家Jean J.Labrosse用C语言编写的一个结构小巧、抢占式的多任务实时内核。μC/OS-II能管理64个任务,并提供任务调度与管理、内存管理、任务间同步与通信、时间管理和中断服务等功能,具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点。
μClinux
μClinux是一种优秀的嵌入式Linux版本,其全称为micro-control Linux,从字面意思看是指微控制Linux。同标准的Linux相比,μClinux的内核非常小,但是它仍然继承了Linux操作系统的主要特性,包括良好的稳定性和移植性、强大的网络功能、出色的文件系统支持、标准丰富的API,以及TCP/IP网络协议等。因为没有MMU内存管理单元,所以其多任务的实现需要一定技巧。
eCos
eCos(embedded Configurable operating system),即嵌入式可配置操作系统。它是一个源代码开放的可配置、可移植、面向深度嵌入式应用的实时操作系统。最大特点是配置灵活,采用模块化设计,核心部分由小同的组件构成,包括内核、C语言库和底层运行包等。每个组件可提供大量的配置选项(实时内核也可作为可选配置),使用eCos提供的配置工具可以很方便地配置,并通过不同的配置使得eCos能够满足不同的嵌入式应用要求。
RTXC
RTXC是C语言的实时执行体(Real-Time eXecutive in C)的缩写。它是一种灵活的、经过工业应用考验的多任务实时内核,可以广泛用于各种采用8/16位单片机、16/32位微处理器、DSP处理器的嵌入式应用场合。中国单片机公共实验室“经过几年的考察,认为比较适合中国的国情后,引入中国市场的”嵌入式实时多任务操作系统两者之一。

相比PC机操作系统,嵌入式操作系统具有以下的特点

  1. 微型化:嵌入式系统体积小,系统资源受限,要求嵌入式操作系统本身不能占用过多的存储空间和资源。
  2. 可裁剪性:嵌入式系统应用环境差异很大,功能要求也各不相同,所以能够根据实际需求删减不需要的功能。
  3. 实时性强和可靠性高:对实时性要求较高,且要求具备一定的抗干扰能力,可靠性高。
  4. 易移植:为满足多种硬件平台的统一性,要求嵌入式操作系统具有一定的可移植性。

分类
在这里插入图片描述
在这里插入图片描述
uC/OS-Ⅲ就是一个基于优先级的抢占式多任务实时操作系统。

插入

1、总体介绍

在嵌入式应用领域,很多场合对系统的实时性要求严格,因此操作系统的选择要基于实时系统。实时多任务操作系统(Real Time Operating System,简称RTOS)是根据操作系统的工作特性而言的,实时是指物理进程的真实时间。
实时操作系统是指具有实时性,能支持实时控制系统工作的操作系统。其首要任务调度一切可利用的资源完成实时控制任务,其次才着眼于提高计算机系统的使用效率,重要特点是要满足对时间的限制和要求。 通常对于分时操作系统,软件的执行在时间上的要求并不严格,时间上的错误一般不会造成灾难性的后果。但对于实时操作系统,主要任务是要求对事件进行实时的处理,虽然事件可能在无法预知的时刻到达.但是软件上必须在事件发生时能够在严格的时限内做出响应(系统响应时间),即使能够响应,但是如果超出了时限,系统时间响应的超时就意味着致命的失败。实时操作系统的重要特点是具有系统的可确定性,即系统能对运行情况的最好和最坏等情况能做出精确的估计。
实时多任务操作系统(RTOS)是嵌入式应用软件的基础和开发平台。大多数嵌入式开发还是在单片机上直接进行,没有RTOS,但仍要有一个主程序负责调度各个任务。RTOS是一段嵌入在目标代码中的程序,系统复位后首先执行,相当于用户的主程序,用户的其他应用程序都建立在RTOS之上。不仅如此,RTOS还是一个标准的内核,将CPU时间、中断、I/O、定时器等资源都包装起来,留给用户一个标准的API(系统调用),并根据各个任务的优先级,合理地在不同任务之间分配CPU时间。
RTOS是针对不同处理器优化设计的高效率实时多任务内核,RTOS可以面对几十个系列的嵌入式处理器MPU、MCU、DSP、SOC等提供类同的API接口,这是RTOS基于设备独立的应用程序开发基础。因此,基于RTOS的C语言程序具有极大的可移植性。据专家测算,优秀RTOS上跨处理器平台的程序移植只需要修改1%~4%的内容。在RTOS基础上可以编写出各种硬件驱动程序、专家库函数、行业库函数、产品库函数,和通用性的应用程序一起,可以作为产品销售,促进行业的知识产权交流。因此,RTOS又是一个软件开发平台。

2、发展过程

实时操作系统(RTOS)的研究是从20世纪60年代开始的。从系统结构上看,RTOS到现在已经历了如下三个阶段:

  • 早期的实时操作系统
    早期的实时操作系统,还不能称为真正的RTOS,它只是小而简单的、带有一定专用性的软件,功能较弱,可以认为是一种实时监控程序。它一般为用户提供对系统的初始化管理以及简单的实时时钟管理,有的实时监控程序也引入了任务调度及简单的任务间协调等功能,属于这类实时监控程序的有RTMX等。这个时期,实时应用较简单,实时性要求也不高。应用程序、实时监控程序和硬件运行平台往往是紧密联系在一起的。
  • 专用实时操作系统
    专用实时操作系统,随着应用的发展,早期的RTOS已越来越显示出明显的不足了。有些实时系统的开发者为了满足实时应用的需要,自己研制与特定硬件相匹配的实时操作系统。这类专用实时操作系统在国外称为Real—Time
    Operating System Developed in
    House。它是在早期用户为满足自身开发需要而研制的。一般只能适用于特定的硬件环境,且缺乏严格的评测,移植性也不太好。属于这类实时操作系统的有Intel公司的iMAX86等。
  • 通用实时操作系统
    在各种专用RTOS中,一些多任务的机制如基于优先级的调度、实时时钟管理、任务间的通信、同步互斥机构等基本上是相同的,不同的只是面向各自的硬件环境与应用目标。实际上,相同的多任务机制是能够共享的,因而可以把这部分很好地组织起来,形成一个通用的实时操作相同内核。这类实时操作系统大多采用软组件结构,以一个个软件“标准组件”构成通用的实时操作系统,一方面,在RTOS内核的最底层将不同的硬件特性屏蔽掉;另一方面.对不同的应用环境提供了标准的、可剪裁的系统服务软组件。这使得用户可根据不同的实时应用要求及硬件环境选择不同的软组件,也使得实时操作系统开发商在开发过程中减少了重复性工作。这类通用实时操作系统,有Integrated
    System公司的psosystem,Intel公司的iRMX386,Ready
    System公司(后与MicrotecResearch合并)的VRTX32,WindRiver
    SystomS公司(位于美国加州Almeda市)的VxworkS,Accelerated Technology Inc公司的NuclouS
    PLUS等。它们一般都提供了实时性较好的内核、多种任务通信机制、基于TCP/IP的网络组件、文件管理及I/O服务,提供了集编辑、编译、调试、仿真为一体的集成开发环境,支持用户使用C、C++进行应用程序的开发。

3、功能

3.1任务管理

分时操作系统中的基本调度单位一般是进程(或者线程),而对于实时操作系统,操作系统内核调度的基本单位就是任务。任务一般由任务控制块、程序区、数据区、堆栈区组成,对于多数实时操作系统来说,堆栈一般又分为系统堆栈和用户堆栈。系统堆栈用于任务做系统调用访问系统核心时用到的堆栈,把它从用户堆栈中独立出来,是为了保证系统核心的安全性。任务的驱动一般是基于消息或者事件的.即任务的设计是按照依次处理可能接收到的消息和事件,周而复始轮询循环的。实时操作系统中的任务有四种状态:运行(Executing),就绪(Ready),挂起(Suspended),冬眠(Dormant)。 1)运行:获得CPU控制权。 2)就绪:进入任务等待队列,通过调度转为运行状态。 3)挂起:任务发生阻塞,移出任务等待队列,等待系统实时事件的发生而唤醒,从而转为就绪或运行。 4)冬眠:任务完成或错误等原因被清除的任务,也可以认为是系统中不存在了的任务。 系统中只能有一个任务在运行状态,各任务按级别通过时间片分别获得对CPU的访问权。实时操作系统一个最主要的功能就是多任务管理和基于优先级的任务调度。

3.2任务间同步和通信

主要的实时操作系统的任务间同步和通信的机制有:消息、事件、信号量.而部分实时操作系统仍然在沿用邮箱机制,另外一些实时操作系统提供了共享内存的任务间通信机制。
1)消息机制的概念和分时操作系统没有差别,其基本思想是任务通过系统公用的数据交换区(包括私有消息缓冲区和共用消息缓冲池)来交互任务间需要通信的信息。消息机制的系统调用一般包括消息队列的创建(q—create)、删除(q—delete)、接收消息(q—receive)、发送消息(q—send)、广播消息(q-broadcast)、紧急消息(q—urgency)。大多数实时操作系统支持的消息队列既可以是定长的,也可以是变长的。
2)事件机制适用于任务间需要同步并且通信的数据量不大的情况。一般说来,任务之间的事件通信机制是可以覆盖的,即任务A先后发送二次事件给任务B,如果任务B还没有来得及处理的话,任务B只需要处理一次事件就行了。事件机制的系统调用一般包括发送事件(ev—send)、接收事件(ev—receive)。大多数实时操作系统支持16~32个事件。
3)如同分时操作系统中的信号量一样,实时操作系统提供的信号量机制也是为了解决对于临界资源共享的加锁机制。信号量机制提供了信号量的创建(sm—create)、信号量的删除(sm—delete)、信号量的P操作(sm—p)、信号量的V操作(sm—v)。实时操作系统与分时操作系统在信号量机制上有一个明显的区别,那就是优秀的商用实时操作系统要解决信号量机制的优先级倒置的问题。

3.3内存管理

和分时操作系统一样,实时操作系统会借用CPU的内存管理单元(MMU)来完成内存管理,实时操作系统内存管理模式可以分为实模式与保护模式。主流的实时操作系统一般都可以提供两种模式,让用户根据应用自己选择。一般来说,实时操作系统的内存管理,含有对于内存的优化分配,以尽量减少整个系统的内存占有量的要求。

3.4实时时钟服务

商用的实时操作系统在硬件的硬时钟中断的基础上,提供了实时时钟服务。实时时钟是系统调度的基础,也是系统定时服务器的基础。实时时钟服务一般包括定时唤醒(tm—wkafter或者tm—wkwhen)、定时事件(tm—wevafter或者tm—evwhen)机制。另外,部分优秀的实时操作系统提供了定时消息机制,即应用任务(比如说任务A)向系统定时服务器申请定时器,当定时时间到后,定时服务器返回任务A一条消息。相应的系统调用一般有定时器申请(tm—start)、定时器删除(tm—delete)、定时器重置(tm—restart),定时消息的接收一般采用消息队列的接收机制(q-receive)。是否提供灵活的、高精确度的定时器服务,是衡量实时操作系统功能完整性的一个重要指标。

3.5中断管理服务

如同分时操作系统一样,中断管理服务是操作系统的核心和基本功能。实时操作系统的中断管理有自己的特殊的要求,那就是中断处理程序要更加短小、精悍,以减少中断禁止时间和中断延迟时间。

3、UC/OSIII简单介绍

UCOS是Micrium公司出品的RTOS类实时操作系统, UCOS目前有两个版本:UCOSII和UCOSIII。
UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制,提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。
UCOSIII是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的, UCOSIII结构简洁,可读性很强!非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。
uC/OS-III的任务
在这里插入图片描述
任务(线程)是简单的程序。单CPU 中,在任何时刻只能是一个任务被执行。任务看起来像C 函数。在大多数嵌入式系统中,任务通常是无限循环的。任务不能像C 函数那样,它是不能return 的。
在这里插入图片描述

在UCOSIII中任务就是程序实体,UCOSIII能够管理和调度这些小任务(程序)。UCOSIII中的任务由三部分组成:任务堆栈、任务控制块和任务函数。
任务堆栈:上下文切换的时候用来保存任务的工作环境,就是STM32的内部寄存器值。
任务堆栈是任务的重要部分,堆栈是在RAM中按照“先进先出(FIFO)”的原则组织的一块连续的存储空间。为了满足任务切换和响应中断时保存CPU寄存器中的内容及任务调用其它函数时的需要,每个任务都应该有自己的堆栈。

#define START_STK_SIZE 512 //堆栈大小
CPU_STK START_TASK_STK[START_STK_SIZE]; //定义一个数组来作为任务堆栈
任务堆栈初始化
任务需要恢复现场才能切换回上一个任务并且还能接着从上次被中断的地方开始运行,现场就是CPU的内部各个寄存器。因此在创建一个新任务时,必须把系统启动这个任务时所需的CPU各个寄存器初始值事先存放在任务堆栈中。这样当任务获得CPU使用权时,就把任务堆栈的内容复制到CPU的各个寄存器,从而可以任务顺利地启动并运行。

把任务初始数据存放到任务堆栈的工作就叫做任务堆栈的初始化,UCOSIII提供了完成堆栈初始化的函数:OSTaskStkInit()

当然,用户一般不会直接操作堆栈初始化函数,任务堆栈初始化函数由任务创建函数OSTaskCreate()调用。不同的CPU对于的寄存器和对堆栈的操作方式不同,因此在移植UCOSIII的时候需要用户根据各自所选的CPU来编写任务堆栈初始化函数。

任务控制块:任务控制块用来记录任务的各个属性。
任务控制块是用来记录与任务相关的信息的数据结构,每个任务都要有自己的任务控制块。我们使用OSTaskCreate()函数来创建任务的时候就会给任务分配一个任务控制块。任务控制块由用户自行创建。

OS_TCB StartTaskTCB; //创建一个任务控制块

USOCIII提供了用于任务控制块初始化的函数:OS_TaskInitTCB()。但是,用户不需要自行初始化任务控制块。因为和任务堆栈初始化函数一样,函数OSTaskCreate()在创建任务的时候会对任务的任务控制块进行初始化。

任务函数:由用户编写的任务处理代码,是实实在在干活的,任务函数通常是一个无限循环,也可以是一个只执行一次的任务。任务的参数是一个void类型的,可以可以传递不同类型的数据甚至是函数。
任务函数其实就是一个C语言的函数,但是在使用UCOIII的情况下这个函数不能有用户自行调用,任务函数何时执行执行,何时停止完全有操作系统来控制。

UCOSIII支持时间片轮转调度,因此在一个优先级下会有多个任务,那么我们就要对这些任务做一个管理,这里使用OSRdyList[]数组管理这些任务。

OSRdyList[]数组中的每个元素对应一个优先级,比如OSRdyList[0]就用来管理优先级0下的所有任务。OSRdyList[0]为OS_RDY_LIST类型,从上面OS_RDY_LIST结构体可以看到成员变量:HeadPtr和TailPtr分别指向OS_TCB,我们知道OS_TCB是可以用来构造链表的,因此同一个优先级下的所有任务是通过链表来管理的,HeadPtr和TailPtr分别指向这个链表的头和尾,NbrEntries用来记录此优先级下的任务数量,图5.5.2表示了优先级4现在有3个任务时候的就绪任务列表。
同一优先级下如果有多个任务的话最先运行的永远是HeadPtr所指向的任务。

二、创建HAL库

1、创建工程

1、打开STM32CubeMX创建新的工程
在这里插入图片描述
在这里插入图片描述

2、实现配置
配置RCC
在这里插入图片描述
配置SYS
在这里插入图片描述

设置PC13为GPIO_Output用于点亮LED灯
在这里插入图片描述

设置串口USART1
在这里插入图片描述

设置工程名称、路径等
在这里插入图片描述
在这里插入图片描述

点击右上角图块,并选择打开项目跳转至Keil。
3、检验
在main函数中的while循环里添加语句

while (1)
  {
   
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
		HAL_Delay(500);
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
		HAL_Delay(500);
  }
  /* USER CODE END 3 */

编译,将代码烧录到STM32F103中,BOOT0置零,按下Reset按钮,可以看到PC13LED灯闪烁,证明代码没有问题。

2、准备uCOSIII源码

进入官网下载:http://micrium.com/downloadcenter/
或链接:
链接:https://pan.baidu.com/s/1eUpNs2svykxZYDqcIQur2g
提取码:x2ft
网盘下载,打开目录如下(文件夹uC-BSP和uC-CONFIG是自己新建的两个文件夹)

三、移植过程

1、移植前准备

1.为uC-BSP文件夹新建bsp.c和bsp.h文件(若通过网盘链接下载就已经存在)
2.从以下路径复制图中指定文件添加到下载的文件中的文件夹uC-CONFIG里面
在这里插入图片描述

将uCOS相关文件(下图框起来的部分)复制到HAL工程的MDK-ARM文件夹下
在这里插入图片描述
复制完成以后的状态:
在这里插入图片描述

2、开始移植

回到Keil打开的HAL工程
1.将uCOS文件添加到项目
点击Manage Project Items
在这里插入图片描述
为项目新建文件夹如下
在这里插入图片描述

分别给新增的文件夹添加文件:
(1)给CPU添加文件
按照如下图中,双击左侧工程栏中的CPU进入弹窗界面,然后选择uc/MDK-ARM/uC-CPU,选择下图框起来的部分进行添加【注意一定要点击add,同时也可以注意选择所有的文件类型,后面也如此】
在这里插入图片描述
然后选择uc/MDK-ARM/uC-CPU/ARM-Cortex-M3/RealView,选择下图框起来的部分进行添加【注意此处点击所有文件,然后点击add
在这里插入图片描述

(2)给LIB添加文件
按照如下图中,双击左侧工程栏中的LIB进入弹窗界面,然后选择uc/MDK-ARM/uC-LIB,选择下图框起来的部分进行添加【注意一定要点击add,同时也可以注意选择所有的文件类型】
在这里插入图片描述
然后选择uc/MDK-ARM/uC-LIB/Ports/ARM-Cortex-M3/RealView,选择下图框起来的部分进行添加【注意此处点击所有文件,然后点击add
在这里插入图片描述
(3)给PORT添加文件
按照如下图中,双击左侧工程栏中的PORT进入弹窗界面,然后选择uc/MDK-ARM/uCOS-Ⅲ/Ports/ARM-Cortex-M3/Generic/RealView,选择下图框起来的部分进行添加【注意一定要点击add,同时也可以注意选择所有的文件类型】
在这里插入图片描述
然后选择uc/MDK-ARM/uCOS-Ⅲ/Source,选择下图框起来的部分进行添加【注意此处点击所有文件,然后点击add
在这里插入图片描述
(4)给CONFIG添加文件
按照如下图中,双击左侧工程栏中的CONFIG进入弹窗界面,然后选择uc/MDK-ARM/uC-CONFIG,选择下图框起来的部分进行添加【注意一定要点击add

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值