raw_task_0相关源码注释

一、raw_system.h相关代码

/*
****************************
*说明:中断信息类型
****************************
*/
enum {
                                               
    RAW_TYPE_Q_FRONT,        /*消息插入消息队列(不带消息大小,只唤醒一个任务)相应链表头部*/
    RAW_TYPE_Q_END,            /*消息插入消息队列(不带消息大小,只唤醒一个任务)相应链表尾部*/
    RAW_TYPE_Q_ALL,            /*消息插入消息队列(不带消息大小,唤醒全部任务)相应链表*/
    RAW_TYPE_SEM,            /*释放一个信号量(只唤醒一个任务)*/
    RAW_TYPE_SEM_ALL,        /*释放一个信号量(唤醒全部任务)*/
    RAW_TYPE_SUSPEND,        /*挂起任务*/
    RAW_TYPE_RESUME,        /*解除挂起任务*/
    RAW_TYPE_Q_SIZE_FRONT,    /*消息插入消息队列(带消息大小,只唤醒一个任务)相应链表头部*/
    RAW_TYPE_Q_SIZE_END,    /*消息插入消息队列(带消息大小,只唤醒一个任务)相应链表尾部*/
    RAW_TYPE_Q_SIZE_ALL,    /*消息插入消息队列(带消息大小,唤醒所有任务)相应链表*/
    RAW_TYPE_EVENT            /*设置事件标志*/
    
};



二、raw_task_0.h


#ifndef RAW_TASK_0_H
#define RAW_TASK_0_H

typedef struct EVENT_HANLDER {

    void  (*handle_event)(RAW_U8 ev, RAW_U8 *data);        
    
} EVENT_HANLDER;/*任务0事件处理函数*/


typedef struct EVENT_STRUCT {
    
    RAW_U8 ev;            /*处理函数参数。在中断信息事件里,做任务0事件类型(详见raw_system.h的中断信息类型)*/
    RAW_U8 *data;        /*处理函数参数。在中断信息事件里,与该任务0事件绑定的中断信息结构指针*/
    EVENT_HANLDER *p;    /*该任务0事件的处理函数*/
 
} EVENT_STRUCT;/*任务0事件结构*/


typedef struct OBJECT_INT_MSG {
    
    RAW_U8                  type;            /*中断信息的类型(详见raw_system.h)*/
    void                    *object;         /*指向中断信息的关联结构(任务控制块,信号量,消息队列等等)*/
    struct OBJECT_INT_MSG   *next;           /*指向下一个中断信息结构体,用于链接链表*/                       
    
    RAW_U8                  opt;             /*用于指定消息是插入到尾部还是头部,或者event里面用于设置RAW_OR或者 RAW_AND*/
    void                    *msg;            /*信息里附带的消息*/                     
    RAW_U32                 msg_size;        /*消息大小*/                    
    RAW_U32                 event_flags;     /*用在中断信息类型为RAW_TYPE_EVENT*/                         
                            
} OBJECT_INT_MSG;/*中断里发送信息的结构体*/


void task_0_tick_post(void);
void raw_task_0_post(EVENT_HANLDER *p, RAW_U8 ev, RAW_U8 *data);
void raw_task_0_init(void);

RAW_U16 int_msg_post(RAW_U8 type, void *p_obj, void *p_void, RAW_U32 msg_size, RAW_U32 flags, RAW_U8 opt);

#endif



三、raw_task_0.c



#include <raw_api.h>

#if (CONFIG_RAW_TASK_0 > 0)

/*
*************************************************************
*名称:时钟节拍中断事件处理函数
*功能:更新节拍数,更新指定优先级ev第一个任务时钟片,一般是当前运行任务优先级
*通知定时器管理任务更新定时器(会执行到时的定时器处理函数),
*通过信号量来驱动定时器管理任务timer_task
*************************************************************
*/
void task_0_tick_handler(RAW_U8 ev, RAW_U8 *data)
{
    data = data;

    #if (CONFIG_RAW_USER_HOOK > 0)
    raw_tick_hook();
    #endif

    /*主要处理超时了的任务*/
    tick_list_update();

    /*update task time slice if possible*/
    #if (CONFIG_SCHED_FIFO_RR > 0)
    caculate_time_slice(ev);
    #endif
    
    /*通知定时器管理任务更新定时器*/    
    #if (CONFIG_RAW_TIMER > 0)
    call_timer_task();
    #endif

}

/*
********************************************************
*功能:发送时钟节拍中断事件给任务0。
********************************************************
*/
void task_0_tick_post()
{
    
    raw_task_0_post(&task_0_event_handler, raw_task_active->priority, 0);

}


