OSAL消息相关函数介绍
2015-08-05 11:01
351 查看
重要的数据结构
这里有一点要说明的是:osal_msg_q_t这个指针指向的是消息的的实际内容,即 函数osal_msg_allocate 开辟内存的返回值
还有就是 *next 同样是指向
消息的的实际内容,即 函数osal_msg_allocate 开辟内存的返回值
这里上一张在百度文库里看到的一片文章里的关于消息数据链表的示意图
这个函数有一点不明白
osal_msg_hdr_t *listHdr;
osal_msg_hdr_t *prevHdr = NULL;
osal_msg_hdr_t *foundHdr = NULL;
typedef void * osal_msg_q_t;
osal_msg_q_t osal_qHead;
listHdr = osal_qHead; 两个不同类型的指针赋值总感觉哪里不对呢?
typedef struct { void *next; /* 指向消息队列的下一个节点 */ uint16 len; /* 消息实际内容的大小 */ uint8 dest_id; /* 指向任务的ID */ } osal_msg_hdr_t; typedef struct { uint8 event; /* 事件 */ uint8 status; /* 状态 */ } osal_event_hdr_t; typedef void * osal_msg_q_t;
这里有一点要说明的是:osal_msg_q_t这个指针指向的是消息的的实际内容,即 函数osal_msg_allocate 开辟内存的返回值
还有就是 *next 同样是指向
消息的的实际内容,即 函数osal_msg_allocate 开辟内存的返回值
这里上一张在百度文库里看到的一片文章里的关于消息数据链表的示意图
/********************************************************************* * @fn osal_msg_allocate * * @brief * 为消息分配内存 * This function is called by a task to allocate a message buffer * into which the task will encode the particular message it wishes * to send. This common buffer scheme is used to strictly limit the * creation of message buffers within the system due to RAM size * limitations on the microprocessor. Note that all message buffers * are a fixed size (at least initially). The parameter len is kept * in case a message pool with varying fixed message sizes is later * created (for example, a pool of message buffers of size LARGE, * MEDIUM and SMALL could be maintained and allocated based on request * from the tasks). * * * @param uint8 len - wanted buffer length * * 返回指向分配的消息实际内容缓冲区的指针或者如果分配失败指向NULL * @return pointer to allocated buffer or NULL if allocation failed. */ uint8 * osal_msg_allocate( uint16 len ) { osal_msg_hdr_t *hdr; if ( len == 0 ) return ( NULL ); /* 分配一块 Len(消息实际内容缓冲区大小) + 消息头结构大小(结构体大小) 长度内存 */ hdr = (osal_msg_hdr_t *) osal_mem_alloc( (short)(len + sizeof( osal_msg_hdr_t )) ); /* 获取内存成功,初始化结构体 */ if ( hdr ) { hdr->next = NULL; hdr->len = len; hdr->dest_id = TASK_NO_TASK; return ( (uint8 *) (hdr + 1) ); /* 指向分配的消息实际内容缓冲区的指针 */ } else return ( NULL ); }
/********************************************************************* * @fn osal_msg_deallocate * * @brief * 当消息实际内容缓冲区不为空但是消息头ID为空时,释放已经分配的内存(消息实际内容缓冲区) * 这个函数往往使用在任务调用接收消息函数后对释放整条消息占用内存 * This function is used to deallocate a message buffer. This function * is called by a task (or processing element) after it has finished * processing a received message. * * * @param uint8 *msg_ptr - pointer to new message buffer * * @return SUCCESS, INVALID_MSG_POINTER */ uint8 osal_msg_deallocate( uint8 *msg_ptr ) { uint8 *x; /* 假如消息实际内容缓冲区为NULL,返回无效的消息指针 */ if ( msg_ptr == NULL ) return ( INVALID_MSG_POINTER ); /* 假如消息头的ID不为空,不释放消息内容缓冲区 因为上一句已经判断消息的内容缓冲区是有效的,加上消息头的ID不为空 所以认为这条消息是有效的 */ // don't deallocate queued buffer if ( OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK ) return ( MSG_BUFFER_NOT_AVAIL ); /* 假如消息头的ID为TASK_NO_TASK(指向的任务无效,消息是无效的)则清消息 */ x = (uint8 *)((uint8 *)msg_ptr - sizeof( osal_msg_hdr_t )); /* 释放整条消息占用内存 */ osal_mem_free( (void *)x ); return ( SUCCESS ); }
/********************************************************************* * @fn osal_msg_send * * @brief * 发送消息 * FALSE 表示消息插入对尾 * TRUE 表示消息插入对首 * This function is called by a task to send a command message to * another task or processing element. The sending_task field must * refer to a valid task, since the task ID will be used * for the response message. This function will also set a message * ready event in the destination tasks event list. * * * @param uint8 destination_task - Send msg to Task ID * @param uint8 *msg_ptr - pointer to new message buffer * * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER */ uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ) { return ( osal_msg_enqueue_push( destination_task, msg_ptr, FALSE ) ); }
/********************************************************************* * @fn osal_msg_push_front * * @brief * * This function is called by a task to push a command message * to the head of the OSAL queue. The destination_task field * must refer to a valid task, since the task ID will be used to * send the message to. This function will also set a message * ready event in the destination task's event list. * * @param uint8 destination_task - Send msg to Task ID * @param uint8 *msg_ptr - pointer to message buffer * * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER */ uint8 osal_msg_push_front( uint8 destination_task, uint8 *msg_ptr ) { return ( osal_msg_enqueue_push( destination_task, msg_ptr, TRUE ) ); } /********************************************************************* * @fn osal_msg_enqueue_push * * @brief * 把消息插入消息队列 * This function is called by a task to either enqueue (append to * queue) or push (prepend to queue) a command message to the OSAL * queue. The destination_task field must refer to a valid task, * since the task ID will be used to send the message to. This * function will also set a message ready event in the destination * task's event list. * * @param uint8 destination_task - Send msg to Task ID * @param uint8 *msg_ptr - pointer to message buffer * @param uint8 push - TRUE to push, otherwise enqueue * * @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER */
static uint8 osal_msg_enqueue_push( uint8 destination_task, uint8 *msg_ptr, uint8 push ) { if ( msg_ptr == NULL ) { return ( INVALID_MSG_POINTER ); } /* 释放消息内存 */ if ( destination_task >= tasksCnt ) { osal_msg_deallocate( msg_ptr ); return ( INVALID_TASK ); } /* 检查消息头,假如两个条件都不满足说明该消息该消息还没有分配给任务 */ // Check the message header if ( OSAL_MSG_NEXT( msg_ptr ) != NULL || OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK ) { osal_msg_deallocate( msg_ptr ); return ( INVALID_MSG_POINTER ); } OSAL_MSG_ID( msg_ptr ) = destination_task; if ( push == TRUE ) { /* 插入队首 */ // prepend the message osal_msg_push( &osal_qHead, msg_ptr ); } else { /* 插入队尾 */ // append the message osal_msg_enqueue( &osal_qHead, msg_ptr ); } // Signal the task that a message is waiting osal_set_event( destination_task, SYS_EVENT_MSG ); return ( SUCCESS ); }
/********************************************************************* * @fn osal_msg_receive * * @brief * 接收一条消息 * This function is called by a task to retrieve a received command * message. The calling task must deallocate the message buffer after * processing the message using the osal_msg_deallocate() call. * * @param uint8 task_id - receiving tasks ID * * @return *uint8 - message information or NULL if no message */ uint8 *osal_msg_receive( uint8 task_id ) { osal_msg_hdr_t *listHdr; osal_msg_hdr_t *prevHdr = NULL; osal_msg_hdr_t *foundHdr = NULL; halIntState_t intState; // Hold off interrupts HAL_ENTER_CRITICAL_SECTION(intState); /* 关中断 */ // Point to the top of the queue listHdr = osal_qHead; /* 指向队首 */ // Look through the queue for a message that belongs to the asking task while ( listHdr != NULL ) { if ( (listHdr - 1)->dest_id == task_id ) /* 假如找到任务ID */ { if ( foundHdr == NULL ) /* 假如第一次找到任务ID */ { // Save the first one foundHdr = listHdr; /* 保存第一个任务指针 */ } else { // Second msg found, stop looking /* 假如第二次找到任务ID,退出循环 */ break; } } /* 假如当前节点不是要找到任务,且之前没有找到过 */ if ( foundHdr == NULL ) { prevHdr = listHdr; /* 保存当前节点指针为上一次节点指针*/ } listHdr = OSAL_MSG_NEXT( listHdr ); /* 指向下一节点指针 */ } /* 退出循环之后判断是没有消息,一条消息,还是多条消息 */ // Is there more than one? /* 假如不为NULL,说明是多条消息,告诉任务还有消息是在等待的 */ if ( listHdr != NULL ) { // Yes, Signal the task that a message is waiting osal_set_event( task_id, SYS_EVENT_MSG ); } else { // No more /* 只有一条消息或者没有消息 */ osal_clear_event( task_id, SYS_EVENT_MSG ); } // Did we find a message? if ( foundHdr != NULL ) /* 判断是否找到了消息 */ { // Take out of the link list osal_msg_extract( &osal_qHead, foundHdr, prevHdr ); /* 从消息队列中取出消息 */ } // Release interrupts HAL_EXIT_CRITICAL_SECTION(intState); /* 开中断 */ return ( (uint8*) foundHdr ); /* 返回消息头指针 */ }
这个函数有一点不明白
osal_msg_hdr_t *listHdr;
osal_msg_hdr_t *prevHdr = NULL;
osal_msg_hdr_t *foundHdr = NULL;
typedef void * osal_msg_q_t;
osal_msg_q_t osal_qHead;
listHdr = osal_qHead; 两个不同类型的指针赋值总感觉哪里不对呢?
/************************************************************************************************** * @fn osal_msg_find * * @brief This function finds in place an OSAL message matching the task_id and event * parameters. * * input parameters * * @param task_id - The OSAL task id that the enqueued OSAL message must match. * @param event - The OSAL event id that the enqueued OSAL message must match. * * output parameters * * None. * * @return NULL if no match, otherwise an in place pointer to the matching OSAL message. ************************************************************************************************** */ osal_event_hdr_t *osal_msg_find(uint8 task_id, uint8 event) { osal_msg_hdr_t *pHdr; halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts. /* 指向消息头 */ pHdr = osal_qHead; // Point to the top of the queue. // Look through the queue for a message that matches the task_id and event parameters. while (pHdr != NULL) { if (((pHdr-1)->dest_id == task_id) && (((osal_event_hdr_t *)pHdr)->event == event)) { break; } pHdr = OSAL_MSG_NEXT(pHdr); } HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts. return (osal_event_hdr_t *)pHdr; }
/********************************************************************* * @fn osal_msg_enqueue * * @brief * 把消息放到队尾 * This function enqueues an OSAL message into an OSAL queue. * * @param osal_msg_q_t *q_ptr - OSAL queue * @param void *msg_ptr - OSAL message * * @return none */ void osal_msg_enqueue( osal_msg_q_t *q_ptr, void *msg_ptr ) { void *list; halIntState_t intState; // Hold off interrupts HAL_ENTER_CRITICAL_SECTION(intState); /* 关中断 */ OSAL_MSG_NEXT( msg_ptr ) = NULL; /* 消息头next指向NULL */ /* 假如是第一条消息 */ // If first message in queue if ( *q_ptr == NULL ) { *q_ptr = msg_ptr; /* 消息表头指向该消息 */ } else { // Find end of queue for ( list = *q_ptr; OSAL_MSG_NEXT( list ) != NULL; list = OSAL_MSG_NEXT( list ) ); // Add message to end of queue OSAL_MSG_NEXT( list ) = msg_ptr; /* 消息对尾节点next指向该消息 */ } // Re-enable interrupts HAL_EXIT_CRITICAL_SECTION(intState); /* 开中断 */ }
/********************************************************************* * @fn osal_msg_dequeue * * @brief * 从消息队列队首释放一个消息 * This function dequeues an OSAL message from an OSAL queue. * * @param osal_msg_q_t *q_ptr - OSAL queue * * @return void * - pointer to OSAL message or NULL of queue is empty. */ void *osal_msg_dequeue( osal_msg_q_t *q_ptr ) { void *msg_ptr = NULL; halIntState_t intState; // Hold off interrupts HAL_ENTER_CRITICAL_SECTION(intState); if ( *q_ptr != NULL ) { // Dequeue message msg_ptr = *q_ptr; *q_ptr = OSAL_MSG_NEXT( msg_ptr ); OSAL_MSG_NEXT( msg_ptr ) = NULL; OSAL_MSG_ID( msg_ptr ) = TASK_NO_TASK; } // Re-enable interrupts HAL_EXIT_CRITICAL_SECTION(intState); return msg_ptr; }
/********************************************************************* * @fn osal_msg_push * * @brief * 把消息放到队首 * This function pushes an OSAL message to the head of an OSAL * queue. * * @param osal_msg_q_t *q_ptr - OSAL queue * @param void *msg_ptr - OSAL message * * @return none */ void osal_msg_push( osal_msg_q_t *q_ptr, void *msg_ptr ) { halIntState_t intState; // Hold off interrupts HAL_ENTER_CRITICAL_SECTION(intState); // Push message to head of queue OSAL_MSG_NEXT( msg_ptr ) = *q_ptr; *q_ptr = msg_ptr; // Re-enable interrupts HAL_EXIT_CRITICAL_SECTION(intState); }
/********************************************************************* * @fn osal_msg_extract * * @brief * 从一个消息队列中取出消息,清除消息头的有效数据 * This function extracts and removes an OSAL message from the * middle of an OSAL queue. * * @param osal_msg_q_t *q_ptr - OSAL queue * @param void *msg_ptr - OSAL message to be extracted * @param void *prev_ptr - OSAL message before msg_ptr in queue * * @return none */ void osal_msg_extract( osal_msg_q_t *q_ptr, void *msg_ptr, void *prev_ptr ) { halIntState_t intState; // Hold off interrupts HAL_ENTER_CRITICAL_SECTION(intState); /* 关中断 */ /* 假如要找的消息为队首消息 */ if ( msg_ptr == *q_ptr ) { // remove from first *q_ptr = OSAL_MSG_NEXT( msg_ptr ); } else { // remove from middle OSAL_MSG_NEXT( prev_ptr ) = OSAL_MSG_NEXT( msg_ptr ); } /* 释放的ID,为以后调用清除该消息准备条件 */ OSAL_MSG_NEXT( msg_ptr ) = NULL; OSAL_MSG_ID( msg_ptr ) = TASK_NO_TASK; // Re-enable interrupts HAL_EXIT_CRITICAL_SECTION(intState); /* 开中断 */ }
相关文章推荐
- 如何利用百度蜘蛛referer找到报错页面入口?
- 二叉搜索树
- Terrible Sets(求矩形的最大面积(递增栈))
- 在Linux中打开了太多文件(Too many open files)的解决方法
- 南邮 OJ 1207 众数问题
- 《Objective-C基础教程》第2章 对C的扩展
- error C1189: #error : Please use the /MD switch for _AFXDLL builds---解决方案
- iOS开发之NSString的几条实用技巧
- hdu 2104 hide handkerchief
- 单例模式
- C++四种不同的对象生存方式
- 二叉树的递归与非递归遍历
- play框架配置使用过程中遇到的各种疑难问题汇总(学习同事经验)
- 第1章 程序设计入门
- 乱码解决方案
- lvcreate 常用命令举例
- Linux下查看CPU信息[/proc/cpuinfo]
- Leetcode 179 Largest Number 构造最大数字
- hdu 5349 MZL's simple problem (2015多校第五场第7题) multiset
- 解决Java应用程序连接Acces问题心得一