EP&C News UPDATED. 2017.5.29 월 18:18

상단여백
HOME 포커스 리포트 뉴스레터
애플리케이션이 독립 실행 안되는 이유는?
이나리 기자 | 승인 2017.01.02 16:29

제품을 개발하면서 코드에 대한 테스트를 하기 위해 디버깅 기능을 이용한다. 이러한 디버깅 환경에서는 정상적으로 동작하는 애플리케이션을 단독으로 전원을 인가해 실행하는 경우에 정상적으로 동작하지 않는 경우가 있다. 이러한 현상은 여러 요인에서 발생될 수 있다.

IAR EWARM(Embedded Workbench for ARM)에서 디버깅 프로브를 연결해 테스트하는 경우에는 정상적으로 동작하나 프로브를 제거하고 단독으로 애플리케이션을 실행할 때 동작이 되지 않는 경우에 대해 살펴보도록 하겠다.

응용프로그램이 C-SPY 디버거를 사용해 실행되는 경우와 단독으로 실행될 때를 생각해 보자.
C-SPY 디버거를 이용해서 응용프로그램을 디버깅하게되면 여러 SFR(Special Function Register) 들이 설정된다.

- 플래시로더의 소스 코드에서의 설정
- 플래시로더에서 사용되는 매크로 파일
- 애플리케이션에서 사용되는 매크로 파일

응용프로그램이 단독으로 실행될 때는 이러한 SFR들이 응용프로그램의 스타트업이나 초기화 코드에서 설정돼야 한다. 그럼 응용프로그램이 디버그 프로브없이 독립적으로 실행시 정상적으로 동작이 되지 않는 경우에 대해서 살펴보겠다.

처음으로는 플래시로더의 설정을 확인한다. 이에 프로젝트 옵션(Options) → 디버거(Debugger) → 다운로드(Download) 탭에서 사용 플래시 로더(Use flash loader) 항목을 확인한다.

플래시로더가 설정돼 있다면 이는 플래시로더 매크로 파일을 사용하고 있다는 의미다. 매크로 파일(.mac)이 사용되는 닷보드(.board) 그리고 닷플래시(.flash) 파일들을 확인하자.
매크로 파일을 열어 그 내용을 확인할 수 있다. 응용 프로그램의 스타트업 코드에서 이러한 설정이 필요한지를 검토해야 한다. 경우에 따라서는 플래시로더를 비활성화해 문제가 해결될 수 도 있다.

[그림1]

응용 프로그램에서 셋업 매크로 파일(Setup macro file: 옵션 → 디버거 → 셋업)을 사용하고 있는지를 확인하자. 그리고 매크로 파일을 열어 그 내용을 확인하자.
응용 프로그램의 스타트업 코드에서 이러한 설정이 필요한지를 확인하고 셋업 매크로 파일을 비활성화해 문제를 해결 할 수도 있다.

[그림2]

애플리케이션의 코드중에 printf()문을 사용했다면 프로젝트 설정에 따라 다르지만 디버깅 프로브를 연결하지 않은 경우에 멈추는 현상이 발생할 수 있다. Printf()문의 사용을 확인하는 방법은 프로젝트 옵션 → 제너너 옵션(General Options) → 라이브러리 컨피규레이션(Library Configuration) → 라이브러리 로우레벨 인터페이스(Library low-level interface) → 논(None)으로 설정한다. 별도로 __Write와 같은 저수준의 입출력 함수를 작성하지 않은 경우 빌드시 오류가 발생된다.

[그림3]

프로젝트 옵션 → 제너럴 옵션 → 라이브러리 컨피규레이션 → stdout/stderr → 비아 세미 호스팅(Via Semihosting)이 설정된 경우는 BKPT 명령어에서 애플리케이션이 동작을 멈출 수 있다. 세미호스팅 동작을 위해 SWI 인터럽트를 발생시킬 때 세미호스팅 시스템(semihosting-systems)에서 BKPT는 사용된다.

ARM 코어텍스 코어를 사용하고 있으며 printf() 문을 호출한 경우라면 프로젝트 옵션 → 제너널 옵션 → 라이브러리 컨피규레이션 → stdout/stderr → 비아 SWO로 설정한다.
그리고 빌드를 하면 SWO를 통한 동작으로 라이브러리 코드가 변경돼 애플리케이션이 멈추는 현상을 해결할 수 있다.

[그림4]

 세미호스팅 부문외에 또 다른 경우로 생각해 볼 수 있는 내용은 하드웨어 초기화 부분이다.
타깃 디바이스의 어떠한 하드웨어(PLL 등)는 초기화하기 위해 시간이 필요한 경우도 있다.

만약 애플리케이션에서 이러한 초기화 작업에서 대기하지 못했다면 문제가 발생할 것이다. 디버거상에서 실행되는 경우에는 애플리케이션이 main() 함수에서 멈추게 된다. 이러한 상황이 초기화 할 수 있는 시간을 주게되지만 단독적으로 장치를 실행할 때는 별도의 추가 지연 시간이 없게 된다.

이러한 문제로 발생됐다면 main() 함수에서 제일 먼저 긴 지연 시간을 발생시켜 확인할 수 있다. 이로서 문제가 해결되는 경우에는 디바이스 초기화에 대한 대기 시간 추가와 같이 코드를 재 작성해야 한다.

