20141031 (C++ Template 분할 컴파일, ARM PWM)

170일차









-----------

C++

-----------



------- Template class 분할 컴파일


다음 예제 확인


예제)

--- PointTemlate.h


#ifndef __POINT_TEMPLATE_H
#define __POINT_TEMPLATE_H

template <typename T>
class Point
{
	private:
		T xpos, ypos;

	public:
		Point(T x = 0, T y = 0);

		void ShowPosition() const;
};

#endif




--- PointTemlate.cpp


#include <iostream>
#include "PointTemplate.h"

using namespace std;

template <typename T>
Point<T>::Point(T x = 0, T y = 0) : xpos(x), ypos(y)
{ }

template <typename T>
void Point<T>::ShowPosition() const
{
	cout << "[" << xpos << ", " << ypos << "]" << endl;
}




--- main.cpp


#include <iostream> #include "PointTemplate.h" using namespace std; int main() { Point<int> pos1(3, 4); pos1.ShowPosition(); Point<double> pos2(3.1, 4.2); pos2.ShowPosition(); Point<char> pos3('P', 'T'); pos3.ShowPosition(); return 0; }





이대로 컴파일하면 에러다.

템플릿에 대한 정보가 부족해서 그렇다.


해결 방법은 두 가지로

1. main.cpp에 #include "PointTemplate.cpp" 추가

2. PointTemplate.h 에 정의 내용 추가


그럼 에러없이 잘된다.

















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

ARM

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




------- PWM


Pulse Width Modulation의 뜻으로 주파수 변조이다. 예를 들어 5V의 신호를

High, Low 로 밖에 처리하지 못했었는데,

만약 High인 시간이 아주 짧게 계속 반복 된다면 어떻게 될까?

그냥 깜빡거림이 짧아질까??




하지만 깜빡거림이 짧아지면서 5V의 효과가 아닌 0.5V의 효과, 전압을 제어하게 된다!!

그래서 LED의 밝기가 약해지고 밝아지고를 할 수 있게 된다.




PWM은 두 가지 방법으로 사용 가능하다

1. PWM device를 사용

2. TC device를 사용


이번엔 TC device를 사용해서 해본다.



--- 먼저 TC Block Diagram



전에는 Interrupt 발생(보라색)으로 시간 계산을 했었는데

이제는 (빨강색) 내부 clock을 가공하여 외부로 출력해 일정 전압이 발생하는 것처럼 처리한다.



각 신호에 대한 설명




- 각 핀 설명







- 주파수가 발생하는 과정?



TC_CV Reg 값이 증가하다가 Ra Reg에 설정해 놓은 값을 만나면 TIOA에 High가 걸린다.

TC_CV Reg 값이 증가하다가 Rb Reg에 설정해 놓은 값을 만나면 TIOB에 High가 걸린다.

TC_CV Reg 값이 증가하다가 Rc Reg에 설정해 놓은 값을 만나면 TIOA, TIOB에 Low가 걸린다.

TC_CV Reg 값이 증가하다가 0xFFFF 인 최대 값에 도달하면 0으로 됨.


이때 이 High 걸리는 시간에 따라 전압이 달라지게 된다.




예제 소스)

#include "AT91SAM7S256.h"


#define MASTERCLOCK     48000000


void Delay_ms(unsigned int ms)

{

volatile unsigned int count;

volatile unsigned int countmax = (MASTERCLOCK / 10000) * ms;

for(count = 0; count < countmax; count++);

}


int main(void)

{

unsigned int RA = 1000;         // initial register value

unsigned int RB = 0xFFFF;

unsigned int RC = 0xFFFF;

unsigned int uiCnt = 1000;


*AT91C_PMC_PCER = (1 << AT91C_ID_TC0); // TC0 전원 공급

*AT91C_PIOA_PDR = 0xFFFFFFFF; // PA0, PA1 PIO비활성화

*AT91C_PIOA_BSR = AT91C_PIO_PA0 | AT91C_PIO_PA1;  // TIOA0,TIOB0 output(Peripheral B모드 사용)


   // TC0 Channel Control Register

//*AT91C_TC0_CMR =0x89898402;

*AT91C_TC0_CMR = AT91C_TC_BSWTRG_NONE |

AT91C_TC_BEEVT_NONE |

AT91C_TC_BCPC_CLEAR |

AT91C_TC_BCPB_SET |

AT91C_TC_ASWTRG_NONE |

AT91C_TC_AEEVT_NONE |

AT91C_TC_ACPC_CLEAR |

AT91C_TC_ACPA_SET |

AT91C_TC_WAVE |

AT91C_TC_WAVESEL_UP |

AT91C_TC_EEVT_XC0 |

AT91C_TC_CLKS_TIMER_DIV1_CLOCK;


*AT91C_TC0_CCR = 5;


*AT91C_TC0_RA = RA; // set TC0 RA register

*AT91C_TC0_RB = RB; // set TC0 RB register

*AT91C_TC0_RC = RC; // set TC0 RC register

*AT91C_TC0_SR = AT91C_TC_CLKSTA; // TC0 clock enable and start


while(1)

{

RA = RA + uiCnt;

RB = RB - uiCnt;

Delay_ms(250);


if(RA > RC)

{

RA = 1000;      // RA(PA0)은 점점 어두워지고

RB = 0xFFFF;    // RB(PA1)은 점점 밝아진다.

uiCnt = uiCnt + 2000;    // 밝아지고 어두워지는 속도가 점점 빨라짐

if(uiCnt > RC) // 속도 초기화

{

uiCnt = 1000;

}

}

*AT91C_TC0_RA = RA;

*AT91C_TC0_RB = RB;

}

}






설정

트랙백

댓글

20141030 (C++ string class, Template)

169일차









----------

C++

----------




------- string class


문자열과 관련된 class이다.

다음 예제 확인


예제)

#include <iostream>
#include <string>
using namespace std;

int main(void)
{
  string str1="I like ";
  string str2="string class";
  string str3=str1+str2;

  cout<<str1<<endl;
  cout<<str2<<endl;
  cout<<str3<<endl;

  str1+=str2;
  if(str1==str3)   
    cout<<"동일 문자열!"<<endl;
  else
    cout<<"동일하지 않은 문자열!"<<endl;

  string str4;
  cout<<"문자열 입력: ";
  cin>>str4;
  cout<<"입력한 문자열: "<<str4<<endl;
  return 0;
}

