'분류 전체보기'에 해당되는 글 229건

  1. 2014.08.07 cmd 파일
  2. 2014.08.07 DSP281x_GlobalVariableDefs.c
  3. 2014.08.07 DSP281x_Device.h
  4. 2014.08.06 DSP281x_SysCtrl.c <좀더 자세히>
  5. 2014.08.06 전처리기(Precompiler) pragma
  6. 2014.08.06 DSP281x_SysCtrl.c
  7. 2014.08.05 DSP281x_CodeStartBranch.asm
  8. 2014.08.05 asm(" nop")
  9. 2014.08.05 DSP와 표준C의 차이
  10. 2014.08.05 .gel 파일 대충 이해하기
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 십자성군
TMS320/Study2014. 8. 5. 21:16

asm("    nop")구문은 인라인 어셈블리(inline assembly)함수로, C 코드에 간단한 어셈블리 구문을 곧바로 삽입하는 역할을 한다.

브레이크 포인트, 푸르부 포인트, 프로파일링 등을 쉽게 하기 위한 구문이며 이에 대하여 이 글에 점점 추가하도록 하겠다.

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

DSP281x_SysCtrl.c  (0) 2014.08.06
DSP281x_CodeStartBranch.asm  (0) 2014.08.05
DSP와 표준C의 차이  (0) 2014.08.05
.gel 파일 대충 이해하기  (0) 2014.08.05
[이론]풀-업 저항과 풀-다운 저항2  (0) 2014.07.27
Posted by 십자성군
TMS320/Study2014. 8. 5. 20:35

1.

 

소프트웨어 프로그래밍을 위해서 자주 사용하는 stdio.h나 math.h는 표준 C에서 정의된 각종 입출력 함수와 수학함수가 정의되어 있다.

하지만 DSP같은 임베디드 프로세서에는 '표준 입출력 장치가 없다' 그런데도 표준 입출력 함수를 사용한다면, DSP는 메모리 영역인 stack, heap에서 '가상 입출력 장치'를 만들어서 데이터 입출력을 하게 된다. 언뜻 보기만 해도 매우 거추장스럽고 느려질 것 같지 않은가? 하드웨어가 됐든 소프트웨어가 됐든 신속 정확 간결이 중요하거늘 이는 매우 치명적인 문제가 될 수 있다.

 

더욱이 math.h는, 표준 C는 플랫폼(리눅스던, ARM이던, WINDOWS던)을 가리지 않고 수행되어야 하기 때문에 범용성을 높인 대신 어느 한 플랫폼에 최적화 되어있지는 않다. 즉, DSP에 있어서는 비효율적일 수 밖에 없다는 것이다. 따라서 TI에서는 DSP에 적합한 효율이 좋은 수치함수를 IQmath로 제공하고 있다.

 

2.

28X DSP는 일부 데이터 형이 C와 다르다.

 

 

 

char 

short 

int 

long 

long long 

float 

double 

long double 

 C

16 

32 

32 

64 

32 

64 

64 

 28X

16 

16 

16 

32 

 

32 

32 

64 

 

char, int, double의 크기가 다르며 long long이 없다.

따라서 double을 쓸것 없이 float를 사용하면 된다. 일반 C플랫폼과 DSP간의 데이터 교환이 있을 경우 이런 bit차이에 조심하여야 하겠다.

 

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

DSP281x_CodeStartBranch.asm  (0) 2014.08.05
asm(" nop")  (0) 2014.08.05
.gel 파일 대충 이해하기  (0) 2014.08.05
[이론]풀-업 저항과 풀-다운 저항2  (0) 2014.07.27
[이론]풀-업 저항과 풀-다운 저항  (0) 2014.07.27
Posted by 십자성군
TMS320/Study2014. 8. 5. 17:29

GEL : General Environment Languages 로 Code Composer 사용 환경을 좀 더 편리하도록 하기 위해 고안한 스크립트 언어 이다.

 

여기서는 f2812.gel 파일을 살펴볼텐데, CCS3.3같은곳에서는 따로 볼 수 있을 듯 하지만 일단 5.0에서는 ti폴더의 ti\ccsv5\ccs_base\emulation\gel폴더에 있다. 파일을 열면 개요를 확인할 수 있다.

 

/********************************************************************/
/* f2812.gel                                                        */
/* Version 4.00.1                                                   */
/*                                                                  */
/* This GEL file is to be used with the TMS320F2812 DSP.            */
/* Changes may be required to support specific hardware designs.    */
/*                                                                  */
/* Code Composer Studio supports six reserved GEL functions that    */
/* automatically get executed if they are defined. They are:        */
/*                                                                  */
/* StartUp()              - Executed whenever CCS is invoked        */
/* OnReset()              - Executed after Debug->Reset CPU         */
/* OnRestart()            - Executed after Debug->Restart           */
/* OnPreFileLoaded()      - Executed before File->Load Program      */
/* OnFileLoaded()         - Executed after File->Load Program       */
/* OnTargetConnect()      - Executed after Debug->Connect           */
/*                                                                  */
/********************************************************************/

 

여기서 소개되는 함수는 아래와 같다.

1.StartUp

2.OnReset

3.OnRestart

4.OnPreFileLoaded

5.OnFileLoaded

6.OnTargetConnect

 

그 외에도 다양한 함수들이 많으며 hotmenu어쩌고 하는 함수들도 많이 보인다. 이들 내용중에는 DSP에 바로 명령을 보내거나 레지스터에 값을 보내는 내용도 있기 때문에 만약 이들을 제대로 이해하지 못한 상태에서 다루는 것은 굉장히 위험한 행동이다.

 

현재 CCS.V5 에서는 볼 수 없지만 GEL이라는 메뉴를 사용했지만 현재는 Scripts라는 메뉴를 사용하는듯 하다.

 

위 사진은 디버그 모드에 들어간 사진이다. Scripts메뉴가 활성화 된다. 이들은 GEL파일이 있기 때문에 활성화 되는 것으로 이들이 없었다면 개발자는 수작업으로 필요한 레지스터들을 'Watch window'로 불러야 할 것이다. 이런 레지스터리 관련 작업을 스크립트 언어로 수행할 수 있도록 한것이 GEL프로그램이다.

 

이런 GEL프로그램을 이해없이 잘못짜면... 당연히 대형사고가 터질 수 있지 않을까? 아무것도 모르는 상태로 레지스트리를 건드는 행동이라고 할 수 있겠다.

 

이 F2812.gel파일은 프로젝트와 함께 있지 않다. GEL파일은 칩에서 자동적으로 처리하는것이 아니기 때문에 절대적으로 의존하면 안된다. 레지스트리를 건드는 용도로 사용할 것이 아닌, MMR등을 '관찰'하는 용도로 사용하는 것이 바람직할 것이다.

Posted by 십자성군