2017-10-20 15 views
0

ARM 임베디드 디바이스에서 RTOS를 사용하고 있습니다. 현재 나는 (내가 그 전 (별도의 스레드/작업)이 함수를 호출 할 때 신호가 완전히 잘못 될 수있는과를 기반으로 발견 이것이RTOS에서 vTaskDelay로 핀을 토글

GPIO_Write(PIN_1, LOW); 
vTaskDelay(msec_to_ticks(1)); 

GPIO_Write(PIN_1, HIGH); 
vTaskDelay(msec_to_ticks(1)); 
GPIO_Write(PIN_1, LOW); 
vTaskDelay(msec_to_ticks(3)); 

GPIO_Write(PIN_1, HIGH); 
if (option1){ 
    vTaskDelay(msec_to_ticks(3)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(1)); 
} else { 
    vTaskDelay(msec_to_ticks(1)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(3)); 
} 
GPIO_Write(PIN_1, HIGH); 
if (option2){ 
    vTaskDelay(msec_to_ticks(3)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(1)); 
} else { 
    vTaskDelay(msec_to_ticks(1)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(3)); 
} 
GPIO_Write(PIN_1, HIGH); 
vTaskDelay(msec_to_ticks(3)); 
GPIO_Write(PIN_1, LOW); 

같은 신호를 전환의 필요에 1-2ms 해요 때때로 꺼짐).

taskENTER_CRITICAL() 및 taskEXIT_CRITICAL을 사용하면 다소 정확한 신호를 확보 할 수 있는지 궁금합니다.

내가 가진 한 가지 아이디어는 우선 순위가 높은 인터럽트가 어딘가에 코드를 지연시키고 지연시킬 수 있다는 것입니다 (태스크에 최대 우선 순위를 설정 했음에도 불구하고). 다른 하나는 타이밍이 맞지만 GPIO_Write가 바로 발생하지 않는다는 것입니다.

코드가 중단되지 않도록하려면 어떻게해야합니까?

감사합니다.

답변

0

다음은 몇 가지 사항입니다.

1) vTaskDelay()에서 사용하는 타이머의 기간은 어떻게됩니까? 지연 기간의 오차는 최대 1 tick 일 수 있습니다. 예를 들어, 다음 틱이 발생하기 직전에 지연을 시작하면 지연은 한 틱까지는 너무 짧을 수 있습니다.

틱 기간이 1 밀리 초이면 1 밀리 초 지연을 정확하게 측정 할 수 없습니다. 타이머가 상대적으로 낮 으면 지연 시간이 최대 1 밀리 초 또는 100 %가 너무 짧을 수 있기 때문입니다. 테스트 기간은 1 밀리 초 이하의 오차로 1 밀리 초를 측정 할 수 있기 때문에 0.01 밀리 초 이하 여야합니다. vTaskDelay() 주기적 작업의 빈도를 조절하는 좋은 방법 하지 이유

2) FreeRTOS documentation 설명한다.

vTaskDelay()는 작업이 vTaskDelay()가 호출되는 시점에 상대의 차단을 해제하고자하는 시간을 지정합니다. 예를 들어 블록주기를 100 틱으로 지정하면 vTaskDelay()이 호출 된 후 작업이 100 틱을 차단 해제하게됩니다. vTaskDelay()은 이 아니므로 주기 작업의 빈도를 코드를 통해 취한 경로로 제어하는 ​​좋은 방법과 다른 작업 및 인터럽트 작업은 vTaskDelay()이 호출되는 빈도에 영향을 미치므로 시간 그 다음에 작업 이 실행됩니다. 고정 주파수 실행을 용이하게하기 위해 설계된 대체 API 함수에 대해서는 vTaskDelayUntil()을 참조하십시오. 은 호출 작업이 차단 해제해야하는 절대 시간 (상대적 시간이 아니라)을 지정합니다. vTaskDelay() 나에게 좋은 생각 같아에 taskENTER_CRITICALtaskEXIT_CRITICAL를 사용

3) 주위를 호출합니다. vTaskDelay()을 호출하는 이유는이 작업이 지연되는 동안 다른 작업에 실행할 기회를주는 것입니다. 따라서 taskENTER_CRITICAL으로 인터럽트를 비활성화하는 것이 비생산적인 것으로 보입니다. 지연 중에 다른 작업을 실행하지 않으려면 vTaskDelay()이 아닌 비 차단 지연 기능을 호출하십시오.그럼 당신의 비 차단 기능의 타이밍이 여전히 인터럽트에 의해 영향을받는다면 어쩌면 당신은 중요한 부분에 넣을 것을 고려할 수 있습니다. 이 제 전에 단일 틱 지연 삽입함으로써 해결 될 수

Tick: |   |   |   | 
     ________  __________ 
Signal:  |____|   |__________________ 
      <---------> 
     First transition 
    may occur anywhere here. 

:

+0

첫 번째 전환은 틱 경계와 비동기식이므로 다른 모든 전환은 즉시 지연됩니다. 즉, 지연이 1 틱 지연 (우선 순위가 높은 작업과 허용되는 인터럽트)을 따르는 경우 1 틱 지연을 정확하게 생성 할 수 있습니다. – Clifford

0

한가지 문제는 제 1 핀 세트는 RTOS 클록에 비동기로 발생되므로 클록주기 어딘가에 발생할 수있다 전이.

Tick: |   |   |   | 
     __   __________ 
Signal: |__________|   |__________________ 
Delay(1)-^   
     Transition occurs on the tick boundary 

우선 순위가 높은 작업과 인터럽트 전환 및 원인 지터 지연 될 수 있지만, 스케줄러 또는 비활성화 인터럽트를 잠글 수 있다면, 그 작업은 실행되지 않습니다, 그리고 응용 프로그램이 그 걸릴 수 있습니다 경우 이러한 작업이 할당되어 있습니다 부적절한 우선 순위. 마찬가지로 지터가 중요합니다. 그런 다음 다시 부적절하게 높은 우선 순위 또는 반대로 부적절한 행동과 우선 순위가 높은 작업에 대한 스케줄 가능성이있는 작업이 다시 발생합니다.

작업 우선 순위는 "중요성"에 관한 것이 아니며 스케줄 가능성 및 마감 시간에 관한 것입니다. 가이드로서, 하드 리얼 타임 데드 라인을 가지며 짧은 결정론적인 기간 동안 실행되는 태스크가 최우선 순위를 가져야합니다. 이 경우 작업은 대부분의 시간을 지체하게하는데, GPIO 스위치는 매우 적은 클록 사이클을 소요하므로이 작업에는 높은 우선 순위를 부여 할 수 있습니다.

결정적으로 작동하지 않는 작업은 시간이 중요한 작업에 영향을주지 않도록 우선 순위가 낮아야합니다. 이 조각이 다른 결정적이지 않은 작업을 수행하는 일부 작업의 일부인 경우 작업 분할이 다시 생각해야 할 수도 있습니다. 작업 분할은 항상 "작업"에 관한 것은 아니며 다시 스케줄 가능성에 관한 것이며 직관적으로 단일 기능 또는 동작을 하나 이상의 작업으로 분할해야 할 수도 있습니다. 예를 들어,이 신호는 우선 순위가 낮은 작업에서 직접 구현되지 않고 우선 순위가 낮은 일부 작업에 의해 트리거 된 이벤트를 대기하는 높은 우선 순위의 작업에 의해 생성 될 수 있습니다.