ABOUT ME

-

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

     

     

    공유자원인 시리얼을 두 개의 태스크가 동시에 기록하면 아래처럼 첫번째 태스크에서 다 기록하기 전에 두번째 태스크가 선점하여 문자열을 출력하는 원치 않은 결과를 얻을 수 있다.

     

    이를 방지하기 위해서 뮤텍스 타입의 세마포어를 사용하여 시리얼을 사용 중일 때에는 다른 태스크가 시리얼에 접근 할 수 없도록 막는다.

    정상적으로 수행되는 경우의 결과…

     

    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. static void prvPrintTask( void *pvParameters );  
    12.     
    13. //뮤텍스 타입 세마포어를 이용하여 공유자원인 시리얼을 동시에 사용하지 못하도록한 새로운  
    14. //문자열 출력함수  
    15. static void prvNewPrintString( const char *pcString );  
    16.     
    17. /*-----------------------------------------------------------*/  
    18.     
    19.     
    20. //SemaphoreHandle_t 타입의 변수를 여기에서는 뮤텍스 타입의 세마포어를 위해 사용된다.  
    21. //공유자원인 시리얼로의 출력을 동시에 사용하지 않기 위해서 사용됨(상호배제  mutual exclusive)  
    22. //예를 들어 첫번째 문자열 출력도중에 두번째 문자열을 출력하게 되는 상황이 안벌어지게 한다.  
    23. SemaphoreHandle_t xMutex;  
    24.     
    25.     
    26. void setup( void )  
    27. {  
    28.   Serial.begin(9600);  
    29.       
    30.   //뮤텍스 타입의 세마포어를 생성한다.  
    31.   xMutex = xSemaphoreCreateMutex();  
    32.     
    33.       
    34.   //난수를 발생시키기 위한 시드값  
    35.   //태스크가 랜덤한 시간동안 블록되게 만들때 사용할 rand함수를 사용 하위한 작업  
    36.   srand( 567 );  
    37.     
    38.   if( xMutex != NULL ) //뮤텍스타입의 세마포어가 정상적으로 생성되었다면  
    39.   {  
    40.     
    41.     // 개의 문자열을 출력하는 태스크를 생성한다.  
    42.     //우선순위를 다르게 했기 때문에 하나의 태스크를 수행중 다른 태스크가 실행될수 있게 했다.  
    43.     xTaskCreate( prvPrintTask, "Print1", 200, (void*)"Task 1 ******************************************\r\n", 1, NULL );  
    44.     xTaskCreate( prvPrintTask, "Print2", 200, (void*)"Task 2 ------------------------------------------\r\n", 2, NULL );  
    45.     
    46.     //스케줄러를 시작한다.  
    47.     vTaskStartScheduler();  
    48.   }  
    49.     
    50.   //여기에 도달하면 아마도 메모리 부족  
    51.       
    52.   for( ;; );  
    53. //  return 0;  
    54. }  
    55. /*-----------------------------------------------------------*/  
    56.     
    57. static void prvNewPrintString( const char *pcString )  
    58. {  
    59.   //뮤텍스 타입 세마포어를 무한 시간동안 기다리게 된다.  
    60.   //얻지 못하면 블록상태가 되버림.얻을때에만 블록이 풀리기 떄문에 리턴값을 체크할 필요가 없음.  
    61.   xSemaphoreTake( xMutex, portMAX_DELAY );  
    62.   {  
    63.     /* The following line will only execute once the semaphore has been 
    64.     successfully obtained - so standard out can be accessed freely. */  
    65.     //printf( "%s", pcString );  
    66.     //fflush( stdout );  
    67.     
    68.       Serial.print(pcString);  
    69.       Serial.flush(); //시리얼 포트에 있는 데이터가  기록될때 까지 대기한다.(아두이노 1.0 이전 버전에선 삭제했음)  
    70.     
    71.   }  
    72.   xSemaphoreGive( xMutex );  
    73.     
    74.     
    75.   if( Serial.available() ) //버퍼가 비어있지 않다면 True 반환한다.  
    76.   {  
    77.     //커널 틱을 정지시키고 모든 생성된 태스크들을 삭제한다  
    78.     //시리얼 포트에 있는 데이터가  기록될때 까지 위에서 기다렸는데도 버퍼가 꽉차있다는 것은   
    79.     //먼가 문제가 있는 것이므로 스케줄러를 다시 시작하는 것으로 보인다.  
    80.     vTaskEndScheduler();  
    81.   }  
    82. }  
    83. /*-----------------------------------------------------------*/  
    84.     
    85. static void prvPrintTask( void *pvParameters )  
    86. {  
    87.   //파라메터로 받은 문자열을   
    88.   char *pcStringToPrint;  
    89.   pcStringToPrint = ( char * ) pvParameters;  
    90.     
    91.   for( ;; )  
    92.   {  
    93.     //시리얼로 문자열을 출력하기 위해 새로 만든 함수를 이용한다.  
    94.     prvNewPrintString( pcStringToPrint );  
    95.     
    96.     //rand 생성한 임의의 시간동안 대기한다.  
    97.     //여기에서 critical section없이 사용하려면 rand함수가 reentrant해야 한다  
    98.     //여러 쓰레드에서 코드를 동시에 수행하더라도 실행결과가 정확함을 보장한다는 것이다.  
    99.     vTaskDelay( ( rand() & 0x1FF ) );  
    100.   }  
    101. }  
    102. //------------------------------------------------------------------------------  
    103. void loop() {}  


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

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

    유튜브 구독하기


    댓글 0

Designed by Tistory.