반응형

 

 

Periodic태스크에서 주기적으로 소프트웨어적으로 인터럽트를 발생시킨다.

 

인터럽트가 발생하면 인터럽트를 위한 서비스 루틴인 vExampleInterruptHandler함수가 호출되어 세마포어를 놓아주고 컨택스트 스위치를 한다.

 

바로 Handler 태스크에서 세마포어를 획득하고는 필요한 처리작업을 하게 된다. 이후 다시 세마포어를 기다리는 블록상태에 빠지고

 

다시 Periodic태스크에서 인터럽트 발생 후 해야 할 작업을 이어서 계속한다.

 

지난번 예제와 차이점이 있다면 한번에 세마포어를 세 개씩 주지만 이벤트를 놓치지 않고 잘 처리해주는 것이다.

Handler에서 작업하던 중 인터럽트가 발생되면 다시 Handler를 처리하려 하고 하다 보니 결국 마지막에 발생한 인터럽트 처리부터 하기 때문에 count값이 마지막에 증가한 값으로 출력되는 것으로 보인다.

 

  1. /* FreeRTOS.org includes. */  
  2. #include "FreeRTOS_AVR.h"  
  3. //#include "task.h"  
  4. //#include "semphr.h"  
  5. //#include "portasm.h"  
  6.     
  7. /* Demo includes. */  
  8. #include "basic_io_avr.h"  
  9.     
  10. /* Compiler includes. */  
  11. //#include <dos.h>  
  12.     
  13. static void vHandlerTask( void *pvParameters );  
  14. static void vPeriodicTask( void *pvParameters );  
  15.     
  16. //인터럽트를 위한 서비스 루틴  
  17. static void vExampleInterruptHandler( void );  
  18. int count=0;  
  19.     
  20. /*-----------------------------------------------------------*/  
  21.     
  22. //태스크들에서 세마포어에 접근하기 위해 전역으로 변수 선언  
  23. SemaphoreHandle_t xCountingSemaphore;  
  24.     
  25. // pin to generate interrupts  
  26. #if defined(CORE_TEENSY)  
  27. const uint8_t interruptPin = 0;  
  28. #elfif defined(__AVR_ATmega32U4__)  
  29. const uint8_t interruptPin = 3;  
  30. #else  // interruptPin  
  31. const uint8_t interruptPin = 2;  
  32. #endif  // interruptPin  
  33.     
  34. void setup( void )  
  35. {  
  36.     Serial.begin(9600);  
  37.     
  38.   //최대 10개까지 사용가능한 세마포어를 생성한다.초기값은 0이다.  
  39.   xCountingSemaphore = xSemaphoreCreateCounting( 10, 0 );  
  40.     
  41.    //인터럽트핀을 출력으로 설정  
  42.    pinMode(interruptPin, OUTPUT);  
  43.        
  44.    //인터럽트 서비스 루틴을 지정한다. LOW->HIGH  전압이 변화시 인터럽트 발생    
  45.    attachInterrupt(0, vExampleInterruptHandler, RISING);  
  46.     
  47.   //세마포어가 성공적으로 생성되었다면  
  48.   if( xCountingSemaphore != NULL )  
  49.   {  
  50.     //인터럽트 발생후 바로 실행되기 위해서 우선순위가 높도록해서 Handler 태스크 생성  
  51.     xTaskCreate( vHandlerTask, "Handler", 200, NULL, 3, NULL );  
  52.     
  53.      //주기적으로 소프트웨어 인터럽트를 발생시키는 Periodic태스크를 생성한다.    
  54.      //우선순위 낮기때문에 Handler태스크가 블록될때에만 실행될 것이다.  
  55.     xTaskCreate( vPeriodicTask, "Periodic", 200, NULL, 1, NULL );  
  56.     
  57.     //스케줄러를 시작한다.  
  58.     vTaskStartScheduler();  
  59.   }  
  60.     
  61.   //여기에 도달하면 아마도 메모리가 부족한 상태이다.  
  62.       
  63.   for( ;; );  
  64. //  return 0;  
  65. }  
  66. /*-----------------------------------------------------------*/  
  67.     
  68. static void vHandlerTask( void *pvParameters )  
  69. {  
  70.   /* As per most tasks, this task is implemented within an infinite loop. */  
  71.   for( ;; )  
  72.   {  
  73.       //이벤트를 기다리기 위해서 세마포어를 이용한다.    
  74.      //세마포어를 얻을떄 까지 대기하게 된다.    
  75.      //첫번째 파라메터는 세마포어 핸들러    
  76.      //두번째 파라메터는 세마포어를 획득할때 까지 기다리는 최대 틱수    
  77.      //portMAX_DELAY 설정하면 무한히 기다리게 된다.    
  78.     xSemaphoreTake( xCountingSemaphore, portMAX_DELAY );  
  79.         
  80.     //세마포어를 획득했으므로 이제 이벤트를 처리한다  
  81.     vPrintStringAndNumber( "Handler task - Processing event.\r\n", count );  
  82.   }  
  83. }  
  84. /*-----------------------------------------------------------*/  
  85.     
  86. static void vPeriodicTask( void *pvParameters )  
  87. {  
  88.   for( ;; )  
  89.   {  
  90.     //주기적으로 소프트웨어 인터럽트를 발생시키는 태스크이다.  
  91.      
  92.     vTaskDelay( 500 / portTICK_PERIOD_MS );  
  93.     
  94.     //인터업트 발생전 실행되는 코드  
  95.     vPrintString( "Perodic task - About to generate an interrupt.\r\n" );  
  96.     
  97.     //인터럽트 발생  
  98.     digitalWrite(interruptPin, LOW);  
  99.     digitalWrite(interruptPin, HIGH);  
  100.     
  101.     //인터럽트 발생하여 서비스루틴 처리  실행되는 코드  
  102.     vPrintString( "Periodic task - Interrupt generated.\r\n\r\n\r\n" );  
  103.   }  
  104. }  
  105. /*-----------------------------------------------------------*/  
  106.     
  107. static void vExampleInterruptHandler( void )  
  108. {  
  109.   static portBASE_TYPE xHigherPriorityTaskWoken;  
  110.     
  111.   xHigherPriorityTaskWoken = pdFALSE;  
  112.     
  113.   //세마포어를 세번 연달아 놓아준다   정상적으로 이벤트를 처리한다.  
  114.   //중복적으로 인터럽트가 발생할 경우 어느 것부터 처리하는지 알아보려고 count 증가시킴.  
  115.   count++;  
  116.   xSemaphoreGiveFromISR( xCountingSemaphore, (BaseType_t*)&xHigherPriorityTaskWoken );  
  117.   count++;  
  118.   xSemaphoreGiveFromISR( xCountingSemaphore, (BaseType_t*)&xHigherPriorityTaskWoken );  
  119.   count++;  
  120.   xSemaphoreGiveFromISR( xCountingSemaphore, (BaseType_t*)&xHigherPriorityTaskWoken );  
  121.     
  122.   if( xHigherPriorityTaskWoken == pdTRUE )  
  123.   {  
  124.     //세마포어를 놓아준 걸로 인해서 우선순위 높은 태스크가 블록상태에서 빠져나왔다.    
  125.     //컨텍스트 스위치를 통해 해당 태스크가 바로 실행될  있도록한다.    
  126.     vPortYield();  
  127.   }  
  128. }  
  129. //---------------------------------------------------------------  
  130. void loop() {}  


반응형

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

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


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

+ Recent posts