uC/OS-II源码解析(os_q.c)

/*
** ver   : 2.52
** file  : os_q.c
** brief : 消息队列相关操作 C 文件
*/


#ifndef  OS_MASTER_FILE
#include "includes.h"            /* 包含头文件 */
#endif

#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
/*
**********************************************************************************************
*                                      无等待的请求消息队列
*
* breif    : 该函数用于无等待的请求消息队列中的消息.
*
* pevent   : 指向事件控制块的指针
*
* Returns  : != (void *)0  队列中有可用消息
*            == (void *)0  未获得消息
**********************************************************************************************
*/

#if OS_Q_ACCEPT_EN > 0
void  *OSQAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3                        
    OS_CPU_SR  cpu_sr;
#endif
    void      *msg;
    OS_Q      *pq;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {               /* 无效的事件控制块指针 */
        return ((void *)0);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* 错误的事件类型       */
        return ((void *)0);
    }
#endif
    OS_ENTER_CRITICAL();
    pq = (OS_Q *)pevent->OSEventPtr;             /* 获得队列控制块       */
    if (pq->OSQEntries > 0) {                    /* 判断队列中是否有消息 */
        msg = *pq->OSQOut++;                     /* 将消息取出来返回     */
        pq->OSQEntries--;                        /* 消息数减1            */
        if (pq->OSQOut == pq->OSQEnd) {          /* 调整已实现循环队列   */
            pq->OSQOut = pq->OSQStart;
        }
    } else {
        msg = (void *)0;                         /* 队列为空             */
    }
    OS_EXIT_CRITICAL();
    return (msg);                                    
}
#endif
/*$PAGE*/
/*
*****************************************************************************************
*                                        创建消息队列
*
* brief   : 该函数用于创建消息队列.
*
* start   : 消息队列的基地址.该数组必须被声明为void类型
*
*             void *MessageStorage[size]
*
* size    : 消息数组的大小
*
* Returns : != (OS_EVENT *)0  消息队列创建成功
*           == (OS_EVENT *)0  消息队列创建失败
*****************************************************************************************
*/