/*
*********************************************************************************
*功能1(只针对传递中断信息):把处理函数,参数ev和data绑定在一起投递给
*任务0事件队列(task_0_events_queue)里的空闲任务0事件结构EVENT_STRUCT
*
*data:自定义(在传递中断信息时,该变量为中断信息块,在传递时钟节拍中断信号时,该值为0)
*ev:自定义(在传递中断信息时,该变量为中断信息类型,在传递时钟节拍中断信号时,该值应该为当前运行任务优先级值)
*p:对该任务0事件的执行函数(传递中断信息时,为msg_event_handler,传递时钟节拍中断信号时,为task_0_event_handler)
*
*********************************************************************************
*/
void raw_task_0_post(EVENT_HANLDER *p, RAW_U8 ev, RAW_U8 *data)
{
    RAW_U32 snum;
    RAW_SR_ALLOC();

    /*任务0事件队列里的事件数已经达到队列的最大值*/
    if(nevents_points == MAX_TASK_EVENT) {
        RAW_ASSERT(0);
    }



    RAW_CPU_DISABLE();
    /*取得队列事件尾部的第一个空闲块索引号*/
    snum = (fevent_point + nevents_points) & (MAX_TASK_EVENT - 1);
    /*更新任务0事件数*/
    ++nevents_points;  
    /*使任务0就绪*/
    if (task_0_is_ready == 0) {   //设置任务0就绪标志
        
        task_0_is_ready = 1;
    }

    RAW_CPU_ENABLE();

    /*填充索引尾snum的任务0事件块*/
    task_0_events_queue[snum].ev = ev;
    task_0_events_queue[snum].data = data;
    task_0_events_queue[snum].p = p;

    /*Update the debug information*/
    if (nevents_points > peak_events) {
        peak_events = nevents_points;
    }
}

/*
********************************************************
*功能:任务0切换到其它普通任务
********************************************************
*/
static void task_0_switch()
{
    RAW_SR_ALLOC();

    RAW_CPU_DISABLE();

    if (task_0_is_ready) {
        
        RAW_CPU_ENABLE();
        return;
    }
             
    get_ready_task(&raw_ready_queue);

    CONTEXT_SWITCH();

    RAW_CPU_ENABLE();  

}

/*
************************************************************
*功能:任务0处理函数。任务0创建时被加入到就绪队列里。
*第一次执行任务0需要把该任务控制块取掉,该任务是个死循环,
*以后只在任务0就绪标志task_0_is_ready被置‘1’就会启动该任务。
*任务0就绪标志只在系统初始化时和接收到任务0事件时才被置‘1’。
************************************************************
*/
static void task_0_process(void *pa)
{
    RAW_U8 ev;
    RAW_U8 *data;
    EVENT_HANLDER *receiver;
    RAW_U8 done;
    RAW_S32 i;
    
    RAW_SR_ALLOC();
    /*把任务0从就绪队列里摘除*/
    list_delete(&raw_task_0_obj.task_list);
    /*清除任务0对应task_bit_map里的就绪标志位*/
    data = (RAW_U8 *)raw_ready_queue.task_bit_map;   
    *data &= ~1;
    
    /*任务0的处理,死循环*/
    while (1) {
        
        done = 0;
        /*在这个循环里面会把所有任务0事件都处理完成,最后切换到普通任务,当到任务0再次被激活了,又会回到该循环*/
        while (done == 0) {

            /*Get the message info and update it*/
            RAW_CPU_DISABLE();
            
            /*有任务0事件存在*/
            if (nevents_points) {
                /*对任务0事件队列的访问为FIFO*/
                
                /*提取第一个任务0事件相应信息*/
                ev = task_0_events_queue[fevent_point].ev;  
                data = task_0_events_queue[fevent_point].data;   
                receiver = task_0_events_queue[fevent_point].p;  /*该事件处理函数*/
            
                /*更新fevent_point和nevent_points*/
                fevent_point = (fevent_point + 1) & (MAX_TASK_EVENT - 1);
                --nevents_points;   
                RAW_CPU_ENABLE();

                /*执行该事件处理函数*/
                receiver->handle_event(ev, data);     //执行事件处理函数
            }

            /*没有任务0事件出现*/
            else {
                /*清除任务0就绪标志*/
                task_0_is_ready = 0;

                RAW_CRITICAL_ENTER_CPU_ENABLE();

                /*取出从task_bit_map的第一位到CONFIG_RAW_PRIO_MAX(不包括该位)的第一个‘1’与第一位的偏移量*/
                i = bit_search_first_one(raw_ready_queue.task_bit_map, 1, CONFIG_RAW_PRIO_MAX - 1);

                /*在0优先级之后有次高优先级*/
                if (i >= 0) {
                    /*获取下个高优先级*/
                    raw_ready_queue.highest_priority = 1 + i;
                }
                /*0优先级之后没有就绪的任务*/
                else {

                    #if (CONFIG_RAW_ASSERT > 0)
                    RAW_ASSERT(0);
                    #endif
                }
                /*退出临界区并且不执行调度(这个用使用RAW_CRITICAL_EXIT()也没事,因为task_0_is_ready已经被清零)*/
                RAW_CRITICAL_EXIT_NO_SCHED();

                /*从任务0切换到普通任务执行*/
                task_0_switch();
                done = 1;    
            }
            
        }
            
    }
        
}

