TMS320/Study2014. 8. 11. 15:33

공부하는 내용

 

#pragma 전처리기


Start!

 

핸드북에서는 #pragma에 대하여 섹션설정과 관련햇 설명해 놓았다. 물론 MMR과 관련하여 설명하고 있으므로 그것으로 충분할지도 모른다. 하지만 MMR선언 및 조작과 관련하여서는 앞의 글로 충분하다고 생각하며 우리가 cmd를 확인할 수는 있어도 함부로 만질일은 거의 없을 것이다. 따라서 MMR과 관련된 섹션 설정 및 cmd작성은 '제어'를 목표로 그 선행지식을 위한 본 블로그에 맞지 않기에 핸드북에 맡기기로 하고 간단하게 #pragma에 대해서 다루기로 하겠다. 만약 device driver관련한 dll, lib등에 관심있다면 그와 관련된 전문서적을 참고하는것이 나을 듯 하다.

 

예전에 pragma에 대해서 다음과 같이 언급하였다.

 

pragma는 전처리기(preprocessor)을 의미하고 C컴파일러에 지시를 내릴 때 사용하는 명령이다. pragma의 지시어는 once, comment, loop등 다양하다.

 

아래를 숙지하자.

 

1.전처리문은 다양한 종류가 있다.

2.전처리기 앞에는 #을 적는다.

3.전처리기의 긑에는 ;을 붙이지 않는다

4.한줄에 하나의 전처리기만 사용 할 수 있다.

5.하나의 전처리기를 여러 줄로 나누어 처리하려면 줄 끝에 \(역 슬래쉬)를 붙인다.

 

전처리기의 종류는

 

1.#include                                             : 파일 처리를 위한 전처리문

2.#define, #undef                                   : 형태의 정의를 위한 전처리문

3.#if, #ifdef, #ifndef, #else, #elif, #endif    : 조건처리를 위한 전처리문

4.#pragma                                            : 컴파일 옵션 처리를 위한 전처리문

 

우리는 이중 4.#pragma에 대해 '짧게' 다루고자 한다.

 

#pragma는 전처리기 중 하나로 컴파일러에 명령을 내린다.

 

컴파일러에 대해 naver 백과사전의 내용을 인용하겠다.

고급언어(ex. c)로 쓰인 프로그램이 대상 기계(컴퓨터, 임베디드 장치 등)가 직접 이해할 수 있는 목적언어(어셈블리, 기계어 등)로 바꾸는 일을 하는 프로그램이다.[.out, .obj 등을 만들어 준다]

 

#pragma에 대해서 몇몇 예시를 들어 간단히 설명한다.

 

1.#pragma once() : 컴파일을 한번만 실행

:헤더 파일에서 자주 쓰이며 여러 소스 또는 헤더에서 참조될 때 중복참조의 여지가 있을 때 자주 사용된다.

 

2.#pragma pack() : 메모리 공간 최적화(구조체의 정렬 방식 지정)

()안에 숫자가 들어가며 구조체의 공간을 아낄 수 있다. 자세한 설명은 : http://euro87.tistory.com/150

3.#pragma warning() : 특정 경고 설정

 

4.#pragma DATA_SECTION, CODE_SECTION

 

실제로 dsp등을 사용하면서 다룰만한 것은 once나 pack 정도일 것이다. 섹션 설정은 크게 다룰 일은 없을 것이다.

'TMS320 > Study' 카테고리의 다른 글

28XDSP의 MMR선언과 배치 방법 정리  (0) 2014.08.11
구조체 명명법, MMR 관련 헤더 파일 종류  (0) 2014.08.11
28계열의 MMR선언 및 조작(1)  (0) 2014.08.11
MMR이란?  (0) 2014.08.08
cmd 파일  (0) 2014.08.07
Posted by 십자성군
TMS320/Study2014. 8. 11. 12:01

공부하는 내용

구조체를 기반으로 한 MMR조작 및 선언의 기본


Start!

 

 

GPAMUX BIT 

Peripheral Name 

GPIO Name 

GPADIR Bit 

Type 

Reset 

PWM1 

GPIOA0 

R/W 

1

PWM2

GPIOA1

1

R/W 

0

2

PWM3

GPIOA2

2

R/W 

0

3

PWM4

GPIOA3

3

R/W 

0

4

PWM5

GPIOA4

4

R/W 

0

5

PWM6

GPIOA5

5

R/W 

0

6

T1PWM_T1CMP

GPIOA6

6

R/W 

0

7

T2PWM_T2CMP

GPIOA7

7

R/W 

0

8

CAP1_QEP1

GPIOA8

8

R/W 

0

9

CAP2_QEP2

GPIOA9

9

R/W 

0

10

CAP3_QEPI1

GPIOA10

10

R/W 

0

11

TDIRA

GPIOA11

11

R/W 

0

12

TCLKINA

GPIOA12

12

R/W 

0

13

C1TRIP

GPIOA13

13

R/W 

0

14

C2TRIP

GPIOA14

14

R/W 

0

15

C2TRIP 

GPIOA15 

15 

R/W  

GPAMUX 레지스터 구조

 

struct GPAMUX_BITS  {        // bits   description
   Uint16 PWM1_GPIOA0:1;     // 0 
   Uint16 PWM2_GPIOA1:1;     // 1
   Uint16 PWM3_GPIOA2:1;     // 2 
   Uint16 PWM4_GPIOA3:1;     // 3 
   Uint16 PWM5_GPIOA4:1;     // 4 
   Uint16 PWM6_GPIOA5:1;     // 5
   Uint16 T1PWM_GPIOA6:1;    // 6 
   Uint16 T2PWM_GPIOA7:1;    // 7       
   Uint16 CAP1Q1_GPIOA8:1;   // 8
   Uint16 CAP2Q2_GPIOA9:1;   // 9
   Uint16 CAP3QI1_GPIOA10:1; // 10
   Uint16 TDIRA_GPIOA11:1;   // 11
   Uint16 TCLKINA_GPIOA12:1; // 12
   Uint16 C1TRIP_GPIOA13:1;  // 13 
   Uint16 C2TRIP_GPIOA14:1;  // 14 
   Uint16 C3TRIP_GPIOA15:1;  // 15  
        
};

 

GPAMUX에 대한 구조체를 위와같이 선언하였다. Uint16은 typedef unsinged int    Uint16

으로 선언된 16비트 부호없는 정수를 의미한다. 또한 각각의 변수는 비트필드로 1비트만을 사용하도록 하였다. PWM1등 GPIOA의 기능을 확인할 수 있다.

 

