2016-08-05 2 views
2

메인 루프와 1 밀리 초 인터럽트가있는 마이크로 컨트롤러가 있다고 가정합니다. (메인 루프의 실행을 방해하는 것이 무엇인지 모르는 경우 ..... 1 밀리 초마다 발생하기 때문에 1 밀리 초 인터럽트). 않는 나는 Status 변수를 갱신 메인 루프의 코드 섹션을부분 휘발성 변수?

volatile status_t Status; 

지금 :

은 내가 메인 루프와 밀리 초 인터럽트 사이에서 통신하는 데 사용하는 변수가 거기에 변환의 톤 :

cli(); // This temporarily turns off interrupts, so we don't 
      // modify the variable unsafely 
Status.UpdateStuff(); 
Status.UpdateOtherStuff(); 
//etc. 

sei(); // Turn interrupts back on 

문제는 이러한 기능의 각 ...... 컴파일러가 로컬 메모리에 상태의 값을 캐시 할 수 Status를 다시 작성 Status 호출한다는 것입니다.

이 내가 할 희망 일을 할 것인가, 아니면 얻을 수있는 더 좋은 방법이있다 :

cli(); 
status_t* localStatus = (status_t*)&Status; 
localStatus->UpdateStuff(); 
localStatus->UpdateOtherStuff(); 
//etc. 

Status = *localStatus; 
sei(); 

여기 진짜 문제는 이것이다 :

이 문제에

한 가지 가능한 해결책은 이것이다 최적화 프로그램이 변수를 캐시하는 대신 변수를 새로 고치는 문제가 있습니까?

+0

두 번째 발췌 문장에서는 '& Status'를 사용한다고 가정합니다. BTW, 나는 훨씬 더 좋은 대안이 있다고 생각하지 않는다. –

+0

타이머가 대기열에 작업을 삽입하고 주 스레드가 대기열을 읽고 작업을 처리하도록하십시오. 대기열 작업에만 뮤텍스가 필요합니다. –

+0

@MatteoItalia 그래, 그게 무슨 뜻인지 ... – DarthRubik

답변

3

두 번째 버전은 마이크로 컨트롤러에 여러 번 쓸 수 있습니다. 컴파일러는 메서드 호출간에 값을 캐시 할 수 있다는 것을 모르기 때문에 (아마도 메서드가 인라인 인 경우에만이를 확인할 수 있기 때문입니다). 따라서 로컬 포인터가 아닌 명시적인 로컬 복사본을 만드는 것이 좋습니다.

cli(); 
status_t localStatus = Status; 
localStatus.UpdateStuff(); 
localStatus.UpdateOtherStuff(); 
... 
Status = localStatus; 
sei(); 
+0

이 방법을 사용하면 새로운 버전의 상태를 공유 위치로 이동시키는 코드만으로 인터럽트를 사용하지 않고 실행해야하는 코드의 범위를 줄일 수 있습니다. – nate

0

인터럽트가 비활성화 된 상태에서 프로세서가 실행되는 시간을 최소화하는 예입니다. nextStatus에 다른 부작용이없는 경우에만 작동합니다. 만약 그렇다면 상태가 성공적으로 커밋되면이를 기록하고 실행해야합니다.

cli(); 
do { 
    auto lastStatus = Status; 
    sei(); 

    auto nextStatus = lastStatus; 
    nextStatus.UpdateStuff(); 
    nextStatus.UpdateOtherStuff(); 
    ... 

    cli(); 
} while (lastStatus != Status); 
Status = nextStatus; 
sei();