#if (CONFIG_RAW_ZERO_INTERRUPT > 0)
/*
*********************************************
*功能:这个函数用于处理中断里发出的信息,
*根据信息类型的不同调用不同的实现,详细见注释。
*
*data:要被处理的中断信息结构指针
*ev:指明data中断信息类型
*********************************************
*/
void int_msg_handler(RAW_U8 ev, RAW_U8 *data)
{
    OBJECT_INT_MSG *int_msg;
    
    RAW_SR_ALLOC();
    /*取得中断信息结构指针*/
    int_msg = (OBJECT_INT_MSG *)data;
    
    switch (ev) {  /*判断该data中断信息结构的类型,执行相应的处理*/
        
        case RAW_TYPE_SUSPEND:/*如果中断信息类型为挂起任务类型*/
            task_suspend((RAW_TASK_OBJ *)(int_msg->object));/*挂起中断信息结构里的object对应的任务*/
            break;

        case RAW_TYPE_RESUME:/*如果中断信息类型为解除挂起任务类型*/
            task_resume((RAW_TASK_OBJ *)(int_msg->object));/*解除中断信息结构里的object对应的任务*/
            break;

        case RAW_TYPE_SEM:/*如果中断信息类型为信号量(唤醒一个任务)类型*/
            semaphore_put((RAW_SEMAPHORE *)(int_msg->object), WAKE_ONE_SEM);/*释放一个object指定的信号量,唤醒一个阻塞任务*/
            break;

        case RAW_TYPE_SEM_ALL:/*如果中断类型是唤醒所有阻塞任务的信号量类型*/
            semaphore_put((RAW_SEMAPHORE *)(int_msg->object), WAKE_ALL_SEM);/*释放一个object指定的信号量,唤醒所有阻塞与该信号量的任务*/
            break;

        case RAW_TYPE_Q_FRONT:/*如果是消息队列(LIFO)类型*/
            msg_post((RAW_QUEUE *)(int_msg->object), int_msg->msg, SEND_TO_FRONT, WAKE_ONE_QUEUE);/*往object指定的消息队列传递消息,唤醒一个阻塞任务*/
            break;

        case RAW_TYPE_Q_END:/*如果是消息队列(FIFO)类型*/
            msg_post((RAW_QUEUE *)(int_msg->object), int_msg->msg, SEND_TO_END, WAKE_ONE_QUEUE);
            break;

        case RAW_TYPE_Q_ALL:/*如果是消息队列(唤醒所有阻塞任务)类型*/
            msg_post((RAW_QUEUE *)(int_msg->object), int_msg->msg, int_msg->opt, WAKE_ALL_QUEUE);
            break;

        case RAW_TYPE_Q_SIZE_FRONT:/*如果是带有消息大小的消息队列(LIFO)类型,唤醒一个阻塞任务*/
            msg_size_post((RAW_QUEUE_SIZE *)(int_msg->object), int_msg->msg, int_msg->msg_size, SEND_TO_FRONT, WAKE_ONE_QUEUE);
            break;

        case RAW_TYPE_Q_SIZE_END:/*如果是带有消息大小的消息队列(FIFO)类型,唤醒一个阻塞任务*/
            msg_size_post((RAW_QUEUE_SIZE *)(int_msg->object), int_msg->msg, int_msg->msg_size, SEND_TO_END, WAKE_ONE_QUEUE);
            break;

        case RAW_TYPE_Q_SIZE_ALL:/*如果是带有消息大小的消息队列(唤醒所有阻塞任务)类型*/
            msg_size_post((RAW_QUEUE_SIZE *)(int_msg->object), int_msg->msg, int_msg->msg_size, int_msg->opt, WAKE_ALL_QUEUE);
            break;

        case RAW_TYPE_EVENT:/*如果是事件组类型*/
            event_set((RAW_EVENT *)(int_msg->object), int_msg->event_flags, int_msg->opt);
            break;
        
        default:
            RAW_ASSERT(0);



    }

    RAW_CPU_DISABLE();
    /*处理完该中断信息后,要把该信息结构归还给空闲中断信息结构链表*/
    int_msg->next = free_object_int_msg;
    free_object_int_msg = int_msg;
    
    RAW_CPU_ENABLE();

}