결과


위의 결과를 보면 알수 있듯이 string class를 사용하면

객체끼지 덧셈으로 문자열을 합칠 수도 있다.




이런 class가 어떻게 구현되는지 직접 구현해 보기로 한다.


예제)

#include <iostream>
#include <cstring>

using namespace std;

class String
{
  private:
    int len;
    char * str;

  public:
    String();
    String(const char * s);
    String(const String& s);
    ~String();
    String& operator=(const String& s);
    String& operator+=(const String& s);
    bool operator==(const String& s);
    String operator+(const String& s);

    friend ostream& operator<<(ostream& os, const String& s);
    friend istream& operator>>(ostream& os, const String& s);
};

String::String()
{
  len=0;
  str=NULL;
}

String::String(const char* s)
{
  len=strlen(s)+1;
  str=new char[len];
  strcpy(str, s);
}

String::String(const String& s)
{
  len=s.len;
  str=new char[len];
  strcpy(str, s.str);
}

String::~String() 
{
  if(str!=NULL)
    delete []str; 
}

String& String::operator= (const String& s)
{
  if(str!=NULL)
    delete []str;
  len=s.len;
  str=new char[len];
  strcpy(str, s.str);
  return *this;
}

String& String::operator+= (const String& s)
{
  len+=(s.len-1);
  char* tempstr=new char[len];
  strcpy(tempstr, str);
  strcat(tempstr, s.str);

  if(str!=NULL)
    delete []str;
  str=tempstr;
  return *this;
}

bool String::operator== (const String& s)
{
  return strcmp(str, s.str) ? false : true;
}

String String::operator+ (const String& s)
{
  char* tempstr=new char[len+s.len-1];
  strcpy(tempstr, str);
  strcat(tempstr, s.str);
  
  String temp(tempstr);
  delete []tempstr;
  return temp;
}

ostream& operator<< (ostream& os, const String& s)
{
  os<<s.str;
  return os;
}

istream& operator>> (istream& is, String& s)
{
  char str[100];
  is>>str;
  s=String(str);
  return is;
}

int main()
{
  String str1 = "I like ";
  String str2 = "string class";
  String str3 = str1 + str2;

  cout << str1 << endl;
  cout << str2 << endl;
  cout << str3 << endl;

  str1 += str2;
  if(str1 == str3)
  {
    cout << "동일한 문자열" << endl;
  }
  else
  {
    cout << "다른 문자열" << endl;
  }

  String str4;
  cout << "문자열 입력 : ";
  cin >> str4;
  cout << "입력한 문자열 : " << str4 << endl;

  return 0;
}

결과



이렇게 구현할 수 있다.










------- Template (템플릿)


모형자라는 뜻이 담겨있는데 어떤 틀을 만드는 것이다.

아래 예제를 참고


예제)

#include <iostream>
#include <string>

using namespace std;

template <typename T>
T Add(T num1, T num2)
{
  return num1+num2;
}