아래를 보자

 

union GPAMUX_REG {
   Uint16             all;
   struct GPAMUX_BITS bit;
};

 

union구조체 사용하여 GPAMUX에 대하여 bit또는 all을 이용하여 접근할 수 있음을 알 수 있다.

 

또한 아래와 같이

 

struct GPIO_MUX_REGS {
   union  GPAMUX_REG   GPAMUX;
   union  GPADIR_REG   GPADIR;
   union  GPAQUAL_REG  GPAQUAL;
   Uint16              rsvd1;
   union  GPBMUX_REG   GPBMUX;
   union  GPBDIR_REG   GPBDIR;
   union  GPBQUAL_REG  GPBQUAL;  
   Uint16              rsvd2[5];
   union  GPDMUX_REG   GPDMUX;
   union  GPDDIR_REG   GPDDIR;
   union  GPDQUAL_REG  GPDQUAL;  
   Uint16              rsvd3;
   union  GPEMUX_REG   GPEMUX;
   union  GPEDIR_REG   GPEDIR;
   union  GPEQUAL_REG  GPEQUAL;  
   Uint16              rsvd4;
   union  GPFMUX_REG   GPFMUX;
   union  GPFDIR_REG   GPFDIR;
   Uint16              rsvd5[2];
   union  GPGMUX_REG   GPGMUX;
   union  GPGDIR_REG   GPGDIR;
   Uint16              rsvd6[6];
};

 

GPIO A~BDEFG의 MUX레지스터군을 확인할 수 있다.

또한 아래와 같이 선언하여 다른 코드에서 GPIO_MUX_REGS에 참조가 가능하도록 하고 있다.

DSP281x_Gpio.h.를 참고하라

 

extern volatile struct GPIO_MUX_REGS GpioMuxRegs;

 

이와 관련된 섹션설정은 DSP281x_GlobalVariableDefs.c에서 확인할 수 있다.

 

#pragma DATA_SECTION(GpioMuxRegs,"GpioMuxRegsFile");

 

volatile struct GPIO_MUX_REGS GpioMuxRegs;

 

또한 nonBIOS.cmd에서 아래를 확인할 수 있다.

 

GpioMuxRegsFile   : > GPIOMUX,     PAGE = 1

 

여하튼 우리는 GpioDataRegs를 통해 GPIO_MUX_REGS 구조체에 접근할 수 있으며 GPIOA에 대한 설정도 가능한 것이다.

 

예를들어

 

GpioMuxRegs.GPAMUX.all = 0x0000 ;
GpioMuxRegs.GPAMUX.bit.PWM1_GPIOA0 = 1 ;    // PWM

 

위 코드를 보면, GPAMUX_REG 구조체의 all을 통해서 총 16비트에 한번에 값을 주거나, GPAMUX_BITS  구조체를 갖는 bit에 접근하여 개개의 비트에 접근할 수도 있다.

 

=============================================================================

기본은 마쳤지만 Tip으로써 아래를 보자.

 

/*

GpioMuxRegs.GPAMUX.bit.PWM1_GPIOA    =1;

GpioMuxRegs.GPAMUX.bit.PWM2_GPIOA    =1;

GpioMuxRegs.GPAMUX.bit.PWM3_GPIOA    =1;

GpioMuxRegs.GPAMUX.bit.PWM5_GPIOA    =1;

GpioMuxRegs.GPAMUX.bit.PWM6_GPIOA    =1;

*/

 

GpioMuxRegs.GPAMUX.all=0x0037;

 

위의 주석처리를 1번이라하고 그 아래를 2번이라고 하자. 두 코드 모두 같은 의미를 가지고 있다. 하지만 1번은 5사이클, 2번은 1사이클로 명령처리를 끝낸다. 큰 차이는 안나겠지만 되도록이면 2번과 같이 코드를 짜는것이 나을것이다. 하지만 개발하는 입장에서 인수인계의 문제를 생각한다면 1번이 더 편하겠지. 따라서 위와같이 1,2번 둘다 기재하고 1번을 주석처리하는 것이 여러모로 편할 것이다.

'TMS320 > Study' 카테고리의 다른 글

구조체 명명법, MMR 관련 헤더 파일 종류  (0) 2014.08.11
28계열의 MMR선언 및 조작(2)  (0) 2014.08.11
MMR이란?  (0) 2014.08.08
cmd 파일  (0) 2014.08.07
DSP281x_GlobalVariableDefs.c  (0) 2014.08.07
Posted by 십자성군
TMS320/Study2014. 8. 8. 16:55

공부하는 내용


 

Start!

앞의 글을 반드시 이해한 상태에서 공부하자! 

 

앞선 학습에서도 언급 됐었지만 MMR이란 Memory Mapped Register의 약자이다.

메모리처럼 조작 가능한 레지스터를 의미한다. 그리고 DSP Controller등 Controller 계통의 마이크로 프로세서에는 주변회로가 다양하기에 레지스터가 매우 많다.

 

 

내부(internal) 레지스터

 

계산용으로 사용되는 내부 레지스터는 계산과정에서 자연스럽게 접근이 가능하기에 주소를 부여하지 않는다.

번지를 가진 레지스터는 데이터 메모리 주소 생성 회로를 거쳐서 해당 번지를 부여받고 데이터 교환 작업이 이뤄지기에 사이클이 더 소모된다.

 

계산에는 Accmulator 레지스터, 곱셈을 위한 T, P레지스터 등이 필요하다.

 

이러한 내부 레지스터는 번지가 없기 때문에 데이터 교환으로 레지스터간 전용 통로를 구축하며 이를 레지스터 라 부른다.

레지스터 버스를 이용하면 주소 생성 과정이 필요없어지고 -> 데이터 교환 작업 등이 매우 신속하게 처리된다.

그러나 처리 속도면에서는 좋을 수 있으나 레지스터간 채널이 급격하게 증가하여 칩이 커지게 된다. 또한 전력소비도 많아진다.

메모리를 다루는 고수준 언어에서 주소가 없으니 레지스터를 다룰 수 없다.

 