OS_EVENT  *OSQCreate (void **start, INT16U size)
{
#if OS_CRITICAL_METHOD == 3                     
    OS_CPU_SR  cpu_sr;
#endif
    OS_EVENT  *pevent;
    OS_Q      *pq;


    if (OSIntNesting > 0) {                      /* 不允许中断内创建消息队列 */
        return ((OS_EVENT *)0);                               
    }
    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;                    /* 获取事件控制块           */
    if (OSEventFreeList != (OS_EVENT *)0) {      /* 调整剩余事件控制块链表   */
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    if (pevent != (OS_EVENT *)0) {                   
        OS_ENTER_CRITICAL();
        pq = OSQFreeList;                        /* 获取队列控制块      */
        if (pq != (OS_Q *)0) {                   /* 存在剩余队列控制块  */
            OSQFreeList         = OSQFreeList->OSQPtr;/* 调整队列控制块链表 */
            OS_EXIT_CRITICAL();
            pq->OSQStart        = start;              /* 初始化队列     */
            pq->OSQEnd          = &start[size];
            pq->OSQIn           = start;
            pq->OSQOut          = start;
            pq->OSQSize         = size;
            pq->OSQEntries      = 0;
            pevent->OSEventType = OS_EVENT_TYPE_Q;
            pevent->OSEventCnt  = 0;
            pevent->OSEventPtr  = pq;
            OS_EventWaitListInit(pevent);             /* 初始化等待任务表 */
        } else {                                      /* 无可用队列控制块 */
            pevent->OSEventPtr = (void *)OSEventFreeList; /* 返还事件控制块  */
            OSEventFreeList    = pevent;
            OS_EXIT_CRITICAL();
            pevent = (OS_EVENT *)0;
        }
    }
    return (pevent);
}
/*$PAGE*/
/*
****************************************************************************************
*                                        删除消息队列
*
* brief    : 该函数用于删除消息队列.
*
* pevent   : 指向事件控制块的指针
*
* opt      : 删除选项
*              opt == OS_DEL_NO_PEND   无任务等待时删除
*              opt == OS_DEL_ALWAYS    无条件删除,就绪所有等待任务
*
* err      : 指向错误代码的指针,可能取值:
*              OS_NO_ERR               成功
*              OS_ERR_DEL_ISR          不允许在中断中删除队列
*              OS_ERR_INVALID_OPT      无效的删除选项
*              OS_ERR_TASK_WAITING     有任务正在等待队列中的消息
*              OS_ERR_EVENT_TYPE       错误的时间类型
*              OS_ERR_PEVENT_NULL      I无效的事件控制块指针
*
* Returns    : pevent        删除失败
*              (OS_EVENT *)0 删除成功
*
*****************************************************************************************
*/

#if OS_Q_DEL_EN > 0
OS_EVENT  *OSQDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                             
    OS_CPU_SR  cpu_sr;
#endif
    BOOLEAN    tasks_waiting;
    OS_Q      *pq;


    if (OSIntNesting > 0) {                        /* 不允许中断内删除      */
        *err = OS_ERR_DEL_ISR;                    
        return ((OS_EVENT *)0);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                 /* 无效的事件控制块指针  */
        *err = OS_ERR_PEVENT_NULL;
        return (pevent);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {  /* 错误的事件类型        */
        *err = OS_ERR_EVENT_TYPE;
        return (pevent);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                      /* 是否有任务等待消息 */
        tasks_waiting = TRUE;                              /* 有任务等待         */
    } else {
        tasks_waiting = FALSE;                             /* 无任务等待         */
    }
    switch (opt) {
        case OS_DEL_NO_PEND:                               /* 无任务等待删除    */
             if (tasks_waiting == FALSE) {
                 pq                  = (OS_Q *)pevent->OSEventPtr;  /* 返还队列控制块 */
                 pq->OSQPtr          = OSQFreeList;
                 OSQFreeList         = pq;
                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
                 pevent->OSEventPtr  = OSEventFreeList;    /* 返还事件控制块  */
                 OSEventFreeList     = pevent;             
                 OS_EXIT_CRITICAL();
                 *err = OS_NO_ERR;
                 return ((OS_EVENT *)0);                       
             } else {
                 OS_EXIT_CRITICAL();
                 *err = OS_ERR_TASK_WAITING;
                 return (pevent);
             }

        case OS_DEL_ALWAYS:                                /* 无条件删除       */
             while (pevent->OSEventGrp != 0x00) {          /* 就绪所有等待任务 */
                 OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q);
             }
             pq                  = (OS_Q *)pevent->OSEventPtr;/* 返还队列控制块 */
             pq->OSQPtr          = OSQFreeList;
             OSQFreeList         = pq;
             pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
             pevent->OSEventPtr  = OSEventFreeList;        /* 返还事件控制块 */
             OSEventFreeList     = pevent;                       
             OS_EXIT_CRITICAL();
             if (tasks_waiting == TRUE) {                 
                 OS_Sched();                               /* 任务调度 */
             }
             *err = OS_NO_ERR;
             return ((OS_EVENT *)0);                       

        default:
             OS_EXIT_CRITICAL();
             *err = OS_ERR_INVALID_OPT;
             return (pevent);
    }
}
#endif

/*$PAGE*/
/*
*******************************************************************************************
*                                           清空消息队列
*
* brief       : 该函数用于清空队列内的消息
*
* pevent      : 指向事件控制块的指针
*
* Returns     : OS_NO_ERR           成功
*               OS_ERR_EVENT_TYPE   错误的事件类型
*               OS_ERR_PEVENT_NULL  无效的事件控制块指针
********************************************************************************************
*/