다음은 타임(time) 라이브러리를 사용하는 경우에도 프로브 연결시는 정상적으로 동작하나 독립적으로 실행하면 애플리케이션이 멈출 수 있다. 애플리케이션에서 시간 정보를 사용하는 경우 데이트(date)와 타임 라이브러리를 사용한다. 이러한 경우에 발생될 수 있는 사항에 대해 좀 더 자세히 알아보겠다.

◇ 디버깅을 하는 동안 시간 정보 관리

디버거를 사용할 수 있다면 타임 정보를 관리하기 위해 별도로 코드를 작성할 필요 없이 응용 프로그램에서 데이트/타임 라이브러리를 사용할 수 있다. 다음의 예제에서 하나는 clock() 함수를 사용하며 다른 하나는 time() 함수를 사용한다.
다음과 같은 방식으로 클락(clock)을 사용해 시스템 시작에 대한 경과 시간을 확인 할 수 있다.

[그림 5]
clock_t clk_time;
clk_time = clock ();
printf (“clock time:% dsec \ n”,     clk_time / CLOCKS_PER_SEC);

데이트와 타임 정보를 time() 함수를 통해 가져오고 이를 문자열로 표시할 수 있다.

[그림6]
time_t now;
struct tm * ts;
char buf [80];
 
now = time (NULL);
ts = localtime (& now);
strftime (buf, sizeof (buf), “% a% Y-%     m-% d% H:% M:% S% Z”, ts);
printf (“% s \ n”, buf);

디버거 장비없이 시간 정보 관리

디버거 장비없이 시간 정보를 다루기 위해서는 응용프로그램에서 데이트와 타임에 대한 저수준의 코드를 작성해야 한다. 만약 RTOS를 사용하는 경우라면 유사한 기능이 제공될 수도 있어 이 부분을 활용할 수도 있다.
다음은 시스틱 타이머(SysTick timer)를 포함하는 ARM 코어텍스-M 디바이스용 예제다. 타이머는 데이트와 타임 함수를 쉽게 구현할 수 있다. 이 예제에서는 시스텍이 1msec마다 발생하고 있다.

[그림8]
#define CLOCKS_PER_SEC (1000)
clock_t clk_count = 0;
time_t time_dat;

타임과 클락을 위해 두 개의 변수를 정의했고 CLOCKS_PER_SEC을 1초에 발생되는 틱(tick) 수로 정의했다.

시스틱을 위해 인터럽트 핸들러를 작성했고 Clk_count 변수는 오버플로우를 방지하기 위해 64비트로 선언해 주길 바란다. 인터럽트가 발생되면 clk_count가 증가되고 time_dat는 1초가 경과 될 때 증가한다.

[그림9]
void SysTick_Handler (void) {
   clk_count ++;
   if ((clk_count% 1000) == 0) {
      time_dat ++;
   }
}

두 개의 함수에 해당 변수를 사용해 코드를 작성한다.

[그림10]
clock_t clock (void) {
   return (clk_count);
}

time_t __time32 (time_t * p) {
return time_dat;
}

clock() 함수는 경과 시간을 가져오기 때문에 0(zero)으로 초기화되며 Time_dat 변수는 현재 시각으로 설정돼야 한다. 이러한 현재 시각 정보를 변환 함수를 통해 설정할 수 있다. 다음은 시각 변환을 위해 mktime() 함수를 사용한 예제다.

[그림11]  구조체 설정 : Fri Jul 10 09:46:10 2015
struct tm orig;
 orig.tm_sec = 10;
 orig.tm_min = 46;
 orig.tm_hour = 9;
 orig.tm_mday = 10;
 orig.tm_mon = 6;
 orig.tm_year = 115;
 orig.tm_wday = 5;
 orig.tm_yday = 19;
 orig.tm_isdst = -1;
 time_dat = mktime (& org);

결과적으로 시스틱 핸들러의 모든 호출은 변수를 업데이트한다. 이러한 저수준의 코드를 작성하여 클락과 타임 함수를 애플리케이션에서 사용할 수 있다.

Time.h에 구현돼 있는 표준 C 라이브러리 데이트와 타임 기능은 IAR 임베디드 워크벤치(Embedded Workbench)에서 사용할 수 있으며 디버거에 의해 제공되는 정보를 이용함으로써 저수준의 코드를 작성하지 않아도 이러한 기능들을 이용할 수 있다. 디버거를 사용하지 않고 이러한 데이트와 타임 기능을 사용하기 위해서는 앞서 설명한 것처럼 저수준의 코드를 작성해야 한다.

◇ 맺음말

C-SPY 디버거 프로그램에서 애플리케이션을 실행하면 앞서 살펴 본 내용처럼 디버거에서 지원하는 기능이 동작한다. 그러나 디버거를 사용하지 않고 독립적으로 보드를 실행시키는 경우에는 정상적인 동작이 이뤄지지 못하는 경우가 있다. 이러한 경우들을 미리 인지하고 있으면 문제를 해결하기 위해 많은 시간이 소요되지 않을 것이다.

<자료제공 : IAR(www.iar.com)>

이나리 기자  narilee@epnc.co.kr

<저작권자 © EP&C News, 무단 전재 및 재배포 금지>

이나리 기자의 다른기사 보기
icon인기기사
여백
여백
여백
여백
여백
여백
여백
여백
icon
여백
여백
여백
신제품
여백
여백
여백
여백
Back to Top