ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 아두이노 freeRTOS 튜토리얼 16
    Arduino Uno/FreeRTOS 2015. 1. 16. 23:52

     

     

    우선순위 높은 Print2 태스크가 실행되어 자신에 해당되는 문자열을 큐에 넣고 임의의 시간 대기한다.

    그 사이 태스크 1이 실행되어 자신에 해당되는 문자열을 넣고 임의의 시간 대기한다. 태스크2의 대기 시간보다 짧아서 여러 번 실행될 수 있다.

    다른 태스크들이 블록되어 있는 동안 우선순위 가장 낮은 Gatekeeper 태스크가 큐에 있는 데이터를 출력한다.

    틱 후크 인터럽트가 발생하면 틱 인터럽트 서비스 루틴이 실행되어 큐에 대응되는 문자열을 넣는다.

    역시 나중에 Gatekeeper 태스크에서 출력되어 진다.

     

     

    1. /* FreeRTOS.org includes. */  
    2. #include "FreeRTOS_AVR.h"  
    3. //#include "task.h"  
    4. //#include "semphr.h"  
    5.     
    6. /* Compiler includes. */  
    7. //#include <stdlib.h>  
    8. //#include <stdio.h>  
    9.     
    10.     
    11. //gatekeeper 태스크로 메시지를 보내기 위한 Print1,Print2 태스크에서 사용되는 함수  
    12. static void prvPrintTask( void *pvParameters );  
    13.     
    14. //gatekeeper 태스크에서 사용되는 함수큐에서 메시지를 꺼내어 출력한다.  
    15. //시리얼에 값을 기록하기 위한 전용 태스크가 되는 셈이다.  
    16. static void prvStdioGatekeeperTask( void *pvParameters );  
    17.     
    18. //출력할때 사용할 문자열 정의  
    19. static char *pcStringsToPrint[] =  
    20. {  
    21.   "Task 1 ****************************************************\r\n",  
    22.   "Task 2 ----------------------------------------------------\r\n",  
    23.   "Message printed from the tick hook interrupt ##############\r\n"  
    24. };  
    25.     
    26. /*-----------------------------------------------------------*/  
    27.     
    28.     
    29. //gatekeeper 태스크로 데이터를 보낼때 사용되는 큐에 대한 핸들  
    30. QueueHandle_t xPrintQueue;  
    31.     
    32.     
    33. void setup( void )  
    34. {  
    35.   Serial.begin(9600);  
    36.       
    37.   //5개까지 문자열을 저장할 큐를 생성한다.  
    38.     xPrintQueue = xQueueCreate( 5, sizeofchar * ) );  
    39.     
    40.   //난수 발생시 사용할 씨드  
    41.   srand( 567 );  
    42.     
    43.   //큐가 성공적으로 생성되었다면  
    44.   if( xPrintQueue != NULL )  
    45.   {  
    46.         
    47.     //Gatekeeper태스크로 메세지를 보내는 두개의 태스크를 생성한다.  
    48.     //자신에게 맞는 문자열을 출력할  있게 문자열 배열의 인덱스를 파라메터로 넘겨준다  
    49.     xTaskCreate( prvPrintTask, "Print1", 200, ( void * ) 0, 1, NULL );  
    50.     xTaskCreate( prvPrintTask, "Print2", 200, ( void * ) 1, 2, NULL );  
    51.           
    52.     
    53.     //gatekeeper 태스크를 생성한다시리얼로 데이터를 보내는게 유일하게 허용된 태스크이다.  
    54.     xTaskCreate( prvStdioGatekeeperTask, "Gatekeeper", 200, NULL, 0, NULL );  
    55.     
    56.     //스케줄러를 시작한다.  
    57.     vTaskStartScheduler();  
    58.   }  
    59.     
    60.   //메모리가 부족한 상황이면 여기에 도달한다.  
    61.       
    62.   for( ;; );  
    63. //  return 0;  
    64. }  
    65. /*-----------------------------------------------------------*/  
    66.     
    67. static void prvStdioGatekeeperTask( void *pvParameters )  
    68. {  
    69.   char *pcMessageToPrint;  
    70.     
    71.   for( ;; )  
    72.   {  
    73.     //큐에서 메시지를 꺼낸다.  
    74.     //portMAX_DELAY 인자를 사용했기 때문에 큐가 비어있다며 무한히 대기한다  
    75.     xQueueReceive( xPrintQueue, &pcMessageToPrint, portMAX_DELAY );  
    76.     
    77.     //시리얼로 문자열을 출력하고   
    78.     Serial.print(pcMessageToPrint );  
    79.         
    80.     //문자열이 출력완료되기를 기다린다.  
    81.     Serial.flush();  
    82.         
    83.     //버퍼가 비어있지 않다면 True 반환한다.    
    84.     if (Serial.available()) {  
    85.        //커널 틱을 정지시키고 모든 생성된 태스크들을 삭제한다    
    86.        //시리얼 포트에 있는 데이터가  기록될때 까지 위에서 기다렸는데도 버퍼가 꽉차있다는 것은     
    87.        //먼가 문제가 있는 것이므로 스케줄러를 다시 시작하는 것으로 보인다.    
    88.         vTaskEndScheduler();  
    89.     }  
    90.         
    91.     // 다시 xQueueReceive에서 새로운 메세지를 대기한다.  
    92.   }  
    93. }  
    94. /*-----------------------------------------------------------*/  
    95. extern "C"{  // FreeRTOS expectes C linkage  
    96.   // 후크 인터럽트가 발생했을  수행된다.    
    97.   void vApplicationTickHook( void )  
    98.   {  
    99.   static int iCount = 0;  
    100.   portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;  
    101.     
    102.     //후크 함수 내부에서 카운터를 증가시킨다.    
    103.     iCount++;  
    104.     if( iCount >= 200 ) //200틱을 넘을때 마다   
    105.     {  
    106.       //인터럽트 서비스 루틴내에서 큐에 데이터를 넣을때에는 xQueueSendToFrontFromISR함수를 사용한다.  
    107.       // 후크 인터럽트가 발생했음을 알리기위해 큐에 해당되는 메시지를 넣는다.  
    108.       xQueueSendToFrontFromISR( xPrintQueue, &( pcStringsToPrint[ 2 ] ), (BaseType_t*)&xHigherPriorityTaskWoken );  
    109.     
    110.       //카운터를 리셋한다.  
    111.       iCount = 0;  
    112.     }  
    113.   }  
    114. }  
    115. /*-----------------------------------------------------------*/  
    116.     
    117. static void prvPrintTask( void *pvParameters )  
    118. {  
    119.   //파라메터로 자신에게 맞는 문자열을 출력할  있게 문자열 배열의 인덱스 값을 받음  
    120.   int iIndexToString;  
    121.   iIndexToString = ( int ) pvParameters;  
    122.     
    123.   for( ;; )  
    124.   {  
    125.     //iIndexToString값을 이용하여 자신에 해당되는 문자열을 큐에 넣는다.  
    126.     xQueueSendToBack( xPrintQueue, &( pcStringsToPrint[ iIndexToString ] ), 0 );  
    127.     
    128.     //rand 생성한 임의의 시간동안 대기한다.    
    129.     //여기에서 critical section없이 사용하려면 rand함수가 reentrant해야 한다.     
    130.     //여러 쓰레드에서 코드를 동시에 수행하더라도 실행결과가 정확함을 보장한다는 것이다  
    131.     vTaskDelay( ( rand() & 0x1FF ) );  
    132.   }  
    133. }  
    134. //------------------------------------------------------------------------------  
    135. void loop() {}  


    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구독하기


    댓글 0

Designed by Tistory.