CAFE

DSP 실무 Q&A

DSP_TMS320C 프로그래밍 언어

작성자서상우|작성시간00.03.17|조회수989 목록 댓글 0
DSP_TMS320C 1. 프로그래밍 언어의 선택 방법 l.1 어셈블리어만 사용하는 방법 l.2 C언어를 사용하는 방법(100% C로만은 거의 불가능) l.3 어셈블리와 C언어를 혼용한 방법 2. 어셈블리와 C언어 프로그램의 차이 2.1. 실행파일의 생성 어셈블리 언어 프로그래밍과 C언어 프로그래밍에서는 거시적으로 볼 때 모두 작성 -> 번역 -> 링크 -> 실행의 과정을 거치지만, 그 구체적인 내용은 서로 다르며, 특히 C언어를 사용하는 프로그래밍의 경우에는 그 절차가 다소 복잡 하므로 잘 알아둘 필요가 있다. 2.2. 프로그램의 실행 일반적으로 IBM PC와 같은 범용 컴퓨터에서는 번역과 링크 과정을 통하여 만들어진 실행파일을 MS-DOS와 같은 운영체제가 메모리에 로드하고 변수를 초기화하는 등의 준비과정을 거친 후에 실행시켜 준다. (MS-DOS에서는 COMMAND.COM 파일이 이러한 기능을 수행한다.) 그러나, TI의 DSP와 같은 소규모의 마이크로프로세서 키트에는 대부분 운영체제가 없으며, 따라서 이러한 운영체제의 역할을 수행할 방법이 없다. 마이크로프로세서나 DSP는 모두 리셋후에 특정한 번지로부터 프로그램이 수행되거나 지정된 리셋 벡터에서 프로그램의 시작번지를 인출하여 실행을 개시하도록 되어 있다. 물론 TMS320C3x/4x의 경우에는 다소 특이하게 마이크로컴퓨터 모드에서 프로그램을 Memory Bootloading하는 기능이 있기는 하지만, 이것도 역시 외부에서 단순히 프로그램을 부팅하는 것일 뿐 운영체제와 같은 기능을 수행하지는 못한다. 어셈블리 언어로 프로그램을 작성하여 번역하고 링크하면 프로그램의 시작번지를 마이크로프로세서나 DSP가 리셋 후에 처음 실행을 개시하는 번지와 일치하도록 지정할 수 있기 때문에 별다른 조치없이도 쉽게 사용자 프로그램을 실행시킬 수가 있다. 예를 들어 텍스트 섹션의 시작부분에 라벨을 붙이고, 링커에서 이를 실행을 위한 엔트리 포인트로 지정하여 주기만 하면 사용자 프로그램의 부팅이 완료된 후에 이곳으로부터 실행이 개시되로록 실행파일이 만들어진다. 그러나, C언어로 프로그램을 작성하는 경우에는 그렇지 못하다. C언어는 마이크로프로세서의 종류에 관계없이 이식성과 범용성이 우수한 언어이지만, 오히려 그러하기 때문에 모든 종류의 마이크로프로세서에서 서로 다른 프로그램의 실행개시 방법을 만족하도록 할 수가 없기 때문이다. C언어 프로그램은1개의 main() 함수와 기타 많은 함수들로 구성되는데 이들을 번역하면 main() 함수가 바로 실행될 수 있는 환경으로 실행파일이 만들어지지 못한다. 그래서 대분분의 마이크로프로세서용 C언어에서는 자신에 적합한 실행개시 수단을 제공하는데 이들을 cstartup코드라고 한다. 즉, 마이크로프로세서가 리셋되고 나면 이cstartup코드를 수행하도록 실행파일이 만들어 진다. cstartup코드는 먼저 C프로그램의 초기화 루틴을 수행하여 모든 글로벌 변수나 시스템 스택 등을 초기화한 후에, main()함수를 호출하여 실행하며, main() 함수의 실행이 종료되면 다시 cstartup코드로 제어가 넘겨져서 exit() 함수를 수행함으로써 프로그램이 완전히 종료된다. TI DSP 전용 C컴파일러의 경우에는 cstartup코드가 제공된 라이브러리 속에 포함되어 있다.(boot.obj, exit.obj) 따라서, 사용자는 링크시에 이 라이브러리 파일을 링크시키고, 리셋 후에 사용자 프로그램이 부팅되고 나면 프로그램의 서두에서 곧바로 제어가 이 cstartup 루틴으로 넘어가도록 점프시켜주기만 하면 된다. 이 루틴의 시작점 라벨은 _c_int00으로 되어 있다. 이렇게 프로그램의 서두에서 _c_int00 라벨로 점프시키는 것은C소스 프로그램내의 main() 함수 앞에서 인라인(in-line) 어셈블 명령을 이용하여 처리해도 되고, 이 점프명령을 별도의 소스 파일로 작성하여 번역한 것을 main() 함수의 오브젝트 파일과 링크시켜도 무방하다. (링커 옵션에서 '-e symbol' 옵션을 사용, Default는 _c_int00이다) 3. C언어와 어셈블리 언어의 혼용 C언어는 다른 고급언어에 비하여 하드웨어와 관련된 미세한 처리가 용이한 언어로 평가 받고 있으나 어셈블리 언어에 비하면 매우 불편할 때가 많다. 그래서 많은 사용자들은 C언어를 주로 사용하면서 필요할 경우에는 어셈블리 언어를 보조적으로 사용하고 있다. C언어와 어셈블리 언어를 혼용하는 방법은 여러 가지가 있는데, 그 중에서 가장 보편적이고 손쉬운 방법은 인라인 어셈블(in-line assemble)을 사용하는 방법이다. 이것은 다음과 같이 C소스 프로그램의 내부에서 직접 어셈블리 명령을 사용하는 방법으로서 어셈블리 루틴이 짧은 경우에 유용하다. asm("assembly instruction"); 또 다른 방법으로는 기본적으로 프로그램을 C언어로 작성하고 이중에서 실행기간이 많이 소요되는 루틴이나 하드웨어의 의존도가 높은 루틴만을 어셈블리 언어로 작성하여 이를 C에서 호출하도록 링크하는 방법이다. 아마도 이것이 가장 정석적이고 바람직하며 일반적으로 권장할만한 방법이라고 할 것이다. 그밖에 모든 프로그램을 C언어로 작성하고 이를 번역할 때 어셈블리 소스의 중간 파일을 생성하도록 하여 이를 프로그래머가 효율적으로 수정하는 방법이 있다. 그러나, 이 어셈블리 소스의 중간파일을 분석하는 것은 상당한 수준의 프로그래머가 아니면 어려운 일이며, 또한 TMS320C3x/4x용 C컴파일러의 경우에는 이 중간 파일이 놀라울 만큼 효율적으로 되어 있어서 프로그래머가 이를 수정할 여지가 별로 없는 경우가 대부분이므로 이 방법은 그다지 권할만한 것이 되지 못한다. 4. 메모리 섹션의 사용 어셈블리 프로그램을 번역하면 .text, .data, .bss이외에는 사용자가 소스 프로그램에서 지정한 섹션들만 생성되는데 비하여, C언어 프로그램에서는 소스 프로그램에서 이들 섹션들을 지정할 필요가 없으며 모든 섹션은 컴파일러가 자동적으로 생성한다.(C프로그램은 .data 섹션은 사용하지 않는다.) C프로그램에서 섹션을 임의로 사용하는 방법을 아래에 나타내었다. --------------------------------------------------------------------- #define sect(a) asm(" .sect "#a) sect("pp"); /*Creates .sect "pp" in asm code */ void func() { } --------------------------------------------------------------------- Asm(" .sect "pp" ;사용자가 만든 "pp"영역으로 섹션변경"); /* TODO a user program is go here */ --------------------------------------------------------------------- #pragma CODE_SECTION(symbol, "section name"); #pragma DATA_SECTION(symbol, "section name"); --------------------------------------------------------------------- C컴파일러가 만드는 섹션을 요약하면 <표1>과 같다. 어셈블러에서는 대부분 .data 섹션을 사용하지만 C컴파일러에서는 기본적으로 .data 섹션을 사용하지 않는데 유의하라. 사용자는 링크를 수행할 때 링크 커맨드 파일에서 SECTIONS 지시어를 사용하여 이 섹션들을 메모리의 어느 영역에 할당할지를 지정해야 한다. 일반적으로 initialized section은 ROM 또는 RAM에 할당할 수 있으며, uninitialized section은 반드시 RAM에 할당해야 한다. (어셈블러에서 사용하는 .data 섹션은 ROM 또는 RAM에 할당할 수 있다.) 표1 C컴파일러에 의하여 생성되는 섹션 ------------------------------------------------------------------------- 섹 션 형 식 내 용 ------------------------------------------------------------------------- .text initialized 실행 코드 또는 부동소수점 상수를 포함하는 초기화 섹션이다. .cinit Initialized 초기화된 글로벌 변수 또는 static variable을 포함하는 초기화 섹션이다. .const initialized 부동소수점 상수 또는 switch table을 포함하는 초기화 섹션이다. .bss uninitialized 글로벌 변수 또는 static variable을 포함하는 섹션으로서, 프로그램의 startup루틴이 실행될 때 데이터를 .cinit 섹션으로부터 .bss 섹션으로 복사한다. .sysmem uninitialized malloc, calloc, realloc 등의 메모리 함수에 의하여 사용되는 데이터를 포함하는 섹션이다. .stack Uninitialized 시스템 스택으로 사용되는 섹션이다. ------------------------------------------------------------------------- 5. 초기화 모델(ROM 모델과 RAM 모델) C컴파일러는 소스 프로그램을 컴파일할 때 글로벌 변수들을 자동으로 초기화하기위한 데이터 테이블을 생성하여 이를 오브젝트 파일의 .cinit 섹션에 저장하여 두며, 이는 나중에 초기화될 때 .bss 섹션 으로 복사된다. 이 초기화 테이블을 사용하는 방법에 따라 실행파일을 RAM 모델과 ROM 모델로 나누어지는데, 이는 링커에서 각각 -cr 옵션과 -c옵션(default)으로 지정한다. RAM 모델의 실행파일은 링커에서 -cr 옵션으로 지정하여 생성되며, 글로벌 변수들을 프로그램 로드 시에(at load time) 초기화한다. 이 모델에서는 로더가 실행 프로그램을 메모리에 로드할 때 초기화 데이터 테이블을 남기지 않으며 이로부터 초기화가 완료된 .bss 섹션만 남는다. 따라서, RAM 모델을 사용하면 메모리 용량을 적게 사용하는 장점은 있으나, 이 모델의 실행파일은 로더가 이러한 초기화 기능을 가지고 있어야만 정상적인 처리가 수행되므로 똑똑한 로더가 필요하다. 이 로더는 TI사의 전용 C컴파일러에 포함되어있지 않다. (C4x/3x계열의 경우 포함되어 있지 않으나C6x에는 별도로 포함되었다) 이를 사용하기 위해서는 TI사의 전용 디버거(Emulator, Simulator)나 load6x(C6x계열에만 해당)를 사용해야한다. ROM 모델의 실행파일은 링커에서 -c옵션으로 지정하여 생성되며, 글로벌 변수들을 프로그램 실행 시에(at runtime) 초기화한다. 이 모델에서는 로더가 실행 프로그램을 메모리에 로드할 때 .cinit 섹션의 초기화 데이터 테이블을 만들어 두며, 나중에 프로그램을 실행할 때 _c_init00에서 시작되는 부트 루틴 (boot routine) boot.obj에 의하여 이 데이터 테이블이 .bss 섹션으로 복사되어 초기화가 수행된다. 따라서, ROM 모델을 사용하면 메모리 용량을 많이 차지하는 단점은 있으나, 이 모델의 실행파일은 프로그램 실행 시에 실행파일 내에 포함되어 있는 부트 루틴이 데이터를 초기화하여 주므로 쉽게 사용할 수 있다. 6. 기타 프로그래밍 TIP ◆ 프로그램이 로딩될 번지와 실행될 번지를 다르게 지정하기 ◆ 페리페럴들을 C언어의 구조체처럼 사용하기 ◆ Indirect Function Call in C-program ◆ C언어의 I/O기능 활용(에뮬레이터 연결시만) ---- 버전에 따라 기능 유/무 ◆ ISR 이름바꾸기(#progma INTERRUPT(func); ) C40 C소스레벨 디버거의 특징 ◆ JTAG Port를 통한 인터페이스 방식 ◆ 2가지 디버깅 방식 지원(기본, Profile Mode) ◆ 풀다운 메뉴를 통한 디버깅 ◆ 사용자에의한 커맨트 입력 방식의 디버깅 ◆ 사용자가 미리 작성한 Batch File을 통한 디버깅 ◆ 'C I/O'기능 제공(컴파일러가 구버젼일 경우 지원안함)
다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
맨위로

카페 검색

카페 검색어 입력폼