int main()
{
  cout << Add<int>(1520<< endl;
  cout << Add<double>(0.51.0<< endl;
  cout << Add<int>(3.12.2<< endl;
  cout << Add<double>(5.410.15<< endl;
  cout << Add<string>("Hi"" world"<< endl;

  return 0;
}

결과


template <typename "타입 이름">

이 타입을 적용할 변수 앞에 "타입 이름"을 적어서 사용한다.


이런식으로 다른 타입의 오버로딩 함수를 정의하지 않아도 짧게 코드를 작성할 수 있다.

컴파일 과정 중에 다른 타입의 함수를 컴파일러가 코드를 작성하여 넣어주기 때문에

프로그램의 크기가 더 작아지는 것은 아니다.





함수와 인수 사이에 <타입>을 넣어야 하는데, 만약 넣지 않으면 묵시적 변환이 일어난다.

다음 예제 확인


예제)

#include <iostream>
#include <string>

using namespace std;

template <typename T>
T Add(T num1, T num2)
{
  return num1+num2;
}

int main()
{
  cout << Add(1520<< endl;
  cout << Add(0.51.0<< endl;
  cout << Add(3.12.2<< endl;
  cout << Add(5.410.15<< endl;

  //cout << Add("Hi", " world") << endl;
  string obj1("Hi");
  string obj2(" world");
  cout << Add(obj1, obj2) << endl;

  return 0;
}

결과


위에서 보듯이 <타입>을 생략하면 뒤에 오는 타입에 맞게 묵시적으로 변환되기 때문에

의도치 않은 변환이 일어날 수도 있다.




만약 오버로딩 함수와 템플릿 함수를 함께 정의해 놓았을 경우는 어떻게 될까?

아래 예제 참고

예제)

#include <iostream>

using namespace std;

template <typename T>
T Add(T num1, T num2)
{
  cout << "T Add(T num1, T num2)" << endl;
  return num1 + num2;
}

int Add(int num1, int num2)
{
  cout << "Add(int num1, int num2)" << endl;
  return num1 + num2;
}

double Add(double num1, double num2)
{
  cout << "Add(double num1, double num2)" << endl;
  return num1 + num2;
}

int main()
{
  cout << Add(57<< endl;
  cout << Add(3.77.5<< endl;
  cout << Add<int>(57<< endl;
  cout << Add<double>(3.77.5<< endl;

  return 0;
}

결과


이렇듯 겹치게 되면 확실하게 해야한다.








설정

트랙백

댓글

20141029 (C++ ()연산자와 Functor(펑터), ARM SAM-BA)

168일차




--------

C++

--------



------- 연산자 ()와 Functor(펑터)


객체를 함수처럼 사용하는 것을 말한다.

다음 예제로 확인


예제)

#include <iostream>


using namespace std;


class Point

{

private:

int xpos;

int ypos;


public:

Point(int x = 0, int y = 0) : xpos(x), ypos(y)

{ }


Point operator+(const Point& pos) const

{

return Point(xpos + pos.xpos, ypos + pos.ypos);

}


friend ostream& operator<<(ostream& os, const Point& pos);

};


ostream& operator<<(ostream& os, const Point& pos)

{

cout << "[" << pos.xpos << ", " << pos.ypos << "]" << endl;

return os;

}


class Adder

{

public:

int operator()(const int& n1, const int& n2)

{

return n1 + n2;

}


double operator()(const double& n1, const double& n2)

{

return n1 + n2;

}


Point operator()(const Point& n1, const Point& n2)

{

return n1 + n2;

}

};


int main()

{

Adder adder;


cout << adder(1, 3) << endl;

cout << adder(1.5, 1.7) << endl;

cout << adder(Point(3,4), Point(7, 7));


return 0;

}




객체를 함수처럼 사용하는 것을 Functor라고 부른다.

또 다른 예제


예제)

#include <iostream>


using namespace std;


class SortRule              // 추상 클래스

{

public:

virtual bool operator()(int num1, int num2) const = 0;        // 순수 가상함수

};


class AscendingSort : public SortRule

{

public:

bool operator()(int num1, int num2) const

{

if(num1 > num2)

return true;

else

return false;

}

};


class DescendingSort : public SortRule

{

public:

bool operator()(int num1, int num2) const

{

if(num1 < num2)

return true;

else

return false;

}

};


class DataStorage

{

private:

int * arr;

int idx;

const int MAX_LEN;


public:

DataStorage(int arrlen) : idx(0), MAX_LEN(arrlen)

{

arr = new int[MAX_LEN];

}


void AddData(int num)

{

if(MAX_LEN <= idx)

{

cout << "더 이상 저장이 불가능합니다." << endl;

return;

}

arr[idx++] = num;

}


void ShowAllData()

{

for(int i= 0; i < idx; ++i)

{

cout << arr[i] << " ";

}

cout << endl;

}


void SortData(const SortRule& functor)

{

for(int i = 0; i < (idx - 1); ++i)

{

for(int j = 0; j < (idx - 1); ++j)

{

if(functor(arr[j], arr[j+1]))

{

int temp = arr[j];

arr[j] = arr[j + 1];

arr[j + 1] = temp;

}

}

}

}

};


int main()

{

DataStorage storage(5);


storage.AddData(40);

storage.AddData(30);

storage.AddData(50);

storage.AddData(20);

storage.AddData(10);


storage.SortData(AscendingSort());

storage.ShowAllData();


storage.SortData(DescendingSort());

storage.ShowAllData();


return 0;

}

결과



이렇게 사용한다.




















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

ARM

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



------- SAM-BA


ARM에 프로그램을 올려줄 때 SAM-BA를 사용한다.

현재 실습용 장비인데,

항상 프로그램을 넣어주기 전에 TST를 켜고 POWER을 켜서

안에 프로그램을 지워주고, PC와 연결하여 프로그램을 넣었다.


그 구동 원리는


(Memory)


칩 내부에 SAM-BA 프로그램이 저장되어 있어,

TST를 켜면 SAM-BA 프로그램이 Flash에 저장되고,

Windows와 통신이 가능하게 되면서 프로그램을 넣을 수 있게 되는 것이었다.



설정

트랙백

댓글

20141028 (C++ new, delete, *, -> 연산자 오버로딩, ARM 소스변환)

167일차






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

C++

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



------- 생성자


- 다음 예제 확인


소스)

class AAA

{

private:

int num;

public:

AAA(int n=0): num(n)

{  

cout<<"AAA(int n=0) : " << num <<endl;

}

};


int main(void)

{

AAA obj1(12);

// AAA buff(); // error, 인수가 있는 생성자를 호출하는데 아무 값도 안넣어서 warning.

AAA buff; // ok, 기본 생성자를 호출하였는데, 값이 없으니 기본으로 num에 0이 들어간다.

AAA * temp = new AAA;


delete temp;


return 0;

}

결과




주석 처리된 부분을 컴파일하면 아래와 같은 warning이 뜬다.

warning C4930: 'AAA buff(void)': 프로토타입 함수가 호출되지 않았습니다. 변수 정의로 사용하려고 한 것은 아닌지 확인하십시오.






- 또 비슷한 다른 예제

소스)
class AAA
{
private:
int num;

public:
AAA(int n=0): num(n)
{  
cout << "AAA(int n=0) : " << num <<endl;
}

AAA(const AAA &ref): num(ref.num)
{  
cout << "AAA(const AAA & ref)" << endl;
}

AAA & operator=(const AAA &ref)
{
num = ref.num;
cout << "operator=(const AAA &ref) : " << num <<endl;
return *this;
}

~AAA()
{
cout << "bye~ : " << num << endl;
}

void change()
{
num = 100;
cout << "num = " << num << endl;
}
};

int main(void)
{
AAA obj1(12); // num에 12 값인 obj1 생성

obj1 = 10; // 연산자= 호출됨, num에 10 값인 임시 객체가 생성되어 obj1에 값이 복사된다.
obj1.change(); // 임시 객체와 obj1을 분간하기 위해 넣음.

return 0;
}
결과











------- 어제한 소스

- 이 경우는 new로 heap에 할당 받은 경우.
BoundCheckPointPtrArray arr(3);
arr[0] = new Point(3, 4);
arr[1] = new Point(5, 6);
arr[2] = new Point(7, 8);

- 이 경우는 stack에 할당 받은 경우.
BoundCheckPointArray arr(3);
arr[0] = Point(3, 4);
arr[1] = Point(5, 6);
arr[2] = Point(7, 8);

둘 중에 heap에 할당 받는 것이 더 빠르다.
stack에 할당 받을 경우, 임시객체가 발생해서 할당 받고, 복사해 주기 때문에 더 느려지고,
heap에 할당 받으면, 할당 받고, 주소만 받기 때문에 더 효율적이다.













------- new, delete 연산자 오버로딩


new, delete 연산자도 오버로딩이 가능하다.


우선 new 연산자가 하는 일은 다음과 같다.

1. 메모리 공간의 할당

2. 생성자의 호출

3. 할당하고자 하는 자료형에 맞게 반환된 주소 값의 형 변환


객체가 아직 만들어지지 않았는데, 이 연산자가 호출이 된다는 것은

static으로 선언됐다.


예제)

class Point

{

private:

int xpos;

int ypos;


public:

Point(int x = 0, int y = 0) : xpos(x), ypos(y)

{

cout << "Point()" << endl;

}


friend ostream& operator<<(ostream& os, const Point& pos);


void * operator new (size_t size) //new 연산자 오버로딩

{

cout << "operator new : " << size << endl;

void * adr = new char[size];

return adr;

}


void operator delete (void * adr) //delete 연산자 오버로딩

{

cout << "operator delete ()" << endl;

delete []adr;

}

};


ostream& operator<<(ostream& os, const Point& pos)

{

os << "[" << pos.xpos << ", " << pos.ypos << "]" << endl;

return os;

}


int main()

{

Point * ptr = new Point(3, 4);

cout << *ptr;

delete ptr;

return 0;

};

결과


new 연산자가 실행되는 순서와 결과에 나오는 순서가 같다.

1. 메모리 할당

2. 생성자

3. 주소값 변환


이렇게 new, delete도 연산자 오버로딩이 가능하다.

또 다음과 같이 오버로딩이 가능하다.


예제)

class Point

{

private:

int xpos;

int ypos;


public:

Point(int x = 0, int y = 0) : xpos(x), ypos(y)

{

cout << "Point()" << endl;

}


friend ostream& operator<<(ostream& os, const Point& pos);


void operator new (size_t size) //new 연산자 오버로딩

{

cout << "operator new : " << size << endl;

void * adr = new char[size];

return adr;

}


void operator new[] (size_t size) //new[] 연산자 오버로딩

{

cout << "operator new[] : " << size << endl;

void * adr = new char[size];

return adr;

}


void operator delete (void * adr) //delete 연산자 오버로딩

{

cout << "operator delete ()" << endl;

delete []adr;

}


void operator delete[] (void * adr) //delete[] 연산자 오버로딩

{

cout << "operator delete[] ()" << endl;

delete []adr;

}

};


ostream& operator<<(ostream& os, const Point& pos)

{

os << "[" << pos.xpos << ", " << pos.ypos << "]" << endl;

return os;

}


int main()

{

Point * ptr = new Point(3, 4);

cout << *ptr;

delete ptr;

return 0;

};

결과



이렇게 new, delete 연산자도 오버로딩이 가능하다.









------- *, -> 연산자 오버로딩


*, ->도 오버로딩이 가능하다.

다음 예제 확인


예제)

class Number

{

private:

int num;


public:

Number(int n) : num(n) { }

void ShowData()

{

cout << "ShowData : " << num << endl;

}


Number * operator->()

{

cout << "->" << endl;

return this;

}


Number& operator*()

{

cout << "*" << endl;

return *this;

}

};


int main()

{

Number num(20);

num.ShowData();


(*num) = 30;

num->ShowData();

(*num).ShowData();


cout << "********************" << endl;


( num.operator*() ).ShowData(); // (*num).ShowData()이 이렇게 해석된다.

num.operator->()->ShowData(); // num->ShowData()이 이렇게 해석된다.


return 0;

}

결과











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

ARM

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



------- 소스 변환


예제)

//#include "myAT91SAM7S256.h"

#include "AT91SAM7S256.h"


int main()

{

//PMC_PCER = (1<<2);


//PIO_PDR = 0xFFFFFFFF;

//PIO_PER = PA0|PA1; // Port Enable PA0~1

//PIO_OER = PA1; // PA1 is Output

//PIO_ODR = PA0; // PA0 is Input


//-> 위에 소스를 아래처럼 변환

AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA);

AT91C_BASE_PIOA->PIO_PDR = 0xFFFFFFFF;

AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA0 | AT91C_PIO_PA1;

AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA1;

AT91C_BASE_PIOA->PIO_ODR = AT91C_PIO_PA0;



while (1)

{


// if PA0 were Hi

if(AT91C_PIO_PA0 == (AT91C_BASE_PIOA->PIO_PDSR & AT91C_PIO_PA0 ))

{

// then PA1 out is Hi

AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA1;

}

// if PA0 were Lo

else 

{

// then PA1 out is Lo

AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA1;

}


}

return 0;

}








설정

트랙백

댓글

20141027 (C++ 객체 초기화, 대입연산자, 배열 연산자, ARM ADS)

166일차










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

C++

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







------- 객체 초기화


객체를 초기화하는 방법이 두 가지 있습니다.

다음 예제 확인


예제)

//ImproveInit.cpp

#include <iostream>


using namespace std;


class AAA

{

private:

int num;


public:

AAA(int n = 0) : num(n) // default 생성자

{

cout << "AAA(int n = 0)" << endl;

}


AAA(const AAA& ref) : num(ref.num) // 받은 인자로 초기화하는 생성자

{

cout << "AAA(const AAA& ref)" << endl;

}


AAA& operator=(const AAA& ref) // 대입 연산자

{

num = ref.num;

cout << "operator=(const AAA& ref)" << endl;

return *this;

}

};


class BBB

{

private:

AAA mem;


public:

BBB(const AAA& ref) : mem(ref) // 생성자로 초기화

{

}

};


class CCC

{

private:

AAA mem;


public:

CCC(const AAA& ref)

{

mem = ref; // 대입 연산자로 초기화

}

};


int main()

{

AAA obj1(12);

cout << "*************************" << endl;


BBB obj2(obj1);

cout << "*************************" << endl;


CCC obj3(obj1);

cout << "*************************" << endl;


return 0;

}

결과



위의 결과 화면에서 확인할 수 있듯이,

생성자로 초기화한 것과, 대입 연산자로 초시화한 것이

속도 차이가 분명하다.


생성자로 초기화한 것은 한 번(생성자만 호출),

대입 연산자로 초기화한 것은 두 번(생성자, 대입 연산자 호출)

실행한다.











------- 대입 연산자, const


다음 예제를 보고 하겠습니다.


예제)

