ucos

UCOS学习笔记——堆栈

做~自己de王妃 提交于 2019-12-10 00:00:58
堆栈 Cortex-M3堆栈操作 Cortex-M3使用的是**“向下生长的满栈”**模型。堆栈指针SP指向最后一个被压入堆栈的32位数值。在下一-次压栈时, SP先自减4 ,再存入新的数值,如图2.3.1所示。 POP操作刚好相反:先从SP指针处读出,上一次被压入的值,再把 SP指针自增4 。如图2.3.2所示。 在进入ISR时,CM3会自动把一些寄存器压栈,这里使用的是进入ISR之前使用的SP指针(MSP或者是PSP)。离开ISR后,只要ISR没有更改过CONTROL[1],就依然使用先前的SP指针来执行出栈操作。 双堆栈机制 我们已经知道了CM3的堆栈是分为两个: 主堆栈和进程堆栈 , CONTROL[1]决定如何选择。当CONTROL[1]=0时,只使用MSP, 此时用户程序和异常handler 共享同一个堆栈。这也是复位后的缺省使用方式,如图2.3.3所示。 当CONTROL[1]=1时,线程模式将不再使用PSP,而改用MSP(handler模式永远使用MSP) 。此时,进入异常时的自动压栈使用的是进程堆栈,进入异常handler后才自动改为MSP,退出异常时切换同psp,并日从讲程堆栈十弹出数据,如图2.3.4所示: 在特权级下,可以指定具体的堆栈指针,而不受当前使用堆栈的限制,示例代码如下: MRS RO , MSP ; 读取主堆栈指针到RO MSR MSP , RO

STM32F104ZET6之ucosⅢ临界区保护

谁说胖子不能爱 提交于 2019-12-06 00:57:28
UCOSⅢ对临界区的处理方法 1.中断开关的方式 临界区一旦被访问,那么就关闭所有中断,防止执行过程被更高级中断打断 保证了数据的同步性,但可能会导致一些紧急事件未能及时处理 OS_ENTER_CRITICAL()简单地关中断,OS_EXIT_CRITICAL()简单地开中断。 这种方式虽然简单高效,但无法满足嵌套的情况。 如果有多层临界区保护,在退出内层临界区时就会开中断,使外层的临界区也失去保护。 不推荐使用。 2.压栈的方式 临界区在被访问过程中,被中断打断,就对该状态进行压栈处理,保证各个事件按等级正常运行, 但数据无法保证同步性,压栈的数据在出栈时,上次的中断可能已经修改了数据,将数据出栈没有什么意义, 不推荐使用。 3.保存在本地局部变量. 在关中断前,使用局部变量保存中断状态。 一般都用模式三,使用方法如下 //1.定义一个局部变量cpu_sr CPU_SR cpu_sr = (CPU_SR)0; //也可直接调用宏定义一个局部变量cpu_sr //关于这个宏,在cpu.h中303行左右,如下 //#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) //#define CPU_SR_ALLOC() CPU_SR cpu_sr = (CPU_SR)0 //#else //#define

STM32F104ZET6之ucosⅢ常用函数