시대가 지나면서 MPU에 주변회로가 함께 집적되어 CPU가 필요로 하는 레지스터가 많아지고 C언어 등 프로그래밍 언어가 보편화 되어 이를 이용한 개발 환경 구축이 요구되었다. 칩 사이즈를 줄이기 위해 레지스터 버스의 증가를 억제하고 처리능력을 올리기 위한 해결책으로 데이터 버 활용하게 되었다. 이를 통해서 레지스터의 내용을 메모리처럼 입출력하고 조작가능하게 되었다. 이를 통해 C언어와 같은 고수준 언어를 통한 조작이 가능해 진것이고 MMR의 개념이 생겨난 것이다.

 

결론을 말하자면

레지스터의 관리를 용이하도록 하기 위해, 메모리 주소와 같은 주소를 레지스터마다 부여하였으며, 이로 인해 C언어와 같은 데이터 메모리 조작형 언어에서도 어셈블리의 도움없이 레지스터 조작이 가능해진 것이다.

 

정리

1.내부 레지스터에는 사이클의 단축을 위해서 번지를 부여하지 않았으며 데이터 교환을 위한 전용 통로로 레지스터 버스를 활용한다.

2.레지스터 버스의 사용은 칩의 사이즈 증가와 전력소비 증가를 야기한다.

3.이를 줄이기 위해 데이터 버스를 활용하게 되었고 이를 통해 레지스터마다 고수준 언어인 C를 통해 어셈블리 없이 메모리 조작이 가능해졌다.

 

==============================================================================

MMRs(Memory Mapped Registers)

 

일반 입출력 핀인 GPIO(General Pulpose Input Output)을 예시로 들어본다.

GPIO는 개발자가 임의로 입출력 상태를 설정할 수 있다. 이 레지스터는 모두 MMR이며 개발자의 의도가 GPIO장치에 대한 레지스터에 올바르게 반영되어야 할것이다. 개발자는 이 레지스터에, 메모리 값을 사용하듯 읽거나 쓰면서 레지스터 내용을 정할 수 있다.

 

DSP에는 많은 핀들이 달려있고 전원, ADC, JTAG등의 핀을 제외하고는 모두 GPIO로 쓰일 수 있다. '쓰일 수 있다'라는 말의 의미는 '다른 용도도 있다'라고 들릴 수 있다. 리셋 직후에는 GPIO A0인 핀을 '설정 여부에 따라' PWM1로 사용할 수 있다.

 

 

 

GPIO핀 구조

 

위 그림을 보면 알 수 있듯이, GPxMUX레지스터의 설정에 따라 GPIO핀의 기능을 정할 수 있다.

GPxMUX를 0으로 설정하여 일반 입출력 포트로 설정할 경우, 이를 입력으로 사용할 것인지 출력으로 사용할 것인지를 GPxDIR레지스터로 정할 수 있다.

일반 입출력포트를 입력으로 정했다면 이 포트의 값을 읽을 있어야 하고 출력으로 정했다면 값을 정해줘야 할 것이다. 이를 위한 레지스터가 GPxDAT이다.

 

이런 제어를 위한 MCU에는 다양한 주변회로가 탑재되어 있고 이를 다루기 위한 많은 레지스터가 있다. 이 레지스터들을 C언어처럼 데이터 메모리를 조작하기 위해 레지스터에 메모리 주소를 부여하였다.

예를들어 GPAMUX레지스터를 조작학 싶다면 0x70C0라는 데이터 메모리 번지를 조작하면 되는 것이다. 간단히 말해 0x70C0번지에 있는 변수를 조작하는 것과 동일하다.

 

이처럼 번지를 부여받은 레지스터를 MMR(Memory Mapped Register)이라고 하며, 이 덕에 C언어에서 어셈블리 없이 MMR의 조작이 가능하다.

 

정리

1.GPxMUX로 핀의 기능을 정할 수 있다.

2.GPxDIR을 조작하여 일반 입출력 핀의 입출력 여부를 정할 수 있다.

3.GPxDAT값으로 값을 읽거나 쓸 수 있다.

4.레지스터의 메모리 주소를 통해서 C언어처럼 조작할 수 있다.

5.이렇게 주소를 부여받은 레지스터를 MMR이라고 한다.

'TMS320 > Study' 카테고리의 다른 글

28계열의 MMR선언 및 조작(2)  (0) 2014.08.11
28계열의 MMR선언 및 조작(1)  (0) 2014.08.11
cmd 파일  (0) 2014.08.07
DSP281x_GlobalVariableDefs.c  (0) 2014.08.07
DSP281x_Device.h  (0) 2014.08.07
Posted by 십자성군
TMS320/Study2014. 8. 7. 15:51

굉장히 길다!

 

결과파일(.out)이 생기는 일련의 과정이 어떻게 되냐하면

C로 작성된 코드가 컴파일러를 거쳐 어셈블리 파일이 되고 어셈블리 파일이 어셈블러를 거쳐서 오브젝트 파일이 된다.

 

C파일->[컴파일러]->어셈블리 파일->[어셈블러]->오브젝트 파일

 

오브젝트 파일은 기계어로 이루어져 있을 것인데, 주소 정보를 포함하고 있지 않아 마이크로프로세서에서 실행될 수 없다.

이때! 링커가 오브젝트 파일을 입력으로 받아, 개발자가 정의한 메모리 배치 정보를 토대로 주소 정보를 부여하며 결과 파일을 만들어 낸다.

 

정리

1.컴파일러 : C파일을 어셈블리 파일로

2.어셈블러 : 어셈블리 파일을 오브젝트 파일로

3.링커 : 오브젝트 파일에 주소 정보를 부여하고 결과 파일 생성

 

================================================================

링커 커맨더 파일 이용하여 링커에 지시를 보낼 수 있는데 이 링커 커맨더 파일을 cmd라고 한다.(commander)

 

DSP에서 요구하는 링커 커맨더 파일은 단순하다.

cmd파일은 '메모리 정의' 부분과 '섹션 배치' 부분으로 이루어져 있다.

메모리 정의 부분은 시스템이 가지고 있는 메모리 자원을 기술하였으며

섹션 배치 부분은, 컴파일러나 개발자가 작성한 섹션을 앞의 메모리 정의 부분에 배치하는 것을 지시한다.

 

정리

1.cmd(command)파일 : 링커에 지시를 보낸다

2.cmd의 '메모리 정의'부분 : 시스템의 메모리 자원을 기술

3.cmd의 '섹션 배치' 부분 : 섹션을 메모리 정의에 배치

================================================================

2812_RAM_Ink.cmd을 살펴보자.

 

