기타2017. 2. 16. 05:24

DSP등을 사용하면서 UART데이터를 보내려고 할 때, 이를 위한 전용의 함수를 만들어서 사용하곤 한다.



예를들면


typedef volatile struct SCI_REGS RSCI, *PRSCI;


void sci_xmit(const PRSCI pChannel, const unsigned char b);

void ArrayTransmit(const PRSCI pChannel, const unsigned char* Array, const unsigned int length);


void sci_xmit(const PRSCI pChannel, const unsigned char b){

while(pChannel->SCICTL2.bit.TXEMPTY == 0){}

pChannel->SCITXBUF.all=b;

}


void ArrayTransmit(const PRSCI pChannel, const unsigned char* Array, const unsigned int length){

unsigned int i=0;


for(i=0; i<length;i++){

while(pChannel->SCICTL2.bit.TXEMPTY == 0){}

pChannel->SCITXBUF.all=Array[i];

}

}


위 코드는 내가 DSP 28335나 28377 에서 시리얼데이터를 보낼 때 사용하는 함수이다.

위와 같이 사용하면 SCI관련 레지스터의 포인터를 보내는 것으로 어떤 SCI 채널에서든 사용할 수 있다.


그런데 사용 도중 문제가 발생하였다. A와 B센서를 사용하고 이와 통신할 때, 처음에는 함수가 잘 동작하였었는데 프로젝트의 규모가 커지고 코드가 많아짐에 따라 B센서에 데이터가 잘 보내지지 않는 것이다.


당시 전송을 위해서 아래와 같은 코드를 사용했다.


BOOL Write(const PRSCI pChannel, const BYTE* data, const DWORD dataLength){

if(!data || dataLength <=0)

return FALSE;


if(pChannel == 0)

return FALSE;


const DWORD EOI = dataLength/2;

BYTE TXData = 0;

DWORD i = 0;


for(i=0; i<EOI; i++){

TXData = data[i];

sci_xmit(pChannel, (TXData&0x00ff));

sci_xmit(pChannel, ((TXData&0xff00)>>8));

}


return TRUE;

}


DSP에서는 자료형의 최소단위가 2byte였는데, 문자열을 보내는것이 아니라 byte데이터를 보내야 했기 때문에 2byte데이터에 대해서 위처럼 bit shift를 활용해야 했었다. 데이터가 정상적으로 센서에 전송이 되면 센서는 응답을 보내는데 당시 DSP의 수신기능에는 전혀 문제가 없었다.


이것저것 시험해본 결과 깨닫게 된 것은 데이터 전송에 있어서 함수호출방식을 사용했다는 것에 문제가 있다는 것이다. 저 sci_xmit함수를 한번 호출하는데 적어도 다음과 같은 과정을 거칠것이다.


1. 함수의 주소를 참조하여 함수를 호출한다.

2. 두개의 인수 pChannel과 데이터를 넣어준다.

3. 호출된 함수 sci_xmit에서 두 인수가 복사된다.

4. while에서 전송용 버퍼가 비워질 때 까지 기다린다.

5. 전송하고 return한다.


프로젝트 규모가 작았을 때는 센서 B에서 문제없이 응답이 돌아왔었는데 프로젝트가 커지더니 응답이 돌아오지 않았다. 디버깅모드에서 전송 행위는 정상적으로 이루어졌다고 보였었다.


여러가지 방법을 시도하다가 sci_xmit의 while문(버퍼가 비워질 때 까지 대기하기 위한)을 제거해 보았다. 그랬더니 센서 B로부터 응답이 돌아왔다. 정상적으로 동작한 것이다.

나로써는 프로젝트의 규모가 커졌다고는 하나 고작 16byte데이터를 보내는데 함수호출방식을 사용한다고 DSP 내부적으로 어떤 문제가 발생할 수 있는지 모르겠다.


센서 B와 통신이 정상화 되었더니 이번에는 센서 A로부터 응답이 없다.

센서 A는 B와는 전혀 다른 센서였는데, 명령 커맨드를 보내주면 이후에 요청한 정보를 계속 전송해 준다. 따라서 명령 커맨드가 제대로 전송되지 않았다고 보았다.

실제로 제거했던 while문을 다시 넣었더니 동작하는 것이다. 이 점에 있어서는 DSP의 문제라기 보다는 센서 A가 데이터를 수신할 때 어느정도의 텀이 필요한것이 아닌가 생각되었다.

결국 센서 A와 센서 B에 대하여 다른 전송 함수를 사용할 수 밖에 없었다.


--------------------------------------------------------------------------------------