/*
***************************************
*功能:初始化中断信息处理。详细见注释
***************************************
*/
void int_msg_init()
{
    OBJECT_INT_MSG *p_msg1;
    OBJECT_INT_MSG *p_msg2;
    RAW_U32 number;
    /*初始化信息事件处理函数*/
    msg_event_handler.handle_event = int_msg_handler;
    /*取出中断空闲信息链表的最大信息数*/
    number = OBJECT_INT_MSG_SIZE;
    /*清空整个object_int_msg数组,这个空间用于下面链接成空闲信息链表*/
    raw_memset(object_int_msg, 0, sizeof(object_int_msg));
    /*是free_object_int_msg指向空闲信息链表的第一个中断信息结构*/
    free_object_int_msg = object_int_msg;
    
    /*下面是把该数组的元素链接成链表*/
    p_msg1 = object_int_msg;
    p_msg2 = object_int_msg;
    p_msg2++;

    while (--number) {

        p_msg1->next = p_msg2;

        p_msg1++;
        p_msg2++;
    }

    /*最后一个节点没有后续节点*/
    p_msg1->next = 0;                      
    
}


/*
*************************************************************************************
*功能:发出中断信息(中断信息需要传递给任务0进行处理,在此之前会把
*中断信息打包成EVENT_STRUCT传递给任务0事件队列task_0_events_queue)。
*
*type:指明中断信息类型(详见raw_system.h)
*p_obj:指向相应工程结构。(任务控制块,信号量结构体,消息队列结构体,事件结构体)
*p_void:附带消息指针。(如果是RAW_TYPE_Q或者RAW_TYPE_Q_SIZE类型)
*msg_size:附带消息大小。(如果是RAW_TYPE_Q_SIZE类型)
*flags: 用于RAW_TYPE_EVENT的信息类型,事件标志。
*opt:用于指定是置于尾部还是头部(SEND_TO_FRONT or SEND_TO_END),
*或者event里面用于设置RAW_OR或者RAW_AND。
*************************************************************************************
*/
RAW_U16 int_msg_post(RAW_U8 type, void *p_obj, void *p_void, RAW_U32 msg_size, RAW_U32 flags, RAW_U8 opt)
{
    RAW_U8 *data;

    RAW_SR_ALLOC();

    RAW_CPU_DISABLE();
    
    data = (RAW_U8 *)free_object_int_msg;  /*取出第一个空闲中断信息块指针*/

    if (free_object_int_msg == 0) {
        
        RAW_ASSERT(0);
    }
    /*初始化该空闲中断信息块,各成员含义见rawtask_0.h的OBJECT_INT_MSG*/
    free_object_int_msg->type = type;
    free_object_int_msg->object = p_obj;
    free_object_int_msg->msg = p_void;
    free_object_int_msg->msg_size = msg_size;
    free_object_int_msg->event_flags = flags;
    free_object_int_msg->opt = opt;
    /*更新free_object_int_msg(指向中断空闲信息链表的第一个空闲信息结构体)*/
    free_object_int_msg = free_object_int_msg->next;

    RAW_CPU_ENABLE();
    /*把该中断信息块,类型,及对该中断信息块的处理函数绑定成任务0事件队列(task_0_events_queue)里的一个EVENT_STRUCT结构*/
    raw_task_0_post(&msg_event_handler, type, data);

    return RAW_SUCCESS;

}


#endif                  

/*
************************************************************
*功能:初始化任务0。创建0任务,设置任务0事件处理函数,
*在这里该函数用于处理时钟节拍事件(必须的),
*(在其它地方用户也可以自己定义个任务0事件使用自定义的处理函数)。
*使任务0就绪,初始化中断空闲信息块链表
************************************************************
*/
void raw_task_0_init()
{

    /*创建任务0用于处理中断里发出的事件(时钟节拍事件或者中断信息事件)*/
    raw_task_create(&raw_task_0_obj, (RAW_U8  *)"timer_object",  0,
    0,  0, task_0_stack, TASK_0_STACK_SIZE, task_0_process, 1);
    /*初始化时钟节拍事件处理函数*/
    task_0_event_handler.handle_event = task_0_tick_handler;
    task_0_is_ready = 1;
    
    #if (CONFIG_RAW_ZERO_INTERRUPT > 0)
    int_msg_init();/*初始化中断空闲信息块链表*/
    #endif
}

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值