MEMORY
{
PAGE 0 :
   
   RAMM0      : origin = 0x000000, length = 0x000400
   BEGIN      : origin = 0x3F8000, length = 0x000002            
   PRAMH0     : origin = 0x3F8002, length = 0x000FFE
   RESET      : origin = 0x3FFFC0, length = 0x000002          

        
PAGE 1 :

 

   RAMM1    : origin = 0x000400, length = 0x000400
   DRAMH0   : origin = 0x3f9000, length = 0x001000        
}

 

 

위의 코드는 메모리 영역을 기술하고 있다. 몇가지 지켜야 할 규칙이 있는데 PAGE0에는 '코드 성격의 섹션'이 배치될 영역을 잡아주고 PAGE1에는 데이터 성격의 섹션이 배치될 영역을 기술한다.

28X는 단일 메모리 구조라 엄격히 구분할 필요는 없다고 한다.

 

또한 영역의 크기를 기술할 때, 시작번지길이함께 기술해야 한다.

 

RESET은 코드성격의 섹션으로 2비트이며 아래의 메모리맵에서 찾을 수 있다.

 

 

만약 PAGE0에 아래와 같이 작성되어 있다고 생각해보자.

EXDRAM    :    origin = 0x100000, length = 0x006000

 

EMIF(External Memory Interface 회로)가 접근 가능한 Zone0에서 7중 6에 크기 0x006000 만큼을 EXDRAM이라는, 데이터 영역이 배치될 메모리로 잡았다.

 

 

정리

1.PAGE0 : 코드 성격의 섹션을 배치할 메모리

2.PAGE1 : 데이터 성격의 섹션을 배치할 메모리

3.섹션 영역의 배치를 할 메모리를 잡을 때, 시작번지와 길이를 기술해야 한다.

================================================================

SECTIONS
{

   codestart        : > BEGIN,       PAGE = 0
   ramfuncs         : > PRAMH0       PAGE = 0 
   .text            : > PRAMH0,      PAGE = 0
   .cinit           : > PRAMH0,      PAGE = 0
   .pinit           : > PRAMH0,      PAGE = 0
   .switch          : > RAMM0,       PAGE = 0
   .reset           : > RESET,       PAGE = 0, TYPE = DSECT /* not used, */
  
   .stack           : > RAMM1,       PAGE = 1
   .ebss            : > DRAMH0,      PAGE = 1
   .econst          : > DRAMH0,      PAGE = 1     
   .esysmem         : > DRAMH0,      PAGE = 1

    
}

 

섹션 배치 부분이다. 코드에서 정의된 섹션을 위 MEMORY{ } 부분에 정의된 영역에 배치하는 것을 지시한다.

 

 codestart        : > BEGIN,       PAGE = 0
위 지시의 의미는 codestart 라는 섹션을 BEGIN이라는 영역에 주입할 것을 지시한다. 또한 PAGE0에 정의된 영역이라고 알려주고 있다.

 

참고로 codestart는 DSP281x_CodeStartBranch.asm에 선언되어 있다.

BEGIN의 크기는 고작 2word이다. 이는 이 섹션으로 이름 붙여진 코드가 LB _c_int00뿐이며 그 코드의 크기가 2word에 불과하기 때문이다.

 

<대충읽기>

앞서 배웠듯이 _c_int00는 rts2800_ml.lib에 있기 때문에 _c_int00가 수행하면 반드시 rts2800_ml.lib으로 분기하게 되고 그 내용을 실행한다.

MEMORY{ }을 보면 0x3F8000으로 잡혀있는데, 핸드북 47페이지의 부트모드를 보면 0010의 부트모드일 경우 H0 SARAM주소 0x3F8000으로 바로 점프함을 알 수 있다. 이 H0에 대한것 역시 34페이지(또한 56페이지)에 나와있다. 0010모드는 H0에서 코드를 시작하게 하여 시스템 개발 과정을 신속하고 편리하게 할 수 있도록 도모한다.

 

조금만 더 간단히, 설명하자. 위에 내용은 너무 헷갈릴 수 있다.

 

MC모드 기준으로 설명한다.

 

1. 우리가 부트모드를 0010으로 설정했다고 하자. 리셋 신호가 인가된 DSP는 리셋 벡터에 의해 부트로더를 실행시킨다.

2. 부트로더는 핀 설정 상태가 0010임을 감지하고 부트로더 수행을 마친 후 이에 따라 H0 SARAM으로 즉, 0x3F8000으로 분기하게 된다.

3. 0x3F8000번지에 codestart라는 섹션이 넣어져 있다.

4. codestart섹션에서는 LB _c_int00 코드를 실행하라고 한다.

5. 위 코드가 실행되어 _c_int00 즉, rts2800_ml.lib가 어디에 있던(플래시 메모리던, 외부 메모리던) 정확히 호출한다.

6. rts2800_ml.lib가 호출되어 프로그램이 수행될 수 있도록 칩 상태를 정비한 후, main()함수를 호출한다. 

 

.reset의 경우 뒤에 TYPE=DSECT라고 되어있다. DESECT는 앞서 선언한 내용을 '무효로 한다'고 지시한다.

이 RESET은 0x3FFFC0으로 리셋벡터를 가리킨다. 또한 이 리셋벡터는 TI가 마스킹 해놓은 변경불가 영역이다. 즉 이 리셋벡터에 대하여 새로 선언한 내용이 쓸모가 없고 그럴 필요도 없다는 것이다.

 

================================================================

링커의 과정을 아래와 같이 기술한다.

 

 

 

앞서 언급했듯이 링커커맨더 파일을 통해 링커에 지시를 내릴 수 있다.

링커는 오브젝트 파일에 주소 정보를 부여하고 결과 파일(.out)을 생성한다. 또한 링커과정을 보고하는 문서 파일인 map파일 생성한다.

 

================================================================

◎DSP281x_Headers_nonBIOS.cmd

 

역할 : BIOS를 사용하지 않는 상태(nonBIOS)의 MMR을 선언한 헤더(Headers)와 관계된 메모리 정의 및 섹션배치(cmd).

 

BIOS를 사용하는 경우 DSP281x_Headers_BIOS.cmd를 사용하면 된다.

파일의 내용을 살펴보자

 

 

 

 

메모리 배치에 있어서 프로그램 영역은 텅 비어있고 데이터 메모리만이 있다. MMR은 C언어에서 모두 데이터로 취급되기 때문이다.

 

예를들어 ADC부분을 보자.[순서대로 확인하면 이해하기 쉽습니다.]

☞Page1에 있는 ADC는 0x007100번지에 0x00020길이만큼 메모리를 배치받았다.