#if OS_Q_FLUSH_EN > 0
INT8U  OSQFlush (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3                       
    OS_CPU_SR  cpu_sr;
#endif
    OS_Q      *pq;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* 无效的事件控制块指针          */
        return (OS_ERR_PEVENT_NULL);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* 错误的事件类型                */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    pq             = (OS_Q *)pevent->OSEventPtr;      /* 获取队列控制块               */
    pq->OSQIn      = pq->OSQStart;                    /* 清空队列                     */
    pq->OSQOut     = pq->OSQStart;
    pq->OSQEntries = 0;
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif

/*$PAGE*/
/*
**********************************************************************************************
*                                     请求消息
*
* brief     : 该函数用于从消息队列中请求一则消息
*
* pevent    : 指向事件控制块的指针
*
* timeout   : 超时时限
*
*  err      : 指向错误代码的指针,可能取值:
*
*               OS_NO_ERR           成功
*               OS_TIMEOUT          超时
*               OS_ERR_EVENT_TYPE   错误的事件类型
*               OS_ERR_PEVENT_NULL  无效的事件控制块指针
*               OS_ERR_PEND_ISR     不能再中断中请求
*
* Returns    : != (void *)0  请求成功
*              == (void *)0  请求失败
***********************************************************************************************
*/

void  *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                       
    OS_CPU_SR  cpu_sr;
#endif
    void      *msg;
    OS_Q      *pq;


    if (OSIntNesting > 0) {                      /* 不允许中断中请求消息 */
        *err = OS_ERR_PEND_ISR;                               
        return ((void *)0);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {               /* 无效的事件控制块     */
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* 错误的事件类型       */
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
#endif
    OS_ENTER_CRITICAL();
    pq = (OS_Q *)pevent->OSEventPtr;             /* 获取队列控制块       */
    if (pq->OSQEntries > 0) {                    /* 队列中是否有消息     */
        msg = *pq->OSQOut++;                     /* 取出消息             */
        pq->OSQEntries--;                        /* 消息数减1            */
        if (pq->OSQOut == pq->OSQEnd) {          /* 调整指针实现循环队列 */
            pq->OSQOut = pq->OSQStart;
        }
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return (msg);                                          
    }
    OSTCBCur->OSTCBStat |= OS_STAT_Q;            /* 等待消息状态  */
    OSTCBCur->OSTCBDly   = timeout;              /* 记录超时时限  */
    OS_EventTaskWait(pevent);                    /* 使任务进入等待状态 */
    OS_EXIT_CRITICAL();
    OS_Sched();                                  /* 任务调度      */
    OS_ENTER_CRITICAL();
    msg = OSTCBCur->OSTCBMsg;
    if (msg != (void *)0) {                      /* 是否收到了消息 */
        OSTCBCur->OSTCBMsg      = (void *)0;     /* 请空消息       */
        OSTCBCur->OSTCBStat     = OS_STAT_RDY;   /* 就绪态         */
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* 取消关联       */
        OS_EXIT_CRITICAL();
        *err                    = OS_NO_ERR;
        return (msg);                                                 
    }
    OS_EventTO(pevent);                          /* 超时使任务就绪 */
    OS_EXIT_CRITICAL();
    *err = OS_TIMEOUT;                           /* Indicate a timeout       */
    return ((void *)0);                                                  
}
/*$PAGE*/
/*
**********************************************************************************************
*                                        向队列发送一则消息
*
* breif    : 该函数用于向队列发送一则消息,由.OSQIn插入,先进先出
*
* pevent   : 指向事件控制块的指针
*
* msg      : 指向消息的指针
*
* Returns  : OS_NO_ERR             成功
*            OS_Q_FULL             队列已满
*            OS_ERR_EVENT_TYPE     错误的事件类型
*            OS_ERR_PEVENT_NULL    无效的事件控制块指针
*            OS_ERR_POST_NULL_PTR  发送的消息不能为空
***********************************************************************************************
*/

#if OS_Q_POST_EN > 0
INT8U  OSQPost (OS_EVENT *pevent, void *msg)
{
#if OS_CRITICAL_METHOD == 3                    
    OS_CPU_SR  cpu_sr;
#endif
    OS_Q      *pq;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* 无效的事件控制块指针 */
        return (OS_ERR_PEVENT_NULL);
    }
    if (msg == (void *)0) {                           /* 发送的消息不能为空   */
        return (OS_ERR_POST_NULL_PTR);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* 错误的事件类型       */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                 /* 是否有任务等待       */
        OS_EventTaskRdy(pevent, msg, OS_STAT_Q);      /* 就绪最高优先级任务   */
        OS_EXIT_CRITICAL();
        OS_Sched();                                   /* 任务调度             */
        return (OS_NO_ERR);
    }
    pq = (OS_Q *)pevent->OSEventPtr;                  /* 获取队列控制块       */
    if (pq->OSQEntries >= pq->OSQSize) {              /* 队列已满             */
        OS_EXIT_CRITICAL();
        return (OS_Q_FULL);
    }
    *pq->OSQIn++ = msg;                               /* 插入消息             */
    pq->OSQEntries++;                                 /* 消息数加1            */
    if (pq->OSQIn == pq->OSQEnd) {                    /* 调整指针实现循环队列 */
        pq->OSQIn = pq->OSQStart;
    }
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*******************************************************************************************
*                                   向队列发送一则消息
*
* breif   : 该函数用于向队列发送一则消息,由.OSQOut插入,先进后出
*
* pevent  : 指向事件控制块的指针
*
* msg     : 指向消息的指针
*
* Returns : OS_NO_ERR             成功
*           OS_Q_FULL             队列已满
*           OS_ERR_EVENT_TYPE     错误的时间类型
*           OS_ERR_PEVENT_NULL    无效的事件控制块指针
*           OS_ERR_POST_NULL_PTR  发送的消息不能为空
*******************************************************************************************
*/

#if OS_Q_POST_FRONT_EN > 0
INT8U  OSQPostFront (OS_EVENT *pevent, void *msg)
{
#if OS_CRITICAL_METHOD == 3                         
    OS_CPU_SR  cpu_sr;
#endif
    OS_Q      *pq;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* 无效的事件控制块指针 */
        return (OS_ERR_PEVENT_NULL);
    }
    if (msg == (void *)0) {                           /* 发送的消息不能为空  */
        return (OS_ERR_POST_NULL_PTR);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* 错误的事件类型       */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                 /* 是否有任务在等待消息 */
        OS_EventTaskRdy(pevent, msg, OS_STAT_Q);      /* 就绪最高级等待任务   */
        OS_EXIT_CRITICAL();
        OS_Sched();                                   /* 任务调度             */
        return (OS_NO_ERR);
    }
    pq = (OS_Q *)pevent->OSEventPtr;                  /* 获取队列控制块       */
    if (pq->OSQEntries >= pq->OSQSize) {              /* 队列已满             */
        OS_EXIT_CRITICAL();
        return (OS_Q_FULL);
    }
    if (pq->OSQOut == pq->OSQStart) {                 /* 调整指针    */
        pq->OSQOut = pq->OSQEnd;
    }
    pq->OSQOut--;
    *pq->OSQOut = msg;                                /* 插入消息    */
    pq->OSQEntries++;                                 /* 消息数加1   */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*******************************************************************************************
*                                        向队列发送一则消息
*
* breif     : 该函数用于向队列发送一则消息
*
* pevent    : 指向事件控制块的指针
*
* msg       : 指向消息的指针
*
* opt       : 发送选项,可能取值:
*               OS_POST_OPT_NONE         先进先出
*               OS_POST_OPT_BROADCAST    广播
*               OS_POST_OPT_FRONT        先进后出
*
* Returns   : OS_NO_ERR             成功
*             OS_Q_FULL             队列已满
*             OS_ERR_EVENT_TYPE     错误的事件类型
*             OS_ERR_PEVENT_NULL    无效的事件控制块指针
*             OS_ERR_POST_NULL_PTR  发送的消息不能为空
*******************************************************************************************
*/

#if OS_Q_POST_OPT_EN > 0
INT8U  OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
{
#if OS_CRITICAL_METHOD == 3                     
    OS_CPU_SR  cpu_sr;
#endif
    OS_Q      *pq;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* 无效的事件控制块指针 */
        return (OS_ERR_PEVENT_NULL);
    }
    if (msg == (void *)0) {                           /* 发送的消息不能为空   */
        return (OS_ERR_POST_NULL_PTR);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* 错误的事件类型        */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                 /* 是否有任务等待消息 */
        if ((opt & OS_POST_OPT_BROADCAST) != 0x00) {  /* 是否广播消息       */
            while (pevent->OSEventGrp != 0x00) {      /* 就绪所有等待任务   */
                OS_EventTaskRdy(pevent, msg, OS_STAT_Q);
            }
        } else {
            OS_EventTaskRdy(pevent, msg, OS_STAT_Q);  /* 就绪最高优先级任务  */
        }
        OS_EXIT_CRITICAL();
        OS_Sched();                                   /* 任务调度     */
        return (OS_NO_ERR);
    }
    pq = (OS_Q *)pevent->OSEventPtr;                  /* 或许队列控制块       */
    if (pq->OSQEntries >= pq->OSQSize) {              /* 队列已满             */
        OS_EXIT_CRITICAL();
        return (OS_Q_FULL);
    }
    if ((opt & OS_POST_OPT_FRONT) != 0x00) {          /* 先进后出         */
        if (pq->OSQOut == pq->OSQStart) {            
            pq->OSQOut = pq->OSQEnd;                       
        }
        pq->OSQOut--;
        *pq->OSQOut = msg;                            /* 先进先出          */
    } else {                                                            
        *pq->OSQIn++ = msg;                           
        if (pq->OSQIn == pq->OSQEnd) {                
            pq->OSQIn = pq->OSQStart;
        }
    }
    pq->OSQEntries++;                                 /* 消息数加1         */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
***********************************************************************************************
*                                        查询队列
*
* brief     : 该函数用与查询消息队列信息.
*
* pevent    : 指向事件控制块的指针
*
* pdata     : 指向消息队列信息的数据结构指针
*
* Returns   : OS_NO_ERR           成功
*             OS_ERR_EVENT_TYPE   错误的事件类型
*             OS_ERR_PEVENT_NULL  无效的事件控制块指针
************************************************************************************************
*/

#if OS_Q_QUERY_EN > 0
INT8U  OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3                               
    OS_CPU_SR  cpu_sr;
#endif
    OS_Q      *pq;
    INT8U     *psrc;
    INT8U     *pdest;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                         /* 无效的事件控制块指针 */
        return (OS_ERR_PEVENT_NULL);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {          /* 错误的时间类型        */
        return (OS_ERR_EVENT_TYPE);
    }
#endif
    OS_ENTER_CRITICAL();
    pdata->OSEventGrp = pevent->OSEventGrp;                /* 复制等待任务链表       */
    psrc              = &pevent->OSEventTbl[0];
    pdest             = &pdata->OSEventTbl[0];
#if OS_EVENT_TBL_SIZE > 0
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 1
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 2
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 3
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 4
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 5
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 6
    *pdest++          = *psrc++;
#endif

#if OS_EVENT_TBL_SIZE > 7
    *pdest            = *psrc;
#endif
    pq = (OS_Q *)pevent->OSEventPtr;                       /* 获取队列控制块 */
    if (pq->OSQEntries > 0) {
        pdata->OSMsg = *pq->OSQOut;                        /* 取出消息       */
    } else {
        pdata->OSMsg = (void *)0;
    }
    pdata->OSNMsgs = pq->OSQEntries;                       /* 消息数   */
    pdata->OSQSize = pq->OSQSize;                          /* 队列大小 */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif                                                                    

/*$PAGE*/
/*
***************************************************************************************
*                                      初始化消息队列
*
* brief : 被函数 OSInit() 调用去初始化消息队列,你的应用中不应该调用该函数. 
*
****************************************************************************************
*/

void  OS_QInit (void)
{
#if OS_MAX_QS == 1
    OSQFreeList         = &OSQTbl[0];            /* 只有一个 */
    OSQFreeList->OSQPtr = (OS_Q *)0;
#endif

#if OS_MAX_QS >= 2                               /* 超过一个 */
    INT16U  i;
    OS_Q   *pq1;
    OS_Q   *pq2;


    pq1 = &OSQTbl[0];
    pq2 = &OSQTbl[1];
    for (i = 0; i < (OS_MAX_QS - 1); i++) {    /* 初始化队列控制块为单向量表 */
        pq1->OSQPtr = pq2;
        pq1++;
        pq2++;
    }
    pq1->OSQPtr = (OS_Q *)0;                    /* 对后一个队列控制块    */
    OSQFreeList = &OSQTbl[0];                   /* 空队列控制块链表表头  */
#endif
}
#endif                                                                         
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七七云享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值