반응형

 

 

처음 실행시키면 vIntegerGenerator태스크보다 vStringPrinter태스크의 우선순위가 높기때문에 먼저 실행이 되나 큐가 비어있기때문에 블록 상태가 된다.

 

따라서 vIntegerGenerator태스크가 실행되지만 vTaskDelayUntil함수를 사용했기 때문에 정해준 값인 200밀리세컨드마다 대기상태에서 벗어나와 작업을 시작할 수 있다.

 

vIntegerGenerator에서 증가시킨 정수값을 큐에 넣는 것을 5번 반복한 후 인터럽트를 발생시킨다.

 

인터럽트 서비스 루틴인 vExampleInterruptHandler 함수가 호출된다.

vExampleInterruptHandler에서 정수값을 넣은 큐에서 데이터를 꺼내와서 정수에 대응되는 문자열을 큐에 문자열을 넣는 큐에 넣는다. 정수값을 꺼내오는 큐가 빌때까지 계속 반복한다. 최대 5번 반복하게 된다.

 

인터럽트 서비스 루틴을 마치고 vIntegerGenerator에서 인터럽트 발생 후 코드를 마저하기전에 큐에서 데이터를 꺼내와 출력하는 vStringPrinter 태스크가 먼저 실행되도록 강제로 컨텍스트 스위치를 시킨다.

vIntegerGenerator보다 우선순위가 더 높기 떄문에 vStringPrinter이 먼저 실행되게 된다.