☞또한 SECTION 부분을 보면 AdcRegsFile 이라는 섹션을 ADC영역에 주입함을 알 수 있다.

☞이 AdcRegsFile섹션은 DSP281x_GlobalVariableDefs.c에서 전처리기(pragma)에 DATA_SECTION이라는 함수를 통해 선언되어 있다.(AdcRegFile섹션을 AdcRegs라고 명명했음)

☞또한 아래에 volatile struct ADC_REGS AdcRegs;로 ADC_REGS구조체로 데이터형을 대입하였다.

☞DSP281x_Adc.h에는 구조체로 정의된 ADC관련 MMR이 정의되어 있다. (struct ADC_REGS를 볼 수 있으며 그와 관련된 struct, union구조체를 확인할 수 있다.)

 

정리하자면, cmd를 통해 메모리를 배치하고 섹션을 배치하였으며, DSP281x_GlobalVariableDefs.c에서 이를 AdcRegs라고 데이터섹션으로 새로 명명하였다. 그리고 이를 다시 DSP281x_Adc.h에서 선언되어 있는 ADC_REGS의 구조체 데이터형으로 대입하였다. 우리는 이 구조체에 접근하는 것으로 레지스터를 조작할 수 있다. 

 

정리

1.DSP281x_Headers_nonBIOS.cmd은 nonBIOS의 MMR을 선언한 헤더와 관계된 메모리 정의 및 섹션배치를 위한 링커커맨더 이다.

2.MMR은 C언어에서 모두 데이터로 취급된다.

 

P.S : 그 외에도 DSP281x_SysCtrl.c에 명시되어 있는 ramfuncs 역시 선언되어 있다.

'TMS320 > Study' 카테고리의 다른 글

28계열의 MMR선언 및 조작(1)  (0) 2014.08.11
MMR이란?  (0) 2014.08.08
DSP281x_GlobalVariableDefs.c  (0) 2014.08.07
DSP281x_Device.h  (0) 2014.08.07
DSP281x_SysCtrl.c <좀더 자세히>  (0) 2014.08.06
Posted by 십자성군
TMS320/Study2014. 8. 7. 14:21

공부하는 내용




Start!

전역변수 정의를 기술한 소스코드이며 이 코드로 인하여 MMR을 정의한 헤더 파일의 내용들이 지정된 메모리 번지와 연결이 된다.

 

1.

 

#ifdef __cplusplus
#pragma DATA_SECTION("AdcRegsFile")
#else
#pragma DATA_SECTION(AdcRegs,"AdcRegsFile");
#endif
volatile struct ADC_REGS AdcRegs;

 

#ifdef __cplusplus는 C++의 Name mangling과 관련된 것으로 나중에 추후 서술하겠다.

 

일단, C++의 cpp로 만들어 졌다면

#pragma DATA_SECTION("AdcRegsFile")을 선언하여 AdcRegsFile이라는 데이터 섹션을 만드는 것이고, 그렇지 않다면(그냥 c라면) AdcRegs를 AdcRegsFile이라는 데이터 섹션으로 관리하겠다는 것이다.

 

아래에 volatile struct ADC_REGS AdcRegs로, AdcRegs를 선언하였고 구조체 ADC_REGS에 대한 정보는 DSP281x_Adc.h에 기재되어 있다.

 

ADC_REGS는 아래와 같이 구조체로 선언되어 있다.

 

struct ADC_REGS {
    union ADCTRL1_REG      ADCTRL1;       // ADC Control 1
    union ADCTRL2_REG      ADCTRL2;       // ADC Control 2
    union ADCMAXCONV_REG   ADCMAXCONV;    // Max conversions
    union ADCCHSELSEQ1_REG ADCCHSELSEQ1;  // Channel select sequencing control 1
    union ADCCHSELSEQ2_REG ADCCHSELSEQ2;  // Channel select sequencing control 2
    union ADCCHSELSEQ3_REG ADCCHSELSEQ3;  // Channel select sequencing control 3
    union ADCCHSELSEQ4_REG ADCCHSELSEQ4;  // Channel select sequencing control 4
    union ADCASEQSR_REG    ADCASEQSR;     // Autosequence status register
    Uint16                 ADCRESULT0;    // Conversion Result Buffer 0
    Uint16                 ADCRESULT1;    // Conversion Result Buffer 1
    Uint16                 ADCRESULT2;    // Conversion Result Buffer 2
    Uint16                 ADCRESULT3;    // Conversion Result Buffer 3
    Uint16                 ADCRESULT4;    // Conversion Result Buffer 4
    Uint16                 ADCRESULT5;    // Conversion Result Buffer 5
    Uint16                 ADCRESULT6;    // Conversion Result Buffer 6
    Uint16                 ADCRESULT7;    // Conversion Result Buffer 7
    Uint16                 ADCRESULT8;    // Conversion Result Buffer 8
    Uint16                 ADCRESULT9;    // Conversion Result Buffer 9
    Uint16                 ADCRESULT10;   // Conversion Result Buffer 10
    Uint16                 ADCRESULT11;   // Conversion Result Buffer 11
    Uint16                 ADCRESULT12;   // Conversion Result Buffer 12
    Uint16                 ADCRESULT13;   // Conversion Result Buffer 13
    Uint16                 ADCRESULT14;   // Conversion Result Buffer 14
    Uint16                 ADCRESULT15;   // Conversion Result Buffer 15
    union ADCTRL3_REG      ADCTRL3;       // ADC Control 3
    union ADCST_REG        ADCST;         // ADC Status Register
};

 

위와같이 MMR정보를 구조체로 정의하였기 때문에 비트 단위 접근등이 용의하다. 물론 이렇게 해서는 고전 방식과 같이

#define ADCTRL1    (volatile unsigned int *)0x7100

식으로 주소를 바로 부여할 수 없기에 저기 위에처럼 데이터 섹션으로 관리한다. 이 구조체 데이터를 섹션으로 관리하고 링커에게 이 섹션을 메모리의 특정 영역에 배치하라고 하면 자연스럽게 번지 정보를 부여할 수 있는 것이다.

 

다음은 링커를 공부하자!

'TMS320 > Study' 카테고리의 다른 글

MMR이란?  (0) 2014.08.08
cmd 파일  (0) 2014.08.07
DSP281x_Device.h  (0) 2014.08.07
DSP281x_SysCtrl.c <좀더 자세히>  (0) 2014.08.06
전처리기(Precompiler) pragma  (0) 2014.08.06
Posted by 십자성군
TMS320/Study2014. 8. 7. 04:01

