OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4390|回复: 14

[MDK使用] 分享:UCSIII的程序移植+温湿度+串口空闲中断

[复制链接]

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
发表于 2019-1-22 20:54:56 | 显示全部楼层 |阅读模式
刚学UCSIII系统,需要写写程序练练手
1)加中断需要加进入临界区和退出临界区
2)OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err);
这个时间不能超过999,否则会溢出,影响任务进行
*  OS_OPT_TIME_HMSM_STRICT            strictly allow only hours        (0...99)
*                                                                                   minutes      (0...59)
*                                                                                   seconds      (0...59)
*                                                                                   milliseconds (0...999)
3)定义的函数,要放在主函数里面,不要放在任务里面
4)空闲中断直接放在usart.c,方便直接使用
后续再加点其它东西


例4-1 UCOSIII移植+温湿度+串口空闲中断.zip

5.89 MB, 下载次数: 242

业精于勤荒于嬉;行成于思毁于随!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-23 10:40:45 | 显示全部楼层
本帖最后由 1208 于 2019-1-24 12:51 编辑

在任务里面不能写串口波特率,容易导致任务卡死
中断程序不需要加临界区

void chuan_task(void *p_arg)
{   
    OS_ERR err;
    CPU_SR_ALLOC();
    p_arg = p_arg;

  //  OS_CRITICAL_ENTER();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2

//    uart_init(115200);    //串口初始化波特率为115200
//LED_Init();                  //初始化与LED连接的硬件接口  
  //  OS_CRITICAL_EXIT();
    while(1)
    {
        LED1=~LED1;
        OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
    }
}

例6-1 UCOSIII任务创建和删除.zip

6.92 MB, 下载次数: 29

业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-23 21:11:51 | 显示全部楼层
本帖最后由 1208 于 2019-1-24 12:54 编辑

1)在os_core.c任务调度和切换就是获得优先级最高的任务CPU使用权。
任务调度器:一种是任务级调度器 OSSched(void)
一种是中断级调度器OSIntExit (void)
调度器上锁OSSchedLock (OS_ERR  *p_err)可以防止任务切换
调度器上锁 OSSchedUnlock (OS_ERR  *p_err)可以释放任务上锁
2)时间片轮转调度:UCOSIII支持多个任务同时拥有一个优先级
定义OS_CFG_SCHED_ROUND_ROBIN_EN 为1
#define  OS_CFG_TICK_RATE_HZ            200u
OSInit()函数UCOSIII初始化为OS_CFG_TICK_RATE_HZ /10u
默认的时间片就为20
3)将这些优先级分配给了UCOSIII的5个系统内部任务
优先级0:中断服务服务管理任务 OS_IntQTask()
优先级1:时钟节拍任务 OS_TickTask()
优先级2:定时任务 OS_TmrTask()
优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()
4)在os_cfg.h
优先级位映表OSPrioTbl[]用来记录哪个优先级下有任务就绪
UCOSIII中数值越小优先级越高
优先级3个函数:
OS_PrioGetHighest (void)最高优先级任务
OS_PrioInsert (OS_PRIO  prio)将某个任务在就绪表中相对应的位置1
OS_PrioRemove (OS_PRIO  prio)将某个任务在就绪表中相对应的位清零
OSDdylist[]在OS_H用来记录每一个优先级下所有就绪的任务
struct  os_rdy_list {
    OS_TCB              *HeadPtr;        \\向链表头
    OS_TCB              *TailPtr;           \\向链表尾
    OS_OBJ_QTY           NbrEntries;    \\任务数量
}           
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-24 21:27:05 | 显示全部楼层
1)任务创建OSTaskCreate()将任务控制块、任务堆栈、任务代码联系一起
#define START_TASK_PRIO                3          //任务优先级
#define START_STK_SIZE                 128      //任务堆栈大小       
OS_TCB StartTaskTCB;                                //任务控制块
CPU_STK START_TASK_STK[START_STK_SIZE];      //任务堆栈       
void start_task(void *p_arg);                       //任务函数
2)任务删除void  OSTaskDel (OS_TCB  *p_tcb,
                                                OS_ERR  *p_err)
指任务只运行一次,运行完成后就将其删除掉
属于任务创建完成后就要删除掉自身
OSTaskDel((OS_TCB*)0,&err);        //删除start_task任务自身
OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err);  //删除掉任务2
如果多个任务使用同一个共享资源,任务A在使用共享资源
如果删除了任务A,这个资源没有得到释放,其它任务也得不到共享资源的使用权
3)任务挂起OSTaskSuspend (OS_TCB  *p_tcb,
                                               OS_ERR  *p_err)