vStringPrinter 태스크가 실행되는데 큐에 데이터가 있기 때문에 꺼내와서 화면에 출력한다. 5번 문자열을 출력하고 나면 다시 대기상태가 되고 다시 vIntegerGenerator태스크가 실행된다.

 

 

 

  1. /* FreeRTOS.org includes. */  
  2. #include "FreeRTOS_AVR.h"  
  3. //#include "task.h"  
  4. //#include "queue.h"  
  5. //#include "portasm.h"  
  6.     
  7. /* Demo includes. */  
  8. #include "basic_io_avr.h"  
  9.     
  10.     
  11. //숫자를 증가시켜서 큐에 넣는 함수  
  12. static void vIntegerGenerator( void *pvParameters );  
  13.     
  14. //큐에서 문자열 데이터를 꺼내와 출력하는 함수  
  15. static void vStringPrinter( void *pvParameters );  
  16.     
  17. //인터럽트 서비스 루틴  
  18. //중가된 숫자를 이용하여 문자열 데이터를 큐에 넣는다.  
  19. static void vExampleInterruptHandler( void );  
  20.     
  21.     
  22. unsigned long ulNext = 0;  
  23. unsigned long ulCount;  
  24. unsigned long ul[ 100 ];  
  25.     
  26. /*-----------------------------------------------------------*/  
  27.     
  28. //큐에 접근시 사용될 변수  
  29. QueueHandle_t xIntegerQueue, xStringQueue;  
  30.     
  31. // pin to generate interrupts  
  32. #if defined(CORE_TEENSY)  
  33. const uint8_t interruptPin = 0;  
  34. #elfif defined(__AVR_ATmega32U4__)  
  35. const uint8_t interruptPin = 3;  
  36. #else  // interruptPin  
  37. const uint8_t interruptPin = 2;  
  38. #endif  // interruptPin  
  39.     
  40. void setup( void )  
  41. {  
  42.   Serial.begin(9600);  
  43.     
  44.     
  45.   //10개까지 저장가능한  개의 큐를 생성한다각각 unsigned long char * 타입의 변수를 저장할  있음.  
  46.   xIntegerQueue = xQueueCreate( 10, sizeof( unsigned long ) );  
  47.   xStringQueue = xQueueCreate( 10, sizeofchar * ) );  
  48.   if ( xIntegerQueue !=0 && xStringQueue != 0 ) //큐가 성공적으로 생성되었으면  
  49.   {  
  50.       /* Install the interrupt handler. */  
  51.     //  _dos_setvect( 0x82, vExampleInterruptHandler );  
  52.         
  53.       //인터럽트핀을 출력으로 설정하고  
  54.        pinMode(interruptPin, OUTPUT);  
  55.            
  56.        //인터럽트 서비스 루틴을 지정한다. LOW->HIGH  전압이 변화시 인터럽트 발생  
  57.        attachInterrupt(0, vExampleInterruptHandler, RISING);  
  58.         
  59.         
  60.       //큐에 값을 넣은  인터럽트를 발생시키는 태스크를 우선순위 1로해서 생성한다.  
  61.       xTaskCreate( vIntegerGenerator, "IntGen", 200, NULL, 1, NULL );  
  62.         
  63.       //우선순위 2로해서 큐에 있는 데이터를 꺼내어 출력하는 태스크를 생성한다.  
  64.       xTaskCreate( vStringPrinter, "String", 200, NULL, 2, NULL );  
  65.         
  66.       //스케줄러를 시작한다.  
  67.       vTaskStartScheduler();  
  68.   }  
  69.   else {}//큐가 성공적으로 생성되지 못함  
  70.       
  71.   //메모리 부족으로 여기에 도달함  
  72.             
  73.   for( ;; );  
  74. //  return 0;  
  75. }  
  76. /*-----------------------------------------------------------*/  
  77.     
  78. static void vIntegerGenerator( void *pvParameters )  
  79. {  
  80.     TickType_t xLastExecutionTime;  
  81.     unsigned portLONG ulValueToSend = 0;  
  82.     int i;  
  83.     
  84.   //vTaskDelayUntil함수에서 사용할 변수를 현재  카운트로 초기화 해준다  
  85.   xLastExecutionTime = xTaskGetTickCount();  
  86.     
  87.   for( ;; )  
  88.   {  
  89.     
  90.     //정확히 200밀리세컨드마다 대기상태에서 벗어난다.  
  91.       vTaskDelayUntil( &xLastExecutionTime, 200 / portTICK_PERIOD_MS );  
  92.     
  93.     //5 반복해서 증가된 값을 큐에 넣는다.  
  94.     for( i = 0; i < 5; i++ )  
  95.     {  
  96.       xQueueSendToBack( xIntegerQueue, &ulValueToSend, 0 );  
  97.       ulValueToSend++;  
  98.     }  
  99.     
  100.     //인터럽트를 발생시킨다.  
  101.     vPrintString( "Generator task - About to generate an interrupt.\r\n" );  
  102.     
  103.     digitalWrite(interruptPin, LOW);  
  104.     digitalWrite(interruptPin, HIGH);  
  105.     
  106.     //인터업트 처리후 하던일을 마저한다.  
  107.     vPrintString( "Generator task - Interrupt generated.\r\n\r\n\r\n" );  
  108.   }  
  109. }  
  110. /*-----------------------------------------------------------*/  
  111.     
  112. static void vStringPrinter( void *pvParameters )  
  113. {  
  114.   char *pcString;  
  115.     
  116.   for( ;; )  
  117.   {  
  118.     //큐에서 문자열을 꺼내온다.  
  119.     //portMAX_DELAY 사용하면 큐에 데이터가 있을때까지 무한히 기다린다.  
  120.     xQueueReceive( xStringQueue, &pcString, portMAX_DELAY );  
  121.     
  122.     /* Print out the string received. */  
  123.     vPrintString( pcString );  
  124.   }  
  125. }  
  126. /*-----------------------------------------------------------*/  
  127. //인터럽트 발생시 호출되어 진다.  
  128. static void vExampleInterruptHandler( void )  
  129. {  
  130.     static portBASE_TYPE xHigherPriorityTaskWoken;  
  131.     static unsigned long ulReceivedNumber;  
  132.         
  133.      
  134.     //문자열들을 static const으로 선언해서 interrupt service routine스택에서 할당되지 않도록한다.  
  135.     //값이 계속 유지됨.  
  136.     static const char *pcStrings[] =  
  137.     {  
  138.       "String 0\r\n",  
  139.       "String 1\r\n",  
  140.       "String 2\r\n",  
  141.       "String 3\r\n"  
  142.     };  
  143.     
  144.   xHigherPriorityTaskWoken = pdFALSE;  
  145.     
  146.   //정수값 넣은 큐가 비어있지 않는 동안 반복한다.  
  147.   while( xQueueReceiveFromISR( xIntegerQueue, &ulReceivedNumber, (BaseType_t*)&xHigherPriorityTaskWoken ) != errQUEUE_EMPTY )  
  148.   {  
  149.      
  150.     //0~3사이 값으로 변환   
  151.     ulReceivedNumber &= 0x03;  
  152.         
  153.     //첫번째 파라메터는 문자열 데이터를 보낼 큐에 대한 핸들  
  154.     //두번째 파라메터는 큐에 복사될 데이터에 대한 포인터  
  155.     //세번째 파라메터는 큐에 데이터가 들어갔는지 여부를 얻기 위한 변수의 주소를 넣는다.  
  156.     xQueueSendToBackFromISR( xStringQueue, &pcStrings[ ulReceivedNumber ], (BaseType_t*)&xHigherPriorityTaskWoken );  
  157.   }  
  158.     
  159.   //인터럽트 서비스 루틴을 마치고 vIntegerGenerator에서 인터럽트 발생  코드를 마저하기전에 큐에서 데이터를 꺼내와   
  160.   //출력하는 vStringPrinter 태스크가 먼저 실행되도록 강제로 컨텍스트 스위치를 시킨다  
  161.   //우선순위가  높기떄문에 vStringPrinter 먼저 실행되게 된다.  
  162.   if( xHigherPriorityTaskWoken == pdTRUE ) //데이터가 성공적으로 큐에 보내진 경우  
  163.   {  
  164.      //강제로 컨텍스트 스위치를 시킨다.  
  165.      vPortYield();  
  166.   }  
  167. }  
  168. //------------------------------------------------------------------------------  
  169. void loop() {}  


반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


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

+ Recent posts