공부하는 내용




Start!

◎코드에 반드시 집어넣는 헤더파일 DSP281x_Device.h의 이해는 반드시 필요할 것이다.

가장 큰 역할 : DSP의 MMR(Memory Mapped Register)이 선언된 헤더 파일 전체를 포함.

DSP의 MMR은 기능단위로 쪼개져 있어 여러 헤더파일에 걸쳐 선언되어 있다. 프로그래밍에서 이들을 일일이 include할 수도 없는 노릇이기에 이를 통합하는 것이 DSP281x_Device.h이다.

◎MMR은 Header_nonBios.cmd에 선언되어 있다.



코드 분석을 해보자

 

1.

 

#define   TARGET   1
//---------------------------------------------------------------------------
// User To Select Target Device:

#define   DSP28_F2812   TARGET
#define   DSP28_F2811   0
#define   DSP28_F2810   0

 

TARGET을 1이라는 값으로 명명하고 DSP28_F2812가 TARGET으로 명명되었다. 즉, DSSP28_F2812가 1이라고 명명된것.

 

2.

 

#define  EINT   asm(" clrc INTM")
#define  DINT   asm(" setc INTM")
#define  ERTM   asm(" clrc DBGM")
#define  DRTM   asm(" setc DBGM")
#define  EALLOW asm(" EALLOW")
#define  EDIS   asm(" EDIS")
#define  ESTOP0 asm(" ESTOP0")

 

EINT등이 인라인 어셈블리 함수로 명명되어 있다. 앞서 보았었던 EALLOW, EDIS가 어셈블리 함수와 연결되어 있음을 알 수 있다.

 

3.

 

#define M_INT1  0x0001
#define M_INT2  0x0002
#define M_INT3  0x0004
#define M_INT4  0x0008
#define M_INT5  0x0010
#define M_INT6  0x0020
#define M_INT7  0x0040
#define M_INT8  0x0080
#define M_INT9  0x0100
#define M_INT10 0x0200
#define M_INT11 0x0400
#define M_INT12 0x0800
#define M_INT13 0x1000
#define M_INT14 0x2000

#define M_DLOG  0x4000
#define M_RTOS  0x8000

 

인터럽트 설정을 위한 비트마스크이다. 사용할 인터럽트에 대해서 M_INT1 등으로 명명해놓은것.

 

4.

 

#define BIT0    0x0001
#define BIT1    0x0002
#define BIT2    0x0004
#define BIT3    0x0008
#define BIT4    0x0010
#define BIT5    0x0020
#define BIT6    0x0040
#define BIT7    0x0080
#define BIT8    0x0100
#define BIT9    0x0200
#define BIT10   0x0400
#define BIT11   0x0800
#define BIT12   0x1000
#define BIT13   0x2000
#define BIT14   0x4000
#define BIT15   0x8000

 

일반 레지스터 조작의 접근편이성을 위해서 BIT0,1 등으로 명명해 놓았다.

 

5.

 

#ifndef DSP28_DATA_TYPES
#define DSP28_DATA_TYPES
typedef int                 int16;
typedef long                int32;
typedef long long           int64;
typedef unsigned int        Uint16;
typedef unsigned long       Uint32;
typedef unsigned long long  Uint64;
typedef float               float32;
typedef long double         float64;
#endif

 

DSP28_DATA_TYPES 이 전처리기로 선언되어 있지 않으면/ 선언해주고 typedef로 int16등에 int등의 별칭을 붙여준다.

 

6.

 

#include "DSP281x_SysCtrl.h"            // System Control/Power Modes
#include "DSP281x_DevEmu.h"             // Device Emulation Registers
#include "DSP281x_Xintf.h"              // External Interface Registers
#include "DSP281x_CpuTimers.h"          // 32-bit CPU Timers
#include "DSP281x_PieCtrl.h"            // PIE Control Registers
#include "DSP281x_PieVect.h"            // PIE Vector Table
#include "DSP281x_Spi.h"                // SPI Registers
#include "DSP281x_Sci.h"                // SCI Registers
#include "DSP281x_Mcbsp.h"              // McBSP Registers
#include "DSP281x_ECan.h"               // Enhanced eCAN Registers
#include "DSP281x_Gpio.h"               // General Purpose I/O Registers
#include "DSP281x_Ev.h"                 // Event Manager Registers
#include "DSP281x_Adc.h"                // ADC Registers
#include "DSP281x_XIntrupt.h"           // External Interrupts

 

마지막으로 각종 헤더파일을 인클루드 하고 있다.

 

예를들어서 DSP281x_Adc.h는 ADC와 관련된 레지스터가 구조체 형식으로 정의되어 있고 .c파일에서 초기화 함수가 선언되어 있다.

'TMS320 > Study' 카테고리의 다른 글

cmd 파일  (0) 2014.08.07
DSP281x_GlobalVariableDefs.c  (0) 2014.08.07
DSP281x_SysCtrl.c <좀더 자세히>  (0) 2014.08.06
전처리기(Precompiler) pragma  (0) 2014.08.06
DSP281x_SysCtrl.c  (0) 2014.08.06
Posted by 십자성군
TMS320/Study2014. 8. 6. 13:36

공부하는 내용

Watchdog의 무력화와 리셋

PLL 설정과 클럭 시스템 구조 및 분해능 설정



Start!

DisableDog의 함수를 알아보자.

 

1.


void DisableDog(void)
{
    EALLOW;
    SysCtrlRegs.WDCR= 0x0068;
    EDIS;
}

 

EALLOW : MRR보호영역 해제

EDIS : MRR보호

SysCtrlRegs.WDCR = 0x0068;

 

시스템 레지스트리의 WDCR에 0x0068을 주입하였다. WDCR은 Protected영역에 위치하여 보호되어 있기 때문에 값을 쓰기 위해서는 EALLOW 명령어로 보호를 해제 후 EDIS로 다시 보호상태로 해준다.


2.

 

void KickDog(void)
{
    EALLOW;
    SysCtrlRegs.WDKEY = 0x0055;
    SysCtrlRegs.WDKEY = 0x00AA;
    EDIS;
}

 

Watchdog 리셋을 하기 위한 함수로 WDKEY에 0x0055와 0x00AA라는 값을 넣어주면 된다. CPU는 이 함수를 주기적으로 사용하여 Watchdog을 리셋 해주어야 하며 이를 잊으면 Watchdog타이머가 넘치게 되어 CPU가 리셋 당할 수 있다.

 