需要暂停运行,以后再运行,但不能删掉的任务
4)恢复被挂起任务 OSTaskResume (OS_TCB  *p_tcb,
                                                          OS_ERR  *p_err)
等到内核对象后才可以继续运行
5)时间片轮转调度:支持多个任务拥有同一个优先级,
采用时间片轮调度方法进行任务调度
#if        OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
定义为1才会被编译
OSSchedRoundRobinCfg (CPU_BOOLEAN   en,
                                          OS_TICK       dflt_time_quanta,
                                          OS_ERR       *p_err)
#define  OS_CFG_TICK_RATE_HZ            200u
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍为5ms,既1*5=5ms
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-25 12:10:49 | 显示全部楼层
本帖最后由 1208 于 2019-1-25 12:41 编辑

1)在os_core.c
空闲任务OS_IdleTaskInit (OS_ERR  *p_err)
优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()
OS_CFG_PRIO_MAX为64,优先级最低
空闲任务中不能调用任何可使空闲任务进入等待态的函数
2)时钟节拍任务OS_TickTaskInit (OS_ERR  *p_err)
优先级1:时钟节拍任务 OS_TickTask()
#define  OS_CFG_TICK_TASK_PRIO             1u
3)统计任务OS_StatTask (void  *p_arg)
优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
使用前需将宏OS_CFG_STAT_TASK_EN置1
OSStatTaskCPUUsageInit(&err);          //统计任务
统计任务OSStatTaskCtr,用来统计CPU的使用率
4)定时任务OS_TmrTask (void  *p_arg)
优先级2:定时任务 OS_TmrTask()
宏OS_CFG_TMR_EN设置为1就会使能定时任务
5)中断任务OS_IntQTask (void  *p_arg)
优先级0:中断服务服务管理任务 OS_IntQTask()
宏OS_CFG_ISR_POST_DEFERRED_EN置1
就会使能中断服务管理任务
OSIntNestingCtr用来记录中断嵌套次数,最大支持250级的中断嵌套
进入加1,退出减1
6)钩子函数在os_app_hooks.c
    1、OSIdleTaskHook(),空闲任务调用这个函数,可以用来让CPU进入低功耗模式
    2、OSInitHook(),系统初始化函数OSInit()调用此函数。
    3、OSStatTaskHook(),统计任务每秒中都会调用这个函数,此函数允许你向统计任务中添加自己的应用函数。
    4、OSTaskCreateHook(),任务创建的钩子函数。
    5、OSTaskDelHook(),任务删除的钩子函数。
    6、OSTaskReturnHook(),任务意外返回时调用的钩子函数,比如删除某个任务
    7、OSTaskSwHook(),任务切换时候调用的钩子函数。
    8、OSTimeTickHook(),滴答定时器调用的钩子函数
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-25 13:00:20 | 显示全部楼层
本帖最后由 1208 于 2019-2-19 18:07 编辑

1)UCOSIII中断
中断:应内部或外部异步事件的请求中止当前任务,
而去处理异步事件所要求的任务的过程叫做中断。
void USART1_IRQHandler(void)
{
       OSIntEnter();        //进入中断
      //中断服务程序
      OSIntExit();          //触发任务切换软中断
}
OSIntEnter()函数里面
void  OSIntEnter (void)
{
      if (OSRunning != OS_STATE_OS_RUNNING) {
          return
      }
      if (OSIntNestingCtr >= (OS_NESTING_CTR)250u) {
            return;
      }
     OSIntNestingCtr++;
}
OSIntNestingCtr来记录中断嵌套次数,UCOSIII最多支持250级的中断嵌套
进入加1,退出减1
UCOSIII定义了一个进入临界段代码的宏:OS_CRITICAL_ENTER(),
定义了两个退出临界段代码的宏:OS_CRITICAL_EXIT和
OS_CRITICAL_EXIT_NO_SCHED()
2)任务进行延时操作
void  OSTimeDly (OS_TICK   dly,
                          OS_OPT    opt,
                          OS_ERR   *p_err)
        case OS_OPT_TIME_DLY:            //相对模式
        case OS_OPT_TIME_MATCH:       //绝对模式
        case OS_OPT_TIME_PERIODIC    //周期模式
直观的来对某个任务延时
OSTimeDlyHMSM (CPU_INT16U   hours,
                            CPU_INT16U   minutes,
                            CPU_INT16U   seconds,
                            CPU_INT32U   milli,
                            OS_OPT       opt,
                            OS_ERR      *p_err)

3)任务“解救”那些因为调用OSTimeDly()或
OSTIMEDLYHMSM()函数而进入等待态的任务
OSTimeDlyResume (OS_TCB  *p_tcb,
                             OS_ERR  *p_err)
