원자 적 액세스를 보장하려면 인터럽트를 비활성화해야합니다. 다른 프로세스가 읽고 읽는 동안 해당 변수에 액세스하고 잠재적으로 수정할 수 없기를 바랍니다. Introduction to Embedded Computing에서
: 원자 액세스에 대한
의 필요성
이 시나리오 상상 : X를, 16 비트 변수를 검토 전경 프로그램, 8 비트 uc에, 필요에 실행을 호출 그래서 높은 바이트를로드 한 다음 낮은 바이트를로드합니다 (또는 다른 방법으로는 은 중요하지 않음). 그런 다음 16 비트 값을 검사합니다. 이제 해당 16 비트 변수를 수정하는 연관된 ISR로 인터럽트를 상상해보십시오. 또한 변수의 값이 프로그램 실행의 주어진 시간 인 에서 0x1234가된다고 상상해보십시오. ,
- 전경 부하 상위 바이트 (0x12를)
- ISR가 발생합니다
- 전경 프로그램을보고 0xABCD
- 전경 부하 하위 바이트 (0XCD)에 X를 수정 : 여기에 일어날 수있는 아주 나쁜 것 입니다 0x12CD의 16 비트 값
문제는 데이터의 가정 불가분 편 우리 변수 X는, 실제로 변수를 액세스하기위한 CPU 명령어 나누어 질 수 있기 때문에, 액세스 과정에서 수정 된 것이다. 따라서 변수 X의로드가 손상되었습니다. 변수 읽기 순서가 중요하지 않음을 알 수 있습니다. 예제에서 의 순서가 바뀐 경우 변수는 0x35CD 대신 0x3534로 잘못 입력되어 으로 잘못 읽었을 것입니다. 어느 쪽이든 읽을 값은 이전 유효한 값 (0x1234)도 새 유효한 값 (0xABCD)도 아닙니다.
ISR 참조 데이터를 쓰는 것이 더 좋지 않습니다. 이번에는 전경 프로그램이 ISR의 이익을 위해 이전 값 0x1234를 작성한 다음 새 값 0xABCD를 작성해야한다고 가정합니다.이 경우 에서 VBT은 다음과 같다 :
- 전경 저장 새로운 상위 바이트 (확인 0xAB)
- ISR 발생은 0xAB34로 X를 판독
- 전경 저장 새로운 하위 바이트 (0XCD)
다시 한 번 코드 (이번 ISR)는 이전의 유효한 값도 0x1234도 아니고 0xABCD의 새 유효한 값도 아니지만 0xAB34의 잘못된 값을 봅니다.
spiTxRxByteCount &= ~0x0100;
은 C에서 단일 명령어처럼 보일 수 있지만 실제로 CPU에 대한 몇 가지 명령어입니다. GCC에서 컴파일 된 어셈블리 목록이 너무과 같습니다 인터럽트의 사이에 그 명령어의 제공과 데이터를 수정
57:atomic.c **** spiTxRxByteCount &= ~0x0100;
68 .loc 1 57 0
69 004d A1000000 movl _spiTxRxByteCount, %eax
69 00
70 0052 80E4FE andb $254, %ah
71 0055 A3000000 movl %eax, _spiTxRxByteCount
71 00
경우, 첫 번째 ISR은 잠재적으로 잘못된 값을 읽을 수 있습니다. 따라서 인터럽트를 실행하기 전에 인터럽트를 비활성화하고 변수 volatile
을 선언해야합니다.
RTOS가 있다면 뮤텍스를 사용하지 않으시겠습니까? –
@ [OS에서 이런 식으로 구현 된 세마포어 작업] (http://www.mpi-sws.org/~druschel/courses/os/lectures/proc4.pdf) –