3.


InitPll(0xA);

 

void InitPll(Uint16 val)
{
   volatile Uint16 iVol;

   if (SysCtrlRegs.PLLCR.bit.DIV != val)
   {

      EALLOW;
      SysCtrlRegs.PLLCR.bit.DIV = val;
      EDIS;
      for(iVol= 0; iVol< ( (131072/2)/12 ); iVol++)
      {

      }
   }
}

 

 

 

PLL : Phase Lock Loop

역할 : 시스템 클럭 조정

 

 

DIV3 

DIV2 

DIV1 

DIV0 

Clock Frequency (CLKIN) 

0

OSCCLK x 1/2 

OSCCLK x 1/2  

OSCCLK x 2/2  

1

OSCCLK x 3/2  

OSCCLK x 4/2  

OSCCLK x 5/2  

OSCCLK x 6/2  

OSCCLK x 7/2  

 1

OSCCLK x 8/2  

OSCCLK x 9/2  

OSCCLK x 10/2  

 

우리는 PLL을 설정하여 PLL출력 클럭을 입력 클럭의 최저 1배에서 최대 10배까지 변화시킬 수 있다.

이 PLL 출력 클럭은 다시 1/2배 되어 CPU에 공급된다.

 

PLL의 초기상태는 DIV3~0비트가 0(0xA)으로 설정되어 있기 때문에 개발자가 따로 설정하지 않은 경우 칩 외부에 설치한 오실레이터등의 주파수의 1/2배의 클럭 주파수로 구동된다.

만약 30MHz 오실레이터를 사용하고 있다면 우리는 DSP를 최대 150MHz로 구동할 수 있을 것이다.

 

위의 InitPll함수에서 붉게 표시한 부분은 단순 루프로써 PLL안정화에 필요한 시간을 확보하는 역할을 한다. PLL을 조정할 때 시스템 클럭이 바뀌고 안정화 할 때까지 시간이 필요하기 때문이다.

 

함수에서 보면 알 수 있듯이 EALLOW 및 EDIS를 사용하여 MRR의 보호를 해제 및 다시 보호하고 Watchdog에 의한 리셋을 피하기 위하여 DisableDog()를 사용하였다.

 

4.


InitPeripheralClock() 함수는 주변 회로에 공급되는 클럭의 주파수 조절과 함께 공급 여부도 설정하는 코드를 포함한다.


위의 사진에서는 나와있지 않지만, 핸드북을 살펴보면 HSPCLKLSPCLK를 볼 수 있다. 위 사진의 SYSCLKOUT에서 갈라져 나오는것 같다. HSPCLK는 'High Speed Clock의 약자로 고속 클럭을 필요로 하는 주변회로로 클럭을 공급하고 LSPCLK는 Low Speed Clock으로 저속 클럭을 요구하는 주변회로에 클럭을 공급한다.


HSPCLK : ADC, EV(Event Manager)

LSPCLK : eCAN, McBSSP, SPI, SCI


하지만, 저속회로에 고속클럭이 필요하거나 고속회로에 저속클럭이 필요한 경우도 있을 수 있다. 이를 위해서 HSPCLK와 LSPCLK의 주파수 조정 레지스터가 존재하며 각각 HISPCP와 LOSPCP로 구분된다.


아래 표를 보자



H/LSPCLK2 

H/LSPCLK1

H/LSPCLK0 

Peripheral Clock Frequency 

SYSCLKOUT/1 

SYSCLKOUT/2

SYSCLKOUT/4 

SYSCLKOUT/6 

SYSCLKOUT/8 

SYSCLKOUT/10 

SYSCLKOUT/12

SYSCLKOUT/14


HISPCP의 default는 001이며 LOSPCP의 default는 010이다. 즉, HSPCLK를 제일 정밀하게 사용하고 싶다면, 150MHz로 사용해야 할것이며 이를 위해서 PLL을 1010으로, HSPCLK를 000으로 설정해주어야 할것이다. 만약, PLL만 조정을 해준다면 결과적으로 75MHz가 될것이다.


 PCLKCR이라는 레지스터가 주변 회로 각각에 클럭 공급 여부를 결정짓는다.


void InitPeripheralClocks(void)

{

   EALLOW;

// HISPCP/LOSPCP prescale register settings, normally it will be set to default values

   SysCtrlRegs.HISPCP.all = 0x0001;

   SysCtrlRegs.LOSPCP.all = 0x0002;


// Peripheral clock enables set for the selected peripherals.

   SysCtrlRegs.PCLKCR.bit.EVAENCLK=1;

   SysCtrlRegs.PCLKCR.bit.EVBENCLK=1;

   SysCtrlRegs.PCLKCR.bit.SCIAENCLK=1;

   SysCtrlRegs.PCLKCR.bit.SCIBENCLK=1;

   SysCtrlRegs.PCLKCR.bit.MCBSPENCLK=1;

   SysCtrlRegs.PCLKCR.bit.SPIENCLK=1;

   SysCtrlRegs.PCLKCR.bit.ECANENCLK=1;

   SysCtrlRegs.PCLKCR.bit.ADCENCLK=1;

   EDIS;

}


만약 모든 주변회로에 클럭을 넣는다면 다음과 같은 명령을 내리면 된다.

SysCtrlRegs.PCLKCR.all = 0x00FF;



내용정리


EALLOW : MRR보호영역 해제

EDIS : MRR보호

SysCtrlRegs.WDCR = 0x0068;    Watchdog disable

SysCtrlRegs.WDKEY = 0x0055;    Watchdog 리셋 관련


SysCtrlRegs.PLLCR.bit.DIV        PLL 클럭 설정

HSPCLK

LSPCLK

SysCtrlRegs.HISPCP.all

SysCtrlRegs.LOSPCP.all

SysCtrlRegs.PCLKCR.bit.EVAENCLK


P.S

WDCR레지스트리에 대한 학습 필요

'TMS320 > Study' 카테고리의 다른 글

DSP281x_GlobalVariableDefs.c  (0) 2014.08.07
DSP281x_Device.h  (0) 2014.08.07
전처리기(Precompiler) pragma  (0) 2014.08.06
DSP281x_SysCtrl.c  (0) 2014.08.06
DSP281x_CodeStartBranch.asm  (0) 2014.08.05
Posted by 십자성군
TMS320/Study2014. 8. 6. 13:26

 

'TMS320 > Study' 카테고리의 다른 글