OSTimeGet()来获取当前时钟节拍计数器的值
OSTimeSet()设置当前时钟节拍计数器的值

业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-25 18:04:00 | 显示全部楼层
1)定时器本质是递减计数器,当计数器减到零时可以触发某种动作的执行,
这个动作通过回调函数来实现
当定时器计时完成时,定义的回调函数就会被立即调用
宏OS_CFG_TMR_TASK_RATE_HZ为100Hz,时间分辨率为10ms
OS_OPT_TMR_PERIODIC,        //周期模式,
OS_OPT_TMR_ONE_SHOT,         //单次定时器
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-25 19:00:11 | 显示全部楼层
1)信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次释放才能继续执行
如果该资源对应的信号量有效值大于1,则任务可以获得该资源,任务继续运行。如果该信号量的有效值为0,则任务加入等待信号量的任务表中
2)使用信号量访问共享资源区
二进制信号量
资源对应的信号量为1时,可以使用该资源
资源对应的信号量为0时,等待该信号量就会放进等待信号量的任务表中
计数型信号量
可以同时有多个任务访问共享资源,
一个信号量初始化值为10,只有前10个请求改信号的任务可以使用共享资源
3)OS_SEM        MY_SEM;                //定义一个信号量,用于访问共享资源
     OS_SEM        SYNC_SEM;        //定义一个信号量,用于任务同步
创建信号量
OSSemCreate (OS_SEM      *p_sem,
                          CPU_CHAR    *p_name,
                          OS_SEM_CTR   cnt,
                          OS_ERR      *p_err)
发送信号量
OS_SEM_CTR  OSSemPost (OS_SEM  *p_sem,
                                            OS_OPT   opt,
                                            OS_ERR  *p_err)
请求信号量
OS_SEM_CTR  OSSemPend (OS_SEM   *p_sem,
                       OS_TICK   timeout,
                       OS_OPT    opt,
                       CPU_TS   *p_ts,
                       OS_ERR   *p_err)
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-25 20:47:55 | 显示全部楼层
1)优先级反转在可剥夺内核中是非常常见的
当一个低优先级任务和一个高优先级任务同时使用同一信号量,
而系统中还有其他中等优先级任务时。如果低优先级任务获得
信号量,那么高优先级的任务就会处于等待状态,但是,中等
优先级的任务可以打断低优先级任务而先于高优先级任务运行
(此时高优先级的任务在等待信号量,不能运行),这就是优先级反转
2)互斥信号量
创建信号量
OSMutexCreate (OS_MUTEX  *p_mutex,
                            CPU_CHAR  *p_name,
                            OS_ERR    *p_err)
请求互斥型信号量
OSMutexPend (OS_MUTEX  *p_mutex,
                          OS_TICK    timeout,
                          OS_OPT     opt,
                          CPU_TS    *p_ts,
                          OS_ERR    *p_err)
发送互斥信号量
OSMutexPost (OS_MUTEX  *p_mutex,
                        OS_OPT     opt,
                        OS_ERR    *p_err)
3)任务内嵌信号量
请求\等待任务信号量
OS_SEM_CTR  OSTaskSemPend (OS_TICK   timeout,
                                                     OS_OPT    opt,
                                                     CPU_TS   *p_ts,
                                                     OS_ERR   *p_err)
发布任务信号量
OS_SEM_CTR  OSTaskSemPost (OS_TCB  *p_tcb,
                                                   OS_OPT   opt,
                                                   OS_ERR  *p_err)
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-25 20:58:53 | 显示全部楼层
本帖最后由 1208 于 2020-3-26 17:21 编辑

1)消息一般:指向数据的指针,数据的长度和记录消息发布时刻的时间戳
指针指向的可以是一块数据区域或者甚至是一个函数
消息队列中有一个列表,记录了所有正在等待获得消息的任务

创建消息队列
OSQCreate (OS_Q        *p_q,
                 CPU_CHAR    *p_name,
                 OS_MSG_QTY   max_qty,
                 OS_ERR      *p_err)
创建一个消息队列,消息队列使得任务或者中断服务程序可以向一个
或者多个任务发送消息

等待消息队列
*OSQPend (OS_Q         *p_q,
                OS_TICK       timeout,
                OS_OPT        opt,
                OS_MSG_SIZE  *p_msg_size,
                CPU_TS       *p_ts,
                OS_ERR       *p_err)
当一个任务想要从消息队列中接收一个消息的话需要使用函数OSQPend

向消息队列发送消息
OSQPost (OS_Q         *p_q,
               void         *p_void,
               OS_MSG_SIZE   msg_size,
               OS_OPT        opt,
               OS_ERR       *p_err)
