제로 부터 UCOSII 운영 체제 학습 11 - 메시지 대기 열

제로 부터 UCOSII 운영 체제 학습 11 - 메시지 대기 열
1. 메시지 대기 열 은 무엇 입 니까?
(1) 여러 메 일 을 전달 하 는 작업 간 통신 방식
(2) 메시지 대기 열 에서 UCOSII 의 다른 통신 메커니즘 은 하나의 작업 을 허용 하거나 서비스 서브루틴 을 중단 하여 다른 작업 에 포인터 로 정 의 된 변수 나 다른 작업 을 보 낼 수 있 도록 합 니 다.구체 적 인 응용 이 다 르 기 때문에 포인터 마다 메 시 지 를 포함 한 데이터 구 조 를 가리 키 는 변수 유형 도 다르다.
(3) UCOSII 는 메시지 큐 를 조작 하 는 함수 9 개 를 제공 합 니 다. OSQCreate (), OSQDel (), OSQPend (), OSQPost (), OSQPostFront () 등 입 니 다.
(4) 메 시 지 를 보 내 는 대기 열 에 있 는 함수 OSQPost (), OSQPostFront (), OSQPostOpt () 기능 함수 중 하 나 를 호출 해 야 합 니 다.
(5) 그 중에서 메시지 대기 열 은 여러 메 일 로 구 성 된 배열 로 간주 되 는데 그들 은 하나의 대기 작업 목록 을 공유 할 뿐 모든 포인터 가 가리 키 는 데이터 구조 유형 은 구체 적 인 응용 프로그램 에 의 해 결정 된다.
2. 메시지 큐 는 어떻게 사용 합 니까?
(1) 메시지 대기 열 을 실현 하 는 데 필요 한 각종 데이터 구조 입 니 다.
OS_EVENT_TYPE_Q == OSEVENTType; OSEventCnt == 0x00; OSEventPtr == OS_Q = = 한 배열 을 가리 키 는 배열 헤더 함수
메시지 큐 에 사용 할 데이터 구조
(2) 메 시 지 는 메모리 에 저 장 된 데이터 입 니 다. UCOS 의 메 시 지 는 이 메모리 의 첫 번 째 주 소 를 전달 하 는 것 입 니 다. PEND 가 요청 한 메 시 지 는 이 메모리 의 첫 번 째 주소 입 니 다. 그리고 이 주소 부터 메 시 지 를 읽 으 면 됩 니 다. 일반적인 상황 에서 이 메모 리 는 하나의 배열 을 정의 하여 이 루어 집 니 다. 배열 이름 은 메모리 의 첫 번 째 주소 입 니 다.
(3) 이벤트 제어 블록 ECB 기록 대기 작업 목록 이 필요 합 니 다. 또한 이벤트 제어 블록 은 여러 메시지 큐 의 조작 과 신 호 량 함수, 상호 배척 성 신 호 량 과 메 일 박스 에서 같은 코드 를 사용 할 수 있 습 니 다.
(4) 메시지 대기 열 을 만 들 기 전에 메시지 대기 열 최대 메시지 수 와 같은 포인터 배열 을 정의 해 야 합 니 다. 다시 말 하면 이 배열 의 단원 수 는 대기 열 에 있 는 단원 수 와 일치 합 니 다.
3. 간단 한 인 스 턴 스: 메시지 큐 를 어떻게 사용 하 는 지 설명 합 니 다.
메시지 큐 는 사실 여러 메시지 메 일의 응용 이다.
/ / 먼저 메시지 큐 의 저장 주 소 를 정의 합 니 다. 최대 256 개의 메 시 지 를 지원 합 니 다: void * MsgGrp [256];
/ / 열 메시지 표시 작업 void qmsgshowtask(void pdata) { u8 p; u8 err; while (1) {p = OSQpend (q msg, 0, & err); / 요청 메시지 큐 LCD ShowString (5, 170, 240, 16, 16, p); / / 메시지 표시 myfree (SRAMIN, p);}}
/ / 그리고 임의의 함수 의 임무: void tmr 3callback () {OSQPost (q msg, p); / / 발송 대기 열}
void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
    void  *msg;
    OS_Q  *pq;

    pq = pevent->OSEventPtr;                     /* Point at queue control block                       */
//           
    if (pq->OSQEntries != 0) {                   
/*                  */
        msg = *pq->OSQOut++;                     
/* Yes, extract oldest message from the queue         */

pq->OSQEntries--;                       
 /* Update the number of entries in the queue          */

if (pq->OSQOut == pq->OSQEnd) 
{         
 /* Wrap OUT pointer if we are at the end of the queue */
            pq->OSQOut = pq->OSQStart;//            
}
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
    } else if (OSIntNesting > 0) {              
 /* See if called from ISR ...                         */
        OS_EXIT_CRITICAL();                      /* ... can't PEND from an ISR                         */
        *err = OS_ERR_PEND_ISR;
    } else {
    //     ,          
        OSTCBCur->OSTCBStat    |= OS_STAT_Q;     /* Task will have to pend for a message to be posted  */
//         
OSTCBCur->OSTCBDly      = timeout;       /* Load timeout into TCB                              */
//               
OSEventTaskWait(pevent);                 /* Suspend task until event or timeout occurs         */
        OS_EXIT_CRITICAL();
//      
OSSched();                               /* Find next highest priority task ready to run       */
        OS_ENTER_CRITICAL();
//     ,          
        if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) {/* Did we get a message?                         */
            OSTCBCur->OSTCBMsg      = (void *)0;      /* Extract message from TCB (Put there by QPost) */
//     ,          


OSTCBCur->OSTCBStat     = OS_STAT_RDY;
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;  /* No longer waiting for event                   */
            OS_EXIT_CRITICAL();
            *err                    = OS_NO_ERR;
        }
//       ,       
               //           

else if (OSTCBCur->OSTCBStat & OS_STAT_Q) 
              { /* Timed out if status indicates pending on Q    */
            OSEventTO(pevent);//          ,             
                        OS_EXIT_CRITICAL();
            msg                     = (void *)0;      /* No message received                           */
            *err                    = OS_TIMEOUT;     /* Indicate a timeout occured                    */
        } else {//   else   :      ,           ,          ( OSQPend()    )
//                      
msg = *pq->OSQOut++;                      /* Extract message from queue                    */
            pq->OSQEntries--;                         /* Update the number of entries in the queue     */
            if (pq->OSQOut == pq->OSQEnd) {           /* Wrap OUT pointer if we are at the end of Q    */
                pq->OSQOut = pq->OSQStart;
            }
            OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
            OS_EXIT_CRITICAL();
            *err = OS_NO_ERR;
        }
    }                                                 
    return (msg);                                     /* Return message received (or NULL)             */
}

좋은 웹페이지 즐겨찾기