2010-01-28 2 views
2

외부 인터럽트를 트리거하도록 정의 된 ISR이 있습니다. 외부 인터럽트는 항상 활성화되지는 않지만 특정 상황에서는 주 코드 내에서 인터럽트 내에서 ONCE라는 함수를 등록 할 수 있기를 원합니다. 함수는 다른 인터럽트가 있기 전에 다른 것으로 대체되거나 제거 될 수 있습니다.PIC32의 HiTech C에서 함수 포인터를 설정하는 인터럽트 안전한 방법

나는 PIC32에 대한 동기화를위한 기술에 대해 잘 모르겠지만, 나는 다음과 같이 왔어요 : 나는 문제가 있지만 그것에 대해 추론하는 데 문제가

volatile BOOL callbackInterrupted = FALSE; 
volatile BOOL callbackWritten = FALSE; 
void (*myCallback)() = NULL; 

void RegisterCallback(void (*callback)()) 
{ 
    do 
    { 
     callbackWritten = FALSE; 
     myCallback = callback; 
    } 
    while(callbackInterrupted); 

    callbackWritten = (callback != NULL); 
} 

void interrupt MyExternalInterrupt() @EXTERNAL_1_VCTR 
{ 
    // Do a bunch of other things here... 

    if(callbackWritten) 
    { 
     myCallback(); 
     myCallback = NULL; 
     callbackInterrupted = TRUE; 
     callbackWritten = FALSE; 
    } 
} 

합니다. 이것이 내가 원하는 바를 실제로 하는가? ISR이 반 설정 함수 포인터를 호출하거나 함수를 두 번 호출하는 것을 방지 할 수 있습니까? do ... while 루프가 불필요한가요? 더 좋은 방법이 있습니까?

추가 :이 인터럽트를 비활성화하는 것은 의문의 여지가 없습니다. 타이밍에 사용됩니다.

지침 flag = TRUE 생성 : fnc1 = &testfunc 생성

lui   s1,0x0 
ori   s1,s1,0x1 
addiu  at,s1,0 
or   t0,at,zero 

방법 :

lui   a2,0x9d00 
ori   a2,a2,0x50 
or   a1,a2,zero 
sw   a1,16376(gp) 

답변

1

bool을 설정한다고 가정 할 경우 (&의 디스 어셈블을 참조하십시오) - 함수 포인터를 설정하는 플래그를 사용하지만이 플래그는 ISR에서만 읽을 수 있습니다. 일반 코드, 간단한 세마포를 제공합니다. 함수 포인터를 쓰는 것이 원자 적 (다시, 역 어셈블로 검사)이라면, 플래그 대신에 포인터를 사용할 수 있습니다. (내 머리 위로 떨어져)이 같이

void (*myCallback)() = NULL;   

void RegisterCallback(void (*callback)())   
{   
    myCallback = callback; 
}   

void interrupt MyExternalInterrupt() @EXTERNAL_1_VCTR   
{   
    // Do a bunch of other things here...   

    if (myCallback!=NULL) 
     myCallback();   
    myCallback = NULL;   
} 

편집 플래그가 작동로 함수 포인터를 사용하여 분해 지침을보고 한 후. 사용법을 표시하는 수정 된 코드.

+0

두 작업에 대해 디스 어셈블 된 지침을 추가했습니다. 내가 이해하는 한, 그들은 원자가가 아닙니다. – detly

+0

PIC32 명령어 세트는 잘 모르겠지만 안전하다고 생각합니다. fnc = & testfunc는 인터럽트 할 수없는 명령어 인 sw a1, 16376 (gp)에서 발생합니다. 인터럽트 이후에 a1이 복원되기 때문에 그 전에 명령은 a1 레지스터를 설정하는 것 뿐이며 인터럽트 될 수 있습니다. 인터럽트는 sw 명령 전후에서만 발생할 수 있으므로 fnc가 항상 유효하다는 보장이 있습니다. – Jeff

+0

그래서 부울 플래그를 제거하고 단순히'myCallback! = NULL'을 체크 할 수 있습니다 ... 당신은 그 정보로 당신의 대답을 업데이트 할 수 있습니까? – detly

0

난 단지 함수 포인터를 사용하여 인터럽트에 null이 아닌에 대한 것을 확인 전화를 설정합니다을 null로. 포인터를 설정하면 표준 해결책은 인터럽트를 비활성화하는 것입니다.

+0

인터럽트를 비활성화하는 것은 의문의 여지가 있습니다.이 특정 인터럽트는 타이밍 펄스에 사용됩니다. 필자는 함수 포인터 자체를 플래그로 사용하는 것으로는 충분하지 않다고 생각합니다. – detly

1

ISR이 ISR에서 함수를 호출하는 이유는 무엇입니까? 주요 코드가 펄스 타이밍의 결과를 확인하는 곳이라면 어디에서 주 코드로 호출하면 좋을까요?

ISR의 화재로 코드가 실행되는 것이 중요하다고 답한 경우 인터럽트를 실행하기 전에 호출 할 함수를 설정하는 것이 중요합니다. 이 경우 유일한 옵션은 ISR 내의 다음 인터럽트를 호출하는 적절한 함수를 결정하거나 코드의 다른 곳에서 호출 할 적절한 함수를 결정하는 동안 인터럽트를 비활성화하는 것입니다. 타이밍이 중요한 경우이 ISR이 우선 순위가 더 높은 인터럽트로 인해 부딪 힐 수 없도록해야합니다.

+0

"그렇다면 인터럽트가 발생할 때마다 호출하기위한 함수를 설정할 기회가 있다는 것도 중요합니다.이 기능은 펄스 후 가능한 한 빨리 주변 장치를 작동 시키지만 다음 번에는 그다지 클 필요가 없습니다 (다음 클럭 사이클이 몇 초 밖에 걸리지 않으면 큰 문제가되지 않습니다). 그러나 ISR 내에서 다음 인터럽트를 호출 할 적절한 기능을 결정하는 것에 대한 의견은 매우 좋은 지적입니다. – detly

관련 문제