如果有多个任务在等待消息队列,优先级最高的任务将获得这个消息
如果等待的任务优先级比发送消息的任务优先级高,则系统会执行任务调度
等待消息的任务立即恢复执行,而发送消息的任务被挂起
11.jpg

业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-26 15:50:19 | 显示全部楼层
本帖最后由 1208 于 2019-1-26 17:21 编辑

1)任务内建消息队列
使用任务内建消息队列的宏OS_CFG_TASK_DEL_EN必须置1

等待任务内建消息
*OSTaskQPend (OS_TICK       timeout,
                          OS_OPT        opt,
                          OS_MSG_SIZE  *p_msg_size,
                          CPU_TS       *p_ts,
                          OS_ERR       *p_err)
让任务接收其它任务或ISR中发送的消息,不需要经过中间的消息对列

发送任务内建消息
OSTaskQPost (OS_TCB       *p_tcb,
                        void         *p_void,
                        OS_MSG_SIZE   msg_size,
                        OS_OPT        opt,
                        OS_ERR       *p_err)
通过一个任务的内建消息队列向这个任务发送一条消息
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-1-26 19:58:54 | 显示全部楼层
本帖最后由 1208 于 2019-2-20 12:21 编辑

1)事件标记组
有时候一个任务可能需要和多个事件同步,这个时候就需要使用事件标志组。
事件标志组与任务之间有两种同步机制:“或”同步和“与”同步,
当任何一个事件发生,任务都被同步的同步机制是“或”同步;
需要所有的事件都发生任务才会被同步的同步机制是“与”同步

创建事件标志组OSFlagCreate (OS_FLAG_GRP  *p_grp,
                                               CPU_CHAR     *p_name,
                                               OS_FLAGS      flags,
                                               OS_ERR       *p_err)
在使用事件标志组之前,需要调用创建一个事件标志组

等待事件标志组OSFlagPend (OS_FLAG_GRP  *p_grp,
                                                   OS_FLAGS      flags,
                                                   OS_TICK       timeout,
                                                   OS_OPT        opt,
                                                   CPU_TS       *p_ts,
                                                   OS_ERR       *p_err)
将事件标记组里事件标志的“与或”组合状态设置成任务的等待条件
任务等待的事件标记组不满足设置的条件,任务将被置位挂起

向事件标记组发布标记OSFlagPost (OS_FLAG_GRP  *p_grp,
                                                      OS_FLAGS      flags,
                                                      OS_OPT        opt,
                                                      OS_ERR       *p_err)
修改完事件标志后,将检查并使那些等待条件已经满足的任务进入就绪态,
可以对已经置位或清零的标志进行重复置位和清零操作
业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-2-20 17:50:14 | 显示全部楼层
本帖最后由 1208 于 2019-2-20 18:56 编辑

同时等待多个内核对象
在UCOIII中只支持同时等待多个信号量和消息队列
当只要等到其中的任意一个的时候就会导致该任务进入就绪态

不支持同时等待多个事件标记组和互斥信号量
OS_OBJ_QTY  OSPendMulti (OS_PEND_DATA  *p_pend_data_tbl,
                                         OS_OBJ_QTY     tbl_size,
                                         OS_TICK        timeout,
                                         OS_OPT         opt,
                                         OS_ERR        *p_err)



业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

57

主题

1680

帖子

3

精华

资深版主

Rank: 8Rank: 8

积分
4306
金钱
4306
注册时间
2018-6-30
在线时间
808 小时
 楼主| 发表于 2019-2-21 18:50:01 | 显示全部楼层
本帖最后由 1208 于 2019-2-22 09:50 编辑

存储管理
UCOSIII中有内存管理模块,使用内存管理模块可以动态的分配和释放内存
申请内存malloc()和free()释放内存
1)创建存储区使用函数
void  OSMemCreate (OS_MEM       *p_mem,
                              CPU_CHAR     *p_name,
                              void         *p_addr,
                              OS_MEM_QTY    n_blks,
                              OS_MEM_SIZE   blk_size,
                              OS_ERR       *p_err)
2)内存申请
void  *OSMemGet (OS_MEM  *p_mem,
                            OS_ERR  *p_err)
用来从指定的存储区中获取存储块共应用使用


内存释放
void  OSMemPut (OS_MEM  *p_mem,
                void    *p_blk,
                OS_ERR  *p_err)
用于释放内存,将申请到的存储块还给指定的存储区







业精于勤荒于嬉;行成于思毁于随!
回复 支持 反对

使用道具 举报

0

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2020-12-31
在线时间
27 小时
发表于 2021-6-20 19:42:38 | 显示全部楼层
想试着写一写,中断这块还不是很明了,这个程序有帮助吗
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 23:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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