C-SPY 매크로를 사용하여 레지스터 값과 변수를 덤프
IAR Embedded Workbench는 다양한 마이크로 컨트롤러를 지원하는 통합 개발 환경(IDE)입니다. 내장 디버거인 C-SPY는 보다 효율적인 테스트 전략을 위해 사용할 수 있는 광범위한 매크로 시스템과 함께 제공됩니다.
C-SPY 매크로 언어 구성요소
C-SPY 매크로 언어에는 다음의 네 가지 구성 요소가 있습니다:
-
Macro functions: 매크로 함수를 호출할 때 함께 작업을 수행할 수 있는 문장과 변수가 포함된 매크로 코드 블록입니다. 매크로 함수는 완료 시 값을 반환할 수 있으며 호출 시 매크로 매개 변수를 무제한으로 수신할 수 있습니다.
-
Macro variables: 임베디드 프로그램 외부에서 정의 및 할당되는 변수입니다. 이러한 변수는 C-SPY 표현식 평가를 수행할 때 사용하거나 응용 프로그램의 변수 값을 할당할 때도 사용할 수 있습니다. 글로벌 매크로 변수는 매크로 본문 외부에서 정의할 수 있습니다. 이렇게 하면 전체 디버깅 세션에 걸쳐 이 파일이 존재하게 됩니다.
-
Macro strings: 리터럴 문자열을 포함할 수 있는 특수한 종류의 매크로 변수입니다. 대상 메모리에 대한 포인터 액세스 권한이 없기 때문에 일반 C 문자열과 다릅니다. 게다가, 그것은 NULL로 끝나지 않았습니다. C-SPY 내장 매크로 함수
__toString()
은 응용 프로그램의 NULL 종단 C 문자열(char *
orchar[]
)을 매크로 문자열로 변환하는 데 사용할 수 있습니다. -
Macro statements: 해당하는 C 문장과 유사한 방식으로 동작할 것으로 예상됩니다. 다음 C-SPY 매크로 문장이 허용됩니다:
- Expressions
- Conditional statements
- Loop statements
- Return statements
- Blocks
매크로 언어 구성 요소에 대한 자세한 내용은 IAR Embedded Workbench의 도움말 메뉴에서 확인할 수 있는 C-SPY Debugging Guide를 참조하십시오.
예제
아래의 예에서는 제품과 함께 참조 프로젝트로 제공되는 기본 디버깅을 활용할 것입니다. 이 프로젝트는 도움말 메뉴 → Information Center
→ Product explorer
→ Getting started using IAR Embedded Workbench
→ Open tutorial workspace
에서 액세스할 수 있습니다.
예제 1: C 변수 로깅
대상의 메모리에 있는 모든 C 변수는 C-SPY 매크로를 사용하여 덤프할 수 있습니다. 그러나 컴파일러의 최적화 수준에 따라 로컬 범위 또는 짧은 수명을 가진 변수를 저장할 때 레지스터를 사용할 수 있습니다. C-SPY 매크로에서 사용할 응용 프로그램의 변수를 선언할 때 volatile
한정자를 사용할 수 있습니다.
20행 근처에서 글로벌 변수 callCount
의 선언을 검색하고 volatile
한정자를 추가합니다:
static volatile int_fast8_t callCount;
다음으로, 35행 근처에서 로컬 변수 fib
의 선언을 검색하고 volatile
한정자도 추가합니다.
volatile uint32_t fib;
이제 DoForegroundProcess()
함수에서 PutFib(fib)
함수 호출을 마우스 오른쪽 버튼으로 클릭하고 Toggle Breakpoint (Log)
를 선택합니다. 코드 편집기 왼쪽의 같은 줄에 빨간색 원(L)이 표시되어야 합니다.
같은 라인에 한번 더 우 클릭을 한뒤 Edit Breakpoint...
를 선택.
C-Spy macro "__message" style
체크박스 활성화 =.
다음 메시지를 추가:
"callCount: ", callCount:%d, " --- fib: ", fib:%d, "(0x", fib:%x, ")"
Conditions를 다음 Expression:callCount
와 함께 Condition changed
로 바꾼 뒤
Make (F7)
로 프로젝트 빌드하고 Download and Debug (CTRL+D)
수행
Debug Toolbar에서 Go (F5)
클릭
Debug Log 창 이 업데이트 되는 것을 확인:
예제 2: C 변수를 파일로 덤프
File
→ New File (CTRL+N)
로 이동, 아래의 새 라인에 매크로 함수를 붙여넣는다.
__var myFileHandle;
// Called once when the debug session starts.
execUserSetup() {
myFileHandle = __openFile("$PROJ_DIR$\\dump.txt", "a");
if (myFileHandle) {
__fmessage myFileHandle, "Logging started...\n";
}
}
dumpValues() {
__var t1, t2;
t1 = callCount;
t2 = fib;
if (myFileHandle) {
__fmessage myFileHandle, "callCount: ", t1:%d, " --- fib: ", t2:%x, "\n";
} else {
__message "ERROR: file dump.txt could not be open.";
return -1;
}
return 0;
}
// Called once when the debug session ends.
execUserExit() {
if (myFileHandle) {
__closeFile(myFileHandle);
}
return 0;
}
File
→ Save as...
로 이동 한 뒤, 프로젝트 폴더에 dump.mac 로 저장
Project
→ Options…
→ Debugger
→ Setup
로 이동 dump.mac 매크로 파일을 찾는다.
이제 DoForegroundProcess()
함수에, PutFib(fib)
함수 호출에 우클릭하여 Toggle Breakpoint (Code)
를 선택. 코드 편집창의 왼쪽에 붉은 원이 나타난다.
View
→ Breakpoints
를 선택하여 Breakpoint window를 연다. 새 코드 중단점을 우클릭 한뒤 Edit…
를 선택
Action 필드에 dumpValues()
를 입력한다. 중단점에서 코드가 중지되면, dumpValues() 가 실행된다.
실행이 중단점에 도달하면, Debug Log 창에 변수가 덤프되었다는 메시지가 표시됩니다:
dump.txt 파일을 연뒤 내용을 확인합니다.
예제 3: 프로세서 레지스터 덤프
아래에 정의된 C-SPY 매크로 함수dumpRegs()
를 매크로 파일에 추가할 수 있습니다. 그런 다음 매크로가 호출되면 Debug Log 창에 CPU 레지스터가 포함된 메시지를 내보냅니다. CPU 레지스터는 해당 이름 앞에 #
를 붙여 참조할 수 있습니다.
dumpRegs() {
__message "R0, R1, R2, R3 =", #R0:%x, ",", #R1:%x, ",", #R2:%x, ",", #R3:%x;
__message "R4, R5, R6, R7 =", #R4:%x, ",", #R5:%x, ",", #R6:%x, ",", #R7:%x;
__message "R8, R9, R10, R11 =", #R8:%x, ",", #R9:%x, ",", #R10:%x, ",", #R11:%x;
__message "R12, R13, R14, R15 =", #R12:%x, ",", #R13:%x, ",", #R14:%x, ",", #R15:%x;
__message "CPSR =", #CPSR:%x;
}
C-SPY macros 수동 실행
디버그 세션 내에서 매크로 파일에서 C-SPY 매크로를 실행할 수 있습니다.
Quick Watch 창을 보기위해 View
→ Quick Watch
를 선택
dumpReg()
를 입력하거나, 버튼을 클릭하여 dumpReg()함수를 실행합니다. 메시지는 Debug Log창에 표시됩니다.
매크로를 실행하기 위해 View
→ Macro Quicklaunch
에서 Macro Quicklaunch창을 사용할 수 있습니다:
Debug Log창에서 레지스터 변수를 담은 메시지를 받을 수 있습니다:
결론
본 문서에서는 C 변수와 레지스터 내용을 덤프를 C-SPY 매크로를 사용하는 방법에 대한 몇 가지 예를 보여 드렸습니다. C-SPY 매크로를 사용하면 다양한 디버깅 및 검증 작업을 자동화할 수 있습니다. 복잡한 중단점과 함께 하드웨어 설정, 주변 장치 시뮬레이션, 런타임에 외부 데이터를 사용한 애플리케이션 피딩에 사용할 수 있습니다. 단, 몇 가지 가능성은 언급할 수 있습니다.