DSP281x_Device.h  (0) 2014.08.07
DSP281x_SysCtrl.c <좀더 자세히>  (0) 2014.08.06
DSP281x_SysCtrl.c  (0) 2014.08.06
DSP281x_CodeStartBranch.asm  (0) 2014.08.05
asm(" nop")  (0) 2014.08.05
Posted by 십자성군
TMS320/Study2014. 8. 6. 11:52

공부하는 내용

전처리기 pragma의 간단한 소개, 함수 섹션

초기화와 관련된 간단한 소개


Start!


DSP를 사용하다 보면 자주 쓰게될 InitSysCtrl() 함수는 칩 초기화 작업을 기술한 함수이고, DSP281x_SysCtrl.c에 있다.

 

칩 초기화를 이해하려면 칩 내부구조를 자세히 알고 있어야 하지만 기능적인 부분의 이해는 어렵지 않다.

우리 입맛에 맞게 초기화를 하고 싶다면 이 코드를 기초로 코드를 작성하면 되겠다.

 

그전에 DSP281x_SysCtrl.h라는 파일이 있음을 숙지하라. c파일에서는 함수정의 등이 있지만 h파일에는 레지스트리 구조가 구조체 형식으로 정의되어 있으니 Datasheet와 함께 봄이 좋다.

 

1.

 

최초에 DSP281x_Device.h와 DSP281x_Examples.h를 인클루드 하고 있다.

DSP281x_Device.h는 주요 MMR을 정의하고 있으며

DSP281x_Examples.h는 TI의 예제에서 자주 사용되는 중요 함수들이 정의되어 있다.

 

 

2.

 

다음으로 #pragma CODE_SECTION(InitFlash, "ramfuncs");라고 되어있다.

 

pragma는 전처리기(preprocessor)을 의미하고 C컴파일러에 지시를 내릴 때 사용하는 명령이다. pragma의 지시어는 once, comment, loop등 다양하다. 이에 대해서는 인터넷 검색으로 많은 정보를 얻을 수 있을 것이다.

 

CODE_SECTION이나 DATA_SECTION 이라는 키워드는 C언어에서 사용자 정의 섹션을 정의할 때 사용된다. 이 둘은 각각 코드 섹션 및 데이터 섹션 정의에 사용된다.

 

 

CODE_SECTION(InitFlash, "ramfunc")라는 말은 InitFlash 라는 함수를 ramfunc라는 섹션으로 정의하는 것을 뜻한다.

 

DATA_SECTION함수는 특정 데이터를 메모리 영역에 주입하기 위해 사용된다. 즉, 특정 데이터를 모아서 특정 섹션으로 구분지어 링커에게 특정 영역에 배치하도록 지시하는 것이다. 예를들어 #pragma DATA_SECTION(coeff,"m_coeff")는 coeff라는 배열을 C컴파일러의 pragma 전처리기를 통해서 m_coeff라는 섹션으로 처리한 것이다.

 

3.

 

다음으로 나오는 InitSysCtrl(void)에는 세 함수가 있다.

DisableDog()                : Watchdog을 무력화

InitPll(0xA)                    : PLLCR레지스터를 설정, 원하는 시스템 클럭 생성

InitPeripheralClocks()    : peripheral 클럭 설정(CPU로부터 나가는 주변 회로 공급 클럭의 주파수 설정 및 클럭 공급 여부 설정)

 

위에 대해서는 별개의 글에서 다루겠다.

 

'TMS320 > Study' 카테고리의 다른 글

DSP281x_SysCtrl.c <좀더 자세히>  (0) 2014.08.06
전처리기(Precompiler) pragma  (0) 2014.08.06
DSP281x_CodeStartBranch.asm  (0) 2014.08.05
asm(" nop")  (0) 2014.08.05
DSP와 표준C의 차이  (0) 2014.08.05
Posted by 십자성군
TMS320/Study2014. 8. 5. 21:59

공부하는 내용



Start!


이번 내용은 간단하게 그렇구나~ 하고 읽어주는 정도로 충분하다.

 

어셈블리... 일단 필자는 모른다. 현재 참고중인 핸드북 책에서는 쉽다고 한다. 일이 닥치면 금방 할 수 있다고 한다. 하지만 어셈블리는 그 플랫폼에 맞게 되어있기 때문에 이식성이 떨어진다. 요즈음의 C컴파일러의 효율이 뛰어나고 MCU의 데이터 처리 효율도 뛰어나서 어셈블리의 필요성도 낮아졌다. 딱히 이 파일이 없어도 잘 돌아가지 않는가? 게다가 딱히 어셈블리를 위한 가이드북도 없다!

 

그런데 이 코드를 잘 활용하면 DSP의 프로그램을 매우 효율적이고 쉽게 구현할 수 있다고 한다.

그렇다고 어셈블리를 배울 필요는 없다. 28x용 어셈블리는 위의 CodeStartBranch.asm하나로 충분하다고 하고 이해하고 이용하는 정도면 충분하다고 한다. 만약 깊게 들어가야 한다면 차후에 다루도록 하겠다. 이 파일의 코드를 이해하고자 한다면 핸드북을 참고하기를 바란다. 그렇게 길지도 않다.

 

끝내기 전에 약간 언급하고자 한다.

28x DSP에서 코드가 실행되는 과정:MC모드 기준

MCU를 MC모드(Micro Computer)모드로 운영할 경우 DSP칩이 부트할 경우 Program Counter(PC)에 0x3F FFC0가 실린다. 여기에는 리셋 벡터가 고정되어 있는데 이 주소는 내부 버스를 통해, TI가 마스킹한 Boot Rom을 가리킨다.(MC 말고도 MP(Micro Processor 모드가 있다.). 이 Boot Rom에 Boot Loader라는 작은 복사 프로그램이 있으며 MC모드일 때 이것이 실행된다. DSP281x_CodeStartBranch.asm 에는 Watchdog의 사용여부를 묻는 어셈블리 코드가 있다. rts2800_ml.lib도 관계되어 있다.

 

더 자세히는 보류..

 

 

 

 

 

'TMS320 > Study' 카테고리의 다른 글

전처리기(Precompiler) pragma  (0) 2014.08.06
DSP281x_SysCtrl.c  (0) 2014.08.06
asm(" nop")  (0) 2014.08.05
DSP와 표준C의 차이  (0) 2014.08.05
.gel 파일 대충 이해하기  (0) 2014.08.05
Posted by 십자성군