#include <iostream>

#include <cstdlib>


using namespace std;


class BoundCheckIntArray

{

private:

int * arr;

int arrlen;


BoundCheckIntArray(const BoundCheckIntArray& arr)

{ }

BoundCheckIntArray& operator=(const BoundCheckIntArray& ref)

{ }

public:

BoundCheckIntArray(int len) : arrlen(len) // 생성자

{

arr = new int[len];

}


int& operator[] (int idx) // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}

/*

int operator[] (int idx) const // 배열 연산자 (const, 오버로딩)

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}

*/

int GetArrLen() const

{

return arrlen;

}


~BoundCheckIntArray()

{

delete []arr;

}

};


void ShowAllData(const BoundCheckIntArray& ref)

{

int len = ref.GetArrLen();

for(int idx = 00; idx < len; ++idx)

{

cout << ref[idx] << endl; // 배열 연산자  호출

}

}


int main()

{

BoundCheckIntArray arr(5);


for(int i = 0; i<5; ++i)

{

arr[i] = (i+1) * 11;

}


ShowAllData(arr);


return 0;

}


이 예제는 컴파일 시, 에러입니다.

이유는 ShowAllData 함수에서 배열 연산자 호출하는 부분이 있는데,

인수로 받는 ref를 보시면 const로 선언이 된 것을 확인할 수 있습니다.

