반응형

 

 

우선순위 높은 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() {}  


반응형

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

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

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

+ Recent posts