센서 B와 관련해서는 함수호출방식을 아예 배제하기 위해서 Write 함수의 빨간 코드 부분을 아래와 같이 바꾸었다.


for(i=0; i<EOI; i++){

TXData = data[i];

pChannel->SCITXBUF.all=(TXData&0x00ff);

pChannel->SCITXBUF.all=((TXData&0xff00)>>8);

}


만약 C++로 개발중이었다면 가볍게 인라인 함수로 함수화 했을텐데 아쉬운 부분이다.

Posted by 십자성군
TMS320/F283352017. 2. 9. 11:12


#define SYSCLK 150E6 /* 150MHz */

#define TBCLK 2343750 /* 60MHz */

#define     PWMCARRIER 20000 /* 20KHz */ (? : 목표 pwm 주파수?)



void InitEPwm1Module(void)

{

/* Setup TBCLK */

//PWM Counter Set

EPwm1Regs.TBPRD = (TBCLK/PWMCARRIER)-1;                         /* Set Timer Period */

EPwm1Regs.TBCTR = 0;                 /* Clear Counter */


/* Set Compare values */

EPwm1Regs.CMPA.half.CMPA = ((EPwm1Regs.TBPRD+1)>>1); /* Set Compare A value to 50% */

EPwm1Regs.CMPB = ((EPwm1Regs.TBPRD+1)>>1); /* Set Compare B value to 50% */


/* Setup counter mode */

EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; /* Count Up (Asymmetric) */

EPwm1Regs.TBPHS.half.TBPHS = 0; /* Phase is 0 */

EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; /* Disable phase loading */

EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; /* Period Register is loaded from its shadow when                                                                                 CNTR=Zero */

EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x0;                 /* Clock ratio to SYSCLKOUT */

EPwm1Regs.TBCTL.bit.CLKDIV = 0x6;                 /* TBCLK = SYSCLK / (HSPCLKDIV * CLKDIV) */ //important


/* Setup shadowing */

EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; /* Enable Shadowing */

EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; /* Load on CNTR=Zero */


EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;

EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;


/* Set actions */

EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;                 /* Set EPWM1A on CNTR=Zero */

EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;                 /* Clear EPWM1A on event A, up count */


EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;

EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;

}


이전 자료와 함께 설명한다.(http://yeahhappyday.tistory.com/search/epwm)


DSP 28335의 SYSCLK는 150Mhz 이다.

TBCLK는 Time Base clock을 의미하며 pwm의 clock으로써 사용한다.

이는 SYSCLK에서 분배하여 그 값을 정하며 수식적으로는 위에 표시해 놓았듯이 TBCLK = SYSCLK / (HSPCLKDIV * CLKDIV) 이다.

관련 그림은 다음과 같다.

위 소스에서는 CLKDIV를 0x6, HSPCLKDIV를 0으로 해놓았기 때문에 TBCLK는 150Mhz/64 로 2343750hz 가 된다.




위 그림을 보면 어떻게 돌아가는지 일목요연하다.

코드에 설정해 놓은것을 분석해 놓으면

150Mhz인 SYSCLK에서 1/64를 한 값인 2343750hz를 TBCLK로 설정하였으며

이에 역수를 취한 2343750^(-1) 값은 4.26e-7인데 이는 PWM생성을 위한 카운트 주기가 된다.

TBPRD값을 2343750/20000-1을 한 값은 116인데 이는 위에 설정한 카운트 주기에 대하여 117회 카운트를 한 것을 PWM의 1주기로 잡는다는 것이다.

따라서 (4.26e-7)*117 = 0.00004992 로 약 0.05ms(20kHz) 를 pwm의 한 주기로 설정한다는 것이다.


TBCLK : 2343750hz : 4.26e-7 (sec)

TBPRD : 117 count

PWM 주기 : 4.26e-7 * 117 = 0.00004992 (sec)

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

DSP 28335, 28377 flash 작업을 위한 기본자료  (0) 2017.02.22
DSP28335 Flash programming  (0) 2017.02.19
DSP 프로젝트 생성(28377, 28335 공통)  (0) 2016.11.21
Baudrate 설정  (0) 2016.10.09
InitPeripheralClocks  (0) 2016.03.09
Posted by 십자성군
기타/문제해결기2017. 2. 3. 12:22

참고 : http://www.ehowstuff.com/how-to-fix-you-could-try-using-skip-broken-to-work-around-the-problem-error/


내용

-설치 유틸리티 list에 대한 업데이트가 필요한게 아닐까 하다.

-list를 업데이트하고 이전 캐시를 지우라는 내용이려나?

Posted by 십자성군