따라서 이 함수에서 ref 관련 호출할 수 있는 함수는 const로 선언되어야만

호출 가능합니다.


따라서 위에 주석을 제거하면 operator= 이 const로 오버로딩되어

정상적으로 동작하게 됩니다.














------- 배열 연산자


아래 예제를 봅시다.


예제)

#include <iostream>

#include <cstdlib>


using namespace std;


class Point

{

private:

int xpos;

int ypos;


public:

Point(int x = 0, int y = 0) : xpos(x), ypos(y)

{ }

friend ostream& operator<<(ostream& os, const Point& pos); // << 연산자 friend

};


ostream& operator<<(ostream& os, const Point& pos) // << 연산자 정의

{

os << '[' << pos.xpos << ", " << pos.ypos << "]" << endl;

return os;

}



class BoundCheckPointArray

{

private:

Point * arr;

int arrlen;


BoundCheckPointArray(const BoundCheckPointArray& arr)

{ }

BoundCheckPointArray& operator=(const BoundCheckPointArray& arr)

{ }


public:

BoundCheckPointArray(int len) : arrlen(len) // 생성자

{

arr = new Point[len]; // 멤버 변수 arr 메모리 할당

}


Point& operator[](int idx) // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}


Point operator[] (int idx) const // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}


int GetArrLen() const

{

return arrlen;

}

~BoundCheckPointArray()

{

delete []arr;

}

};


int main()

{

BoundCheckPointArray arr(3);


arr[0] = Point(3, 4);

arr[1] = Point(5, 6);

arr[2] = Point(7, 8);


for(int i = 0; i < arr.GetArrLen(); ++i)

{

cout << arr[i];

}


return 0;

}

결과



이 소스에서

arr[0] = Point(3, 4);

명령이  배열연산자에 의해 실행되는 과정을 보면


1. Point 객체 생성 (생성자에 의해 객체 멤버 값은 xpos = 3, ypos = 4)


Point(int x = 0, int y = 0) : xpos(x), ypos(y)



2. arr[0]   ==  arr.operator[](0)   그래서 []함수? 호출


Point& operator[](int idx) // 배열 연산자

{

if(idx < 0 || idx >= arrlen)

{

cout << "Array index out of bound exception" << endl;

exit(1);

}

return arr[idx];

}



3. return 값이 Point& 형이므로 결국 arr.arr[0] 변수를 가리키므로

arr.arr[0]에 값이 대입된다.















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

ARM

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




------- ARM ADS


ARM Developer Suite 라는 줄임말로 ARM 사에서 제작한 유료 C컴파일러

현재는 단종되었다고 합니다.




---- 설치법


- SETUP.EXE를 실행
















- 설치가 끝나면 아래 라이센스 관련 창이 뜹니다.







- 설치 파일이 있던 곳에 가면 CRACK이란 폴더에 위치하고 있습니다.






- 다음과 같은 결과가 보이면 다음으로 갑니다.








- 설치가 완료되면 바탕화면에 바로가기가 생성되지 않기 때문에

C:\Program Files\ARM\ADSv1.2\Bin 으로 가서 IDE.exe 바로가기를 만드셔서 사용하시거나

시작 -> Programs -> ARM Developer Suite v1.2 -> CodeWarrior for ARM Developer Suite 실행하면 됩니다.




- cmd 창에서 버전 확인


ARM 사에서는 문제점들을 보완한 패치버전을 계속해서 내어놓고 있었다고 합니다.

최신 버전으로 업데이트하는 방법을 알아볼 예정인데요

http://www.arm.com/support/downloads/info/4554.html 에서 받을 수 있다는데

현재는 지원이 끝났나 봅니다.


그런데 구하기 쉽더군요ㅋㅋㅋㅋ

4554_ADS12_848_Windows.exe




- 아래와 같이 실행



- 버전이 상승된 걸 확인할 수 있습니다.








---- 실행법


- 먼저 실행하기 전에 예제 파일을 받아옵니다.

http://cpu.kongju.ac.kr/frame3.htm 에 가셔서

책 관련 자료실 -> 166번 게시글 (ADS v1.2용의 C언어 예제 파일)

예제 파일을 받아 ADS 가 설치 된 곳에 함께 둡니다.




- IDE.exe 나 시작프로그램에 CodeWarrior... 실행










- ADS v1.2용 C언어 예제 프로그램에서 항상 공통적으로 사용하는 스타트업 파일이 3개 있는데, 이것들을

하나의 그룹으로 묶어서 등록하여 두면 편리하므로 그룹을 생성합니다.







- Cstartup.s 열기





- 나머지 두 파일도 추가








- 이제 실행할 예제 소스를 추가합니다.



- Xtest01_1.c


소스 내용은


#include "AT91SAM7S256.h"

#include "lib_AT91SAM7S256.h"

#include "OK7S256ads.h"


int main(void)

