강좌 & 팁
안녕하세요.
이번 시간은 익셉션 프로그래밍에 대해서 설명 하겠습니다.
1. 인터럽트 사용하기
인터럽트는 거의 모든 임베디드 어플리케이션에서 사용되고 있습니다.
Cortex-M3 프로세서에는 인터럽트 컨트롤러 NVIC가 우선순위 확인 및 레지스터의 스태킹/언스태킹을 포함한 많은 프로세싱
태스크를 처리합니다. 하지만, 인터럽트가 사용될 때 많은 테스크들이 준비되어 있어야 합니다.
- 스택 셋업
- 벡터 테이블 셋업
- 인터럽트 우선순위 셋업
- 인터럽트 활성화
2. 스텍 셋업
간단한 어플리케이션 개발을 위해서 전체 프로그램에 대해 MSP를 사용할 수 있습니다. 방버에서는 상당히 큰 메모리를 예약해 두어야 하며, 스택의 상위애 MSP를 설정 해야 합니다. 요구되는 스택 크기를 결정할 때, 소프트웨어에 의해 사용될 수 있는 스택 레벨을 확인하기 전, 중첩된 인터럽트가 마나 많이 발생할 수 있는지를 먼저 확인해야 합니다.
중첩된 인터럽트의 각 레벨을 위해서는 최소한 8워드의 스택을 필요로 합니다.
인터럽트 핸들러 안에서의 프로세싱 또 한 여분의 스택 공간을 필요로 합니다.
Cortex-M3에서의 스택 동작은 Full Descending이기 때문에 SRAM의 빈 공간이 나누어지지 않도록 하기 위해 적 메모리의 끝에 초기값을 넣어두는 것이 일반적입니다.
사용자 코드와 커널 코드를 위한 분리된 스택을 사용하는 어플리케이션을 위해 메인 스택은 중첩된 인터럽트 핸들러와 커널 코드에 의해 사용되는 스택 메모리를 위해 충분한 모리를 가지고 있어야 합니다. 프로세스 스택은 사용자 어플리케이션 코드에 한
레벨의 스태킹 공간을 더한 값만큼 충분한 메모리를 가지고 있어야 합니다. 이것은 사용자 레드에서 인터럽트 핸들러의 첫 번째 레벨까지의 스태킹이 프로세스 스택을 사용하기 때문입니다.
[간단한 메모리 사용]
3. 벡터 테이블 셋업
고정된 인터럽트 핸들러를 가진 간단한 어플리케이션에서는 벡터 테이블이 ROM 안에 코딩될 수 있습니다. 이 경우, 런타입에서
벡터 테이블을 셋업할 필요가 없습니다 . 하지만, 많은 어플리케이션에서는 다른 상황을 위해 인터럽트 핸들러를 변경해야 할 수도 있습니다. 그리고 쓰기 가능한 메모리에 벡터 테이블을 재배치할 것입니다.
벡터 테이블을 재배치하기 전에 기존의 벡터 테이블 내용을 새로운 벡터 테이블 위치에 복사해야 할 수도 있습니다.
이것은 결함 핸들러, NMI, 시스템 호출 등을 위한 벡터 테이블을 포함합니다. 그렇지 않으면, 벡터 테이블 재배치 후에 이러한
익셉션들이 발생하는 경우 유효하지 않은 벡터 주소가 프로세서에 의해 패치될 것입니다.
필요한 벡터 테이블 아이템이 셋업되고, 벡터 테이블이 재배치된 후, 새로운 벡터들을 벡터 테이블에 추가할 수 있습니다.
4. 인터럽트 우선순위 설정
디폴트 리셋 후, 프로그래밍 가능한 우선순위를 가진 모든 익셉션은 우선순위 레벨 0이 됩니다.
하드결함 익셉션과 NMI를 위해서는 우선순위 레벨이 각각 -1과 -2가 됩니다. 우선순위-레벨 레지스터를 프로그래밍하기 위해서, 레지스터들이 바이트 주소 단위로 되어 있다는 장점이 있는데, 이는 코딩을 더 쉽게 만들어줍니다.
5. 소프트웨어 인터럽트
인터럽트를 트리거할 수 있는 방법으로는 다양한 것들이 있습니다.
- 외부 인터럽트 입력
- NVIC 안에 있는 인터럽트 펜딩 레지스터 설정하기
- NVIC 안에 있는 소프트웨어 트리거 인터럽트 레지스터를 통해서
대부분의 경우, 일부 인터럽트들은 사용되지 않고 소프트웨어 인터럽트로 사용될 수 있습니다.
소프트웨어 인터럽트는 SVC와 유사하게 동작할 수 있으며, 시스템 서비스에 접근 가능합니다. 하지만, 디폴트로 사용자
프로그램들은 NVIC에 접근될 수 없습니다.
단 NVIC 설정 제어 레지스터 안에 있는 USERSETMPEND 비트가 1로 설정되어 있는 경우에만 NVIC의 STIR에 접근 가능합니다.
SVC와는 달리, 소프트웨어 인터럽트는 정확하지 않습니다. 다시 말하면, 인터럽트 선점이 반드시 즉시 발생하는 것은 아닙니다.
심지어 인터럽트 마스크 레지스터나 다른 인터럽트 서비스 루틴에 의해 블록되어 있지 않는 경우도 마찬가지입니다. 결과적으로 NVIC STIR에 값을 쓴 바로 다음에 오는 명령어가 소프트웨어 인터럽드의 결과에 의존적인 경우, 명령어가 실행된 다음에 소프트웨어 인터럽트가 발생할 수도 있기 때문에, 그 동작이 실패할 수 있습니다.