跟風遠走 提交于 2019-12-05 19:23:49
一、OS的初始化与启动 1.OS初始化,初始化各种内核对象和全局变量 函数原型:void OSInit (OS_ERR *p_err) 参数:p_err,用于返回错误码 返回值:无 它是第一个执行的函数。 2.启动OS,创建任务后调用 函数原型:void OSStart (OS_ERR *p_err) 参数:p_err,用于返回错误码 返回值:无 二、任务的管理 1.创建任务 void OSTaskCreate (OS_TCB *p_tcb,//类似于线程id,控制任务 CPU_CHAR *p_name,//任务的名字,可以自定义 OS_TASK_PTR p_task,//任务函数,类似线程函数 void *p_arg,//任务传递参数,类似于给线程函数传递参数 OS_PRIO prio,//任务的优先级 CPU_STK *p_stk_base,//任务栈基址,提供一个数组基址(任务栈数组基地址) CPU_STK_SIZE stk_limit,//空出10%的栈空间给到堆栈检测函数使用,反过来说,当前任务只能使用90%栈空间 CPU_STK_SIZE stk_size,//任务栈的大小,以字(32位)为单位 OS_MSG_QTY q_size,//任务内消息队列的大小,若不使用,写0 OS_TICK time_quanta,//时间片轮转调度算法,若不使用,写0(这是时间片的长度)

关于STM32F103系列从大容量向中容量移植的若干问题

懵懂的女人 提交于 2019-12-01 13:27:00
一、把STM32F103大容量移植到STM32F103C8T6上的步骤: 1、换启动文件 startup_stm32f10x_cl.s ——互联型的器件 包括:STM32F105xx,STM32F107xx startup_stm32f10x_hd.s ——大容量器件 包括:STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_hd_vl.s ——大容量器件 包括:STM32F100xx startup_stm32f10x_ld.s ——小容量器件 包括:STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_ld_vl.s ——小容量器件 包括:STM32F100xx startup_stm32f10x_md.s ——中容量器件 包括:STM32F101xx,STM32F102xx,STM32F103xx startup_stm32f10x_md_vl.s ——中容量器件 - startup_stm32f10x_ld_vl.s: for STM32 Low density Value line devices - startup_stm32f10x_ld.s: for STM32 Low density devices - startup_stm32f10x_md_vl.s:

2019年9月25日星期三(STM32 ucos3)

五迷三道 提交于 2019-11-30 13:30:16
一.UCOS 1.概念 uc/OS-III(Micro C OS Thee),微型C语言编写的操作系统第三版。是一个可升级,可固化,多任务基于优先级的可抢占式实时内核。 ucos的任务个数不限制,实现了操作系统所需求的大部分功能,资源管理,同步,任务之间的通信。除了这些基本的功能以外,还提供一些其他的实时性内核找不到的特色功能,比如完备的运行时间测量,也可以直接发送信号/消息到某个任务,任务也可以同时等待多个内核对象 由于ucos体积微小,功能强悍,可移植性强,在微控制器领域应用广泛 ucos要收费,有时候我们会选择免费的系统,比如freeRTOS....,以及一些其他和物联网结合操作系统(华为liteOS 阿里巴巴.. 腾讯..) 2.ucos移植 (1)源代码结构 EvalBoards ------------ 工程文件 uc-CPU -------------- CPU相关代码 uc-LIB -------------- 和硬件/编译器 无关的库函数(字符串 数学 内存) uCOS-III ----------- ucos操作系统相关代码 (2)将源码拷贝到工程,修改源码(详情见手册) (3)特性 3.ucos的任务调度和任务 合作式调度 -------- 多个任务按照指定时间和顺序依次运行,下一个任务等待上一个任务时间用完再开始运行 抢占式调度 --------

uCOS-Ⅱ源码分析之uC-CPU文件夹

岁酱吖の 提交于 2019-11-29 14:38:26
此文共连载分析三个uCOS-Ⅱ的三个源码文件夹:uC-CPU 、uC-LIB 、uCOS-Ⅱ uC-LIB文件夹目录: ARM-Cortex-M3 / cpu_a.asm、cpu_c.c、cpu.h cpu_def.h cpu_def.h 这个文件中定义了一些 CPU 有关的宏定义,分为三类: 1、CPU 字节长度的定义,理想情况下 CPU 的字长应该是由 sizeof() 函数计算出来的,但是 sizeof() 函数必须在 CPU 运行中才能进行计算,所以在 uCOS 中直接用宏定义定义了出来 #define CPU_WORD_SIZE_32 4 // 定义 CPU 字节长度为 4 字节 2、CPU 字节顺序的定义,也就是 CPU 的大/小端模式的定义。 #define CPU_ENDIAN_TYPE_NONE 0 // 不知道是大端模式还是小端模式 #define CPU_ENDIAN_TYPE_BIG 1 // 大端模式 #define CPU_ENDIAN_TYPE_LITTLE 2 // 小端模式 3、临界区的定义和配置,临界区是指一个共用资源的程序片段,但共用资源程序片段一次只能被一个线程占用,当有一个线程正在访问临界区时,其他线程或进程就必须等待,以临界区共用资源的互斥使用(举例:打印机的使用,一个用户正在使用打印机,在未使用完成时

UCOS中的OSStatInit()函数

自古美人都是妖i 提交于 2019-11-29 00:32:01
ucos启动以后,会建立两个任务,空闲任务和统计任务(如果配置了的话),我们经常会在代码里看到OSStatInit(),其实这个函数使用的时候要小心了。 作者原著中提到,OSStatInit()要在建立的第一个,并且只有一个任务的时候调用,所以会经常见到下面的结构: int main(void) { OSInit(); OSStart(); } void AppTask(void *pdata) { } 这样做是因为统计任务计算CPU利用率的需要。 之所以说,调用这个函数要注意,主要原因就是因为在OSStatInit()中调用OSTimeDly发生了任务的调度,而这一点特别容易被忽略掉。 ---------------------------------------------------------------------- ---------------------------------------------------------------------- void OSStatInit (void) #if OS_TASK_STAT_EN > 0 void OSStatInit (void) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif OSTimeDly(2); OS_ENTER_CRITICAL();

ucosii使用

我怕爱的太早我们不能终老 提交于 2019-11-28 08:11:37
当需要同时跑多个任务的时候裸机显然不能很好的完成使命,这个时候我们可以给单片机上系统,创建多任务,完成复杂逻辑 一、首先移植uocii在我们的板上,根据mcu型号移植ucosii,需要做相应配置 我用的是ucoii mcu型号是stm32rct6 https://blog.csdn.net/lo_heng/article/details/79127081(移植参考网址) 二、编写任务函数并设置其堆栈大小和优先级等参数。 设置函数堆栈大小,这个需要根据函数的需求来设置,如果任务函数的局部变量多,嵌 套层数多,那么相应的堆栈就得大一些,如果栈设置小了,很可能出现的结果就是 CPU进入 HardFault,遇到这种情况,你就必须把堆栈设置大一点了。另外,有些地方还需要注意堆栈字节对齐的问题,如果任务运行出现莫名其妙的错误(比如用到 sprintf 出错),请 考虑是不是字节对齐的问题。 设置任务优先级,这个需要大家根据任务的重要性和实时性设置,记住高优先级的任务 有优先使用 CPU 的权利。 三、调用 OSInit,初始化 UCOSII,通过调用 OSTaskCreate 函数创建我们的任务。调用 OSStart,启动 UCOSII。 注意:在应用程序中经常有一些代码段必须不受任何干扰地连续运行,这样的代码段叫做临界段 (或临界区)。因此,为了使临界段在运行时不受中断所打断

ucosii内存管理代码的分析

纵饮孤独 提交于 2019-11-27 20:44:14
1.ucosii内存管理的简易原理 ucosii的内存管理,采用的是如下方式,先分成若干个partitions,每个partitions再分成若干个blocks,每个blocks可以划分成若干大小的blksize(ucosii中,对blocksize的缩写)。使用时,通常在task中定义一个局部二维数组作为内存管理的“载体”,这个局部二维数组就是1个partitions,数组的行数是blocks,数组的列数是blksize,局部二维数组完美契合了ucosii中内存管理的特性。 2.ucosii内存管理的代码分析 ucosii的内存管理中使用了二维指针来进行链表的构建,与“正常”的链表有点区别,本文对ucosii中的易混淆的点和重点进行分析。 (1)OSMemFreeList在内存管理的代码中用了“两次”? 在ucosii.h中,有如下定义: OS_EXT OS_MEM *OSMemFreeList; /* Pointer to free list of memory partitions */ 有如下声明 typedef struct os_mem { /* MEMORY CONTROL BLOCK */ void *OSMemAddr; /* Pointer to beginning of memory partition */ void *OSMemFreeList; /*