{

  MCU_initialize(); // initialize AT91SAM7S256 & kit


  while(1)

    { Beep(); // beep 


      LED_on(LED1); // LED1 on 

      Delay_ms(1000);

      LED_off(LED1); // LED1 off

      Delay_ms(1000);

      

      LED_on(LED2); // LED2 on 

      Delay_ms(1000);

      LED_off(LED2); // LED2 off

      Delay_ms(1000);

      

      LED_on(LED2|LED1); // LED2 and LED1 on 

      Delay_ms(1000);

      LED_off(LED2|LED1); // LED2 and LED1 off

      Delay_ms(1000);

    }

}

로 LED 2개를 껐다 켰다 합니다.



- 여기까지 새로운 프로젝트 Test.mcp가 만들어지고 여기에 3개의 스타트업 파일과 사용자 프로그램을 등록 완료하였습니다.



- Tip> 프로젝트에서는 타겟을 기본적으로 DebugRel 폴더로 지정한다. Debug 폴더로 하면 최종 출력 파일에

          디버그 정보를 포함하는데 주력하며 최적화 기능은 희생되는데 비해 Release 폴더로 하면 반대로 최

          적화 기능에 주력하고 디버그 정보는 포함하지 않는다. 그러나, DebugRel 폴더로 지정하면 이것들의

          중간 정도로 처리된다.



- 새로운 프로젝트의 환경 설정

    프로젝트의 프로그래밍 환경설정을 시작하려면 프로젝트 창에서 DebugRel Settings.. 아이콘을 누르거나

  Edit탭의 DebugRel Settings... 메뉴를 선택하거나 Alt+F7단축키를 이용합니다.











- 위에 혹시나 잘 안보이는 글자는 " 0x00000000 ", " 0x00200000 " 입니다.










- 에디터를 사용할 때, 탭 간격 조절






사용자 프로그램을 더블클릭하게 되면 파일 내용을 볼 수 있습니다.

- 컴파일은 프로젝트 창에서 사용자 프로그램을 오른쪽 마우스 클릭하고 Compile을 누르고,

- 컴파일 및 링크를 수행하려면 프로젝트 창에서 Make 아이콘을 누르거나 메인화면에 있는 Make아이콘을

   눌러도 되며, Project탭에서 Make메뉴를 선택하거나 F7단축키를 이용하는 방법이 있습니다.




- 컴파일시 entry 가 없다고 warning?이 뜨던데, 삼바로 arm에 넣으면 잘 돌아갑니다ㅋㅋㅋㅋ

bin 파일 위치는 프로젝트 이름을 test로 했으니, 내문서 -> test -> test_Data -> DebugRel 에 있습니다.



출처 : http://alisa2304.tistory.com/35








------- Cstartup.s 소스 분석



;-------------------------------- ; <- 주석입니다.

;- ARM Core Mode and Status Bits

;--------------------------------

IRQ_STACK_SIZE EQU (3*8*4) ; 2 words per interrupt priority level

;요기는 #define과 같은 맥락으로

;IRQ_STACK_SIZE 는 (3*8*4)로 치환한다는 뜻이겠죠?


ARM_MODE_USER EQU 0x10

ARM_MODE_FIQ EQU 0x11

ARM_MODE_IRQ EQU 0x12

ARM_MODE_SVC EQU 0x13

ARM_MODE_ABORT EQU 0x17

ARM_MODE_UNDEF EQU 0x1B

ARM_MODE_SYS EQU 0x1F


I_BIT EQU 0x80

F_BIT EQU 0x40

T_BIT EQU 0x20


;------------------------------------------------------------------------------

;- Area Definition

;------------------------------------------------------------------------------

AREA  reset, CODE, READONLY ; 읽기전용, CODE 영역

ENTRY

EXPORT entry ; entry를 외부에 보이게.


...


entry

B InitReset ; 0x00 Reset handler

; B 는 jmp 와 같은 명령으로 InitReset으로 가볼까요?

undefvec

B undefvec ; 0x04 Undefined Instruction

...



;--------------------

;- The reset handler

;--------------------

InitReset ; 여기까지 날아왔습니다~

...

IMPORT AT91F_LowLevelInit ; 외부에서 저 함수를 가져온다는 명령.


;- minimum  C initialization

ldr r13,=0x00204000 ; temporary stack in internal RAM

; ldr은 LoaD Register라는 명령으로 r13 Reg 에 0x00204000 값을 넣습니다.

ldr r0,=AT91F_LowLevelInit

; r0 Reg 에 함수 주소?를 넣었어요

mov lr, pc

bx r0

; bx 는 실행, 분기 기능으로 r0에 있는 것을 실행한다는 뜻이니 AT91F_LowLevelInit 을 실행합니다.




- AT91F_LowLevelInit은 Cstartup_SAM7.c 에 정의되어 있습니다.


void AT91F_LowLevelInit(void)

{

  int i;

  AT91PS_PMC pPMC = AT91C_BASE_PMC;

...





오늘은 여기까지... 얼마 남지 않은 시간. 무어싰게 열심히 마무리 합시다!!!

설정

트랙백

댓글

PCB 설계/제작/조립 관련 사이트

잡다 2014. 10. 27. 15:54

출처 : http://cpu.kongju.ac.kr/ezboard/ezboard.cgi?db=room_website&action=read&page=3&num=75&dbf=200106060000&depth=0



*** PCB 소프트웨어 ***

1. Mentor Graphics
   http://www.mentor.com/products/pcb/pads/
   http://www.mentorkr.com/

2. PADS
    http://www.ednc.com/

3. CADSTAR
    http://www.dmss.co.kr/cadstar/

4. CSiEDA
    http://www.csieda.net/

5. Graphicode(무료 거버뷰어 프로그램 제공)
    http://www.graphicode.com/

*** PCB 설계 ***

1. Korea PCB Designer Group
    http://www.pcb.pe.kr/

2. CADROOM
    http://www.cadroom.co.kr/

3. 코리아 캐드 디자인
    http://www.padspcb.co.kr/

4. CAD Korea
    http://www.cadkorea.net/

*** PCB 제작 ***

1. 한샘 디지텍
    http://www.hsdgt.com/

2. 유림 일렉트론
    http://www.ylpcb.co.kr/

3. 재인서키트
    http://jipcb.co.kr/

4. 하영전자
    http://www.hy-e.co.kr/

5. 아프로젠
    http://www.aprogen.net/

6. 경진전자산업
    http://www.kjpcb.com/

7. 에프엠씨전자
    http://www.pcbfamily.co.kr/

8. 마이캠
    http://www.mymycam.com/

9. 다우테크
    http://www.dawootech.kr/

*** PCB 가공기 ***

1. SME 교역
    http://www.npcb.co.kr/

*** 조립 ***

1. SMT 맨
    http://www.smtman.com/

*** PCB Artwork 용역 ***

1. Real PCB
    http://www.realpcb.wo.to/

*** 기타 ***

1. PCB Information Korea
    http://www.pcbinfo.co.kr/

'잡다' 카테고리의 다른 글

arm 내장 함수  (0) 2015.01.19
stm32F10x Standard Peripherals Library  (0) 2015.01.12
C++ Reference, Pointer  (0) 2014.10.13
microangel 마우스 커서, 아이콘 제작 툴  (0) 2014.09.16
map  (0) 2014.09.13

설정

트랙백

댓글

ARM 컴파일 안될 시....

Embedded 2014. 10. 23. 16:37

C:\cygwin\bin; 을 환경변수 가장 앞으로 보낼 것

'Embedded' 카테고리의 다른 글

embedded 기초 강좌 관련 사이트  (0) 2014.09.02
makefile만들기, interrupt 전처리 과정  (0) 2014.06.18

설정

트랙백

댓글

Ethernet, IP, TCP, UDP Frame

통신/TCP_IP 2014. 10. 15. 14:23

------- Ethernet과 IP, TCP, UDP Header









------- Ethernet Frame


Ethernet frame은 다음과 같이 몇몇 타입이 있다.

- Ethernet II

- IEEE 802.3

- IEEE 802.2 Logical Link Control (LLC) frame

- IEEE 802.2 Subnetwork Access Protocol (SNAP) frame



--- Ethernet II


DEC, Intel, and Xerox에 의해 만들어졌으며,

DIX Ethernet 이라고도 불린다


첫 번째 필드엔 목적 MAC주소, 

두 번재 필드엔 보낸 MAC주소,

세 번째 필드엔 Ether type이라고 Ethernet 프로토콜 타입,

네 번째 필드엔 정보,

다섯 번째 필드엔 CRC(cyclic redundancy check) 또는 FCS(Frame Check Sequence)라고

오류 검출에 쓰인다.


(출처 : http://en.wikipedia.org/wiki/Ethernet_frame)






--- IEEE 802.3


Novell 사에서 IPX protocol용으로 만들어졌다.

Ethernet II와 흡사한 구조로 세 번재 필드인 EtherType 대신 Length 이다.







--- IEEE 802.2 Logical Link Control (LLC) frame


OSI 계층 구조에서만 사용하는 Frame으로 거의 사용하지 않는다.

토큰링이 이 구조를 사용한다.







--- IEEE 802.2 Subnetwork Access Protocol (SNAP) frame


OSI 계층 구조에서 사용한다. TCP/IP가 주류므로 OSI는 잘 사용하지 않는다.

AppleTalk이 이 구조를 사용한다.









--- IEEE 802.1Q tag

VLAN (virtual local area network) 서비스에 대한 규약으로 Ethernet frame 들에 포함하고 있는데,

데이타 링크 계층(TCP/IP) or 네트워킹 계층(OSI)인 라우터나 스위치 등에서 운영되는 것으로,

브로드캐스트 필터링, 보안, 주소 축약, 트래픽 흐름 관리, QoS 등에 사용된다고 한다.


VLAN은 Ethernet frame에 Source Address 와 EtherType 또는 Length fields 사이에 위치하고 있거나,

EtherType 또는 Length fields 에 위치하고 있다.

처음 2 byte (2 octets)에는 Tag Protocol Identifier (TPID) 값이 0x8100으로 되어 있다.









------- Ethernet Frame 구조체


linux 환경

/usr/include/linux/if_ether.h

/usr/include/net/ethernet.h

위치에서 확인할 수 있다




struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ unsigned short h_proto; /* packet type ID field */ };



struct ether_header { u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ u_int16_t ether_type; /* packet type ID field */ };





--- 데이터 타입은

/usr/include/i386-linux-gnu/sys/types.h 에 있다.





--- ETH_ALEN 값은

/usr/include/linux/if_ether.h 에 있다.






--- type의 종류는

/usr/include/net/ethernet.h 에 있다.

더 많은 type은 /usr/include/linux/if_ether.h를 참고...














------- IP Header 구조체


http://en.wikipedia.org/wiki/IPv4 참고


/usr/include/netinet/in.h 에 프로토콜에 타입

/usr/include/netinet/ip.h 에 IP구조체가 정의 되어 있다



struct iphdr

{

#if __BYTE_ORDER == __LITTLE_ENDIAN

unsigned int  ihl:4;        //헤더 길이

unsigned int version:4;        //IP version 4

#elif __BYTE_ORDER == __BIG_ENDIAN

unsigned int version:4;        //IP version 4

unsigned int  ihl:4;        //헤더 길이

#else

# error "Please fix <bits/endian.h>"

#endif

u_int8_t    tos;

u_int16_t    tot_len;

u_int16_t    id;

u_int16_t    frag_off;

u_int8_t    ttl;

u_int8_t    protocol;

u_int16_t    check;

u_int32_t    saddr;

u_int32_t    daddr;

/* The options start here. */

};







------- TCP Header 구조체



/usr/include/netinet/tcp.h

/usr/include/linux/tcp.h

에 위치해 있다.


struct tcphdr

{

u_int16_t    source;        //source port

u_int16_t    dest;        //destination port

u_int32_t    seq;          //sequence number

u_int32_t    ack_seq;          //acknowledgement number

#if __BYTE_ORDER == __LITTLE_ENDIAN

u_int16_t    res1:4;           //(unused)

u_int16_t    doff::4;           //data offset

u_int16_t    fin:1;

u_int16_t    syn:1;

u_int16_t    rst:1;

u_int16_t    psh:1;

u_int16_t    ack:1;

u_int16_t    urg:1;

u_int16_t    res2:2;

#elif __BYTE_ORDER == __BIG_ENDIAN

u_int16_t    doff::4;           //data offset

u_int16_t    res1:4;           //(unused)

u_int16_t    res2:2;           //(unused)

u_int16_t    urg:1;

u_int16_t    ack:1;

u_int16_t    psh:1;

u_int16_t    rst:1;

u_int16_t    syn:1;

u_int16_t    fin:1;

#else

#error "Adust your <bits/endian.h> defines"

#endif

u_int16_t    window;        //window

u_int16_t    check;       //checksum

u_int16_t    urg_ptr;        //urgent pointer

};














'통신 > TCP_IP' 카테고리의 다른 글

HTTP 3핸드 쉐이킹 캡쳐  (0) 2020.10.12
TCP/IP 4 계층  (0) 2014.10.15

설정

트랙백

댓글

TCP/IP 4 계층

통신/TCP_IP 2014. 10. 15. 12:17


------- TCP/IP 4계층과 OSI 7계층




- TCP/IP 4계층은 인터넷 모델이라고도 한다.


 레벨

 계층

 기능

 4계층

 Application

응용 계층

프로토콜 : HTTP, FTP, Telnet, DNS, SMTP

OSI 7계층의 5, 6, 7계층에 해당한다.

TCP/IP 기반의 응용프로그램을 구분할 때 사용한다.

 3계층

 Transport

전송 계층

프로토콜 : TCP, UDP

OSI 7계층의 4계층에 해당한다.

통신 노드 간의 연결을 제어하고, 자료의 송수신을 담당한다.

 2계층

 Internet

인터넷 계층

프로토콜 : IP, ARP, RARP, ICMP, OSPF

OSI 7계층의 3계층에 해당한다.

통신 노드 간의 IP 패킷을 전송하는 기능 및 라우팅 기능을 담당한다.

 1계층

 Network Interface

네트워크 인터페이스 계층

프로토콜 : Ehternet, Token Ring, PPP

OSI 7계층의 1, 2 계층에 해당한다.

CSMA/CD, MAC, LAN, X.25, 패킷망, 위성 통신, 다이얼 업 모뎀 등 전송에 사용된다.

 


'통신 > TCP_IP' 카테고리의 다른 글

HTTP 3핸드 쉐이킹 캡쳐  (0) 2020.10.12
Ethernet, IP, TCP, UDP Frame  (0) 2014.10.15

설정

트랙백

댓글

20141015 (C++ class 내에 const static, mutable, 상속, )

158일차







-----------

C++

-----------




------- const static 멤버


class 내에 선언된 const static 멤버는 class 내에서 초기화를 한다.


예제)

#include <iostream>


using namespace std;


class CountryArea

{

public:

const static int RUSSIA = 1707540; // class 내에서 초기화

const static int CANADA = 998467; // class 내에서 초기화

const static int CHINA = 957290; // class 내에서 초기화

const static int SOUTH_KOREA = 9922; // class 내에서 초기화

};


int main(void)

{

cout << "러시아 면적: " << CountryArea::RUSSIA << "㎢" << endl;

cout << "캐나다 면적: " << CountryArea::CANADA << "㎢" << endl;

cout << "중국 면적: " << CountryArea::CHINA << "㎢" << endl;

cout << "한국 면적: " << CountryArea::SOUTH_KOREA << "㎢" << endl;


return 0;

}









------- mutable


const 함수 내에서 예외적으로 값 변경을 허용하는 키워드


예제)

#include <iostream>


using namespace std;


class SoSimple

{

private:

int num1;

mutable int num2;


public:

SoSimple(int n1, int n2) : num1(n1), num2(n2)

{

}


void ShowSimpleData() const

{

cout << num1 << ", " << num2 << endl;

}


void CopyToNum2() const

{

num2 = num1; // const 변수인데 값 수정 가능

}

};


int main()

{

SoSimple sm(1, 2);


sm.ShowSimpleData();

sm.CopyToNum2();

sm.ShowSimpleData();


return 0;

}



좋은 기능이지만 mutable을 사용하지 않는 편이 좋다









------- 상속


Ray 라는 class와 Tico라는 class를 만드는데,

바퀴, 엔진, 색상... 같은 변수는 공통적으로 들어간다.

비슷한 class를 만들 때마다 변수 목록을 복사 + 붙여넣기 하면 되지만,

번거롭다.....


그래서 상속이라는 것이 있는데, 공통적으로 반드시 들어가는 변수, 함수를 모아

Car 라는 class로 정의 하고 Ray, Tico 같은 class에서 상속만 받으면 된다.


상속 받는 법은 아래 예제를 참고한다.


예제)

#include <iostream>

#include <cstring>


using namespace std;


class Car

{

public: // 생략시 private

int Tire;

int Eng;

int Handle;

char Color[100];


public:

void Print()

{

cout << "Tire\t: " << Tire << endl;

cout << "Color\t: " << Color << endl;

}

};

// Car class 가 결함이 있다면

// 상속 받는 다른 class도 다 결함을 갖는다


class Ray : public Car // 상속 받음

{

};


class Tico : public Car // 상속 받음

{

};


int main()

{

Ray MyCar1;

Tico MyCar2;


MyCar1.Tire = 4; // 상속을 받으면 상위 class의 멤버

MyCar2.Tire = 4; // 자신의 멤버처럼 사용할 수 있다.


strcpy(MyCar1.Color, "PINK"); // 상속을 받으면 상위 class의 멤버

strcpy(MyCar2.Color, "RED"); // 자신의 멤버처럼 사용할 수 있다.


MyCar1.Print(); // 상속을 받으면 상위 class의 멤버

MyCar2.Print(); // 자신의 멤버처럼 사용할 수 있다.


return 0;

}





공통적인 클래스를 부모 클래스라 부르고, 

부모 클래스의 멤버를 상속받는 클래스를 자식 클래스라고 한다.


부모, 자식 말고도 여러가지로 불리는데 아래와 같다.



아주 편리한 기능이지만 단점도 있다.

상위 클래스에 결함이 있다면 하위 클래스도 똑같이 물려 받게 된다.






























설정

트랙백

댓글