본문 바로가기
코스웨어/10년 스마트폰BSP

[BSP]업무일지-이상구-20100706

by 알 수 없는 사용자 2010. 7. 6.
728x90
반응형

ARM - 주기적인 시간간격 타이머(PIT)

 주기적인 시간간격 타미어(Periodic Interval Timer ; PIT)는 운영체제의 스케쥴러(Scheduler)에게 주기적인 인터럽트를 발생시키기 위하여 사용하는 타이머이다. 시간의 정확성을 높이기 위하여 슬로우 클록이 아니라 마스터 클록을 사용하여 카운터가 동작한다.

 PIT는 마스터 클록을 16분주한 MCK/16의 주파수로 동작하며, 20비트 증가형 카운터 CPIV와 12비트 증가형 카운터 PICNT로 구성된다. 이것이 동작하려면 PIT_MR 레지스터에서 PITEN 비트로 이를 인에이블시켜야 한다.

 20비트 카운터 CPIV는 0부터 증가하다가 PIT_MR 레지스터의 PIV 값에 이르게 되면 그 다음 주기에서 동작으로 0으로 클리어 되면서 12비트 카운터 PICNT를 1만큼 증가시키게 되며, 이때 인터럽트를 요청할 수 있다. 따라서, 인터럽트 주기는 PIV+1클록 사이클이 되며, 여기서 실제로 인터럽트를 요청할지는 여부는 PIT_MR 레지스터의 PITIEN 비트로 설정한다.

 PIT_MR 레지스터의 PIV 값을 변경하기 위하여 새로 라이트하더라도 카운터를 리셋하거나 리스타트 하지 않는다.

 CPIV 값이나 PICNT 값을 확인하기 위하여 PIT_PIVR 레지스터를 읽으면 PICNT 값이 0으로 클리어되고 PIT_SR 레지스터의 PITS 비트도 클리어 되어 인터럽트 신호를 종료시킨다. (PIT_PIIR 레지스터는 그렇지 않다.)

어드레스 

옵셋 

레지스터 이름

엑세스 속성 

리셋후 초기값 

  0xFFFF_FD30

  0x00

   PIT_MR (PIT 모드 레지스터)

   read/write

   0x000F_FFFF

  0xFFFF_FD34

  0x04

   PIT_SR (PIT 상태 레지스터)

   read-only

   0x0000_0000

  0xFFFF_FD38

  0x08

   PIT_PIVR (PIT 카운터값 레지스터)

   read-only

   0x0000_0000

  0xFFFF_FD3C

  0x0C

   PIT_PIIR (PIT 이미지 레지스터)

   read-only

   0x0000_0000


실습 - PIT로 인터럽트 발생 LED 쉬프트 하기

//------------------------------------------------------------------------------------------------                              
//병렬 입출력 제어기(PIO) I/O 제어 레지스터
#define PIO_PER    (*(volatile unsigned int *) 0xFFFFF400) //PIO 병렬 입출력 허용 레지스터
#define PIO_PDR    (*(volatile unsigned int *) 0xFFFFF404) //PIO 병렬 입출력 금지 레지스터
#define PIO_OER    (*(volatile unsigned int *) 0xFFFFF410) //PIO 출력 허용 레지스터
#define PIO_ODR    (*(volatile unsigned int *) 0xFFFFF414) //PIO 출력 금지 레지스터
#define PIO_IFER  (*(volatile unsigned int *) 0xFFFFF420) //PIO 입력 필터 허용 레지스터
#define PIO_SODR  (*(volatile unsigned int *) 0xFFFFF430) //PIO 출력 데이터 세트 레지스터
#define PIO_CODR  (*(volatile unsigned int *) 0xFFFFF434) //PIO 출력 데이터 클리어 레지스터
#define PIO_IER    (*(volatile unsigned int *) 0xFFFFF440) //PIO 인터럽트 허용 레지스터
#define PIO_IDR    (*(volatile unsigned int *) 0xFFFFF444) //PIO 인터럽트 금지 레지스터
#define PIO_ISR    (*(volatile unsigned int *) 0xFFFFF44C) //PIO 인터럽트 상태 레지스터
#define PIO_PUDR  (*(volatile unsigned int *) 0xFFFFF460) //PIO 풀업저항 금지 레지스터
#define PIO_PUER  (*(volatile unsigned int *) 0xFFFFF464) //PIO 풀업저항 허용 레지스터
#define PIO_ASR    (*(volatile unsigned int *) 0xFFFFF470) //PIO 주변장치 A 선택 레지스터
#define PIO_BSR    (*(volatile unsigned int *) 0xFFFFF474) //PIO 주변장치 B 선택 레지스터
//------------------------------------------------------------------------------------------------
//전력관리 제어기(PMC) I/O 제어 레지스터
#define PMC_PCER  (*(volatile unsigned int *) 0xFFFFFC10)  //PMC 주변장치 클록 허용 레지스터
#define MASTERCLOCK 48000000
//------------------------------------------------------------------------------------------------                              
//인터럽트 제어기(AIC) I/O 제어 레지스터
#define AIC_SMR    ( (volatile unsigned int *) 0xFFFFF000)  //AIC 소스 모드 레지스터
#define AIC_SVR    ( (volatile unsigned int *) 0xFFFFF080)  //AIC 소스 벡터 레지스터
#define AIC_IECR  (*(volatile unsigned int *) 0xFFFFF120)  //AIC 인터럽트 허용 명령 레지스터
#define AIC_IDCR  (*(volatile unsigned int *) 0xFFFFF124)  //AIC 인터럽트 금지 명령 레지스터
#define AIC_ICCR  (*(volatile unsigned int *) 0xFFFFF128)  //AIC 인터럽트 클리어 명령 레지스터
//------------------------------------------------------------------------------------------------
//디버그 유닛(DBGU) I/O 제어 레지스터
#define DBGU_CR    (*(volatile unsigned int *) 0xFFFFF200) //DBGU 제어 레지스터
#define DBGU_MR    (*(volatile unsigned int *) 0xFFFFF204) //DBGU 모드 레지스터
#define DBGU_IER  (*(volatile unsigned int *) 0xFFFFF208) //DBGU 인터럽트 허용 레지스터
#define DBGU_IDR  (*(volatile unsigned int *) 0xFFFFF20C) //DBGU 인터럽트 금지 레지스터
#define DBGU_IMR  (*(volatile unsigned int *) 0xFFFFF210) //DBGU 인터럽트 마스크 레지스터
#define DBGU_SR    (*(volatile unsigned int *) 0xFFFFF214) //DBGU 상태 레지스터
#define DBGU_RHR  (*(volatile unsigned int *) 0xFFFFF218) //DBGU 수신홀딩 레지스터
#define DBGU_THR  (*(volatile unsigned int *) 0xFFFFF21C) //DBGU 송신홀딩레지스터
#define DBGU_BRGR  (*(volatile unsigned int *) 0xFFFFF220) //DBGU 보레이트 발생 레지스터
#define DBGU_CIDR  (*(volatile unsigned int *) 0xFFFFF240) //DBGU 칩 ID레지스터
#define DBGU_EXID  (*(volatile unsigned int *) 0xFFFFF244) //DBGU 칩 ID 확장 레지스터
#define DBGU_FNR  (*(volatile unsigned int *) 0xFFFFF248) //DBGU 강제 NTRST레지스터
//------------------------------------------------------------------------------------------------
//타이머 카운터(TC) I/O 제어 레지스터
#define TC0_CCR    (*(volatile unsigned int *) 0xFFFA0000) //TC0 채널 제어 레지스터
#define TC0_CMR    (*(volatile unsigned int *) 0xFFFA0004) //TC0 채널 모드 레지스터
#define TC0_CV    (*(volatile unsigned int *) 0xFFFA0010) //TC0 카운터 값 레지스터
#define TC0_RA    (*(volatile unsigned int *) 0xFFFA0014) //TC0 레지스터 A
#define TC0_RB    (*(volatile unsigned int *) 0xFFFA0018) //TC0 레지스터 B
#define TC0_RC    (*(volatile unsigned int *) 0xFFFA001C) //TC0 레지스터 C
#define TC0_SR    (*(volatile unsigned int *) 0xFFFA0020) //TC0 상태 레지스터
#define TC0_IER    (*(volatile unsigned int *) 0xFFFA0024) //TC0 인터럽트 허용 레지스터
#define TC0_IDR    (*(volatile unsigned int *) 0xFFFA0028) //TC0 인터럽트 금지 레지스터
#define TC0_IMR    (*(volatile unsigned int *) 0xFFFA002C) //TC0 인터럽트 마스크 레지스터
#define TC_BCR    (*(volatile unsigned int *) 0xFFFA00C0) //TC 블록 제어 레지스터
#define TC_BMR    (*(volatile unsigned int *) 0xFFFA00C4) //TC 블록 모드 레지스터
//------------------------------------------------------------------------------------------------
//주기적인 시간간격 타이머(PIT) I/O 제어 레지스터
#define PIT_MR    (*(volatile unsigned int *) 0xFFFFFD30) //PIT 모드 레지스터
#define PIT_SR    (*(volatile unsigned int *) 0xFFFFFD34) //PIT 상태 레지스터
#define PIT_PIVR  (*(volatile unsigned int *) 0xFFFFFD38) //PIT 카운터값 레지스터
#define PIT_PIIR  (*(volatile unsigned int *) 0xFFFFFD3C) //PIT 이미지 레지스터

void shift_LED() //1초마다 LED 쉬프트 함수
{
  static int i = 0;
  int temp;
  temp=PIT_PIVR; //PIT_PIVR 레지스터 읽어
                 //PITS비트 클리어
  i++;
  
  if(i==3//1초
  {
    PIO_CODR=1<<3;
    PIO_SODR=1<<0;
  }
  else if(i==6//2초
  {
    PIO_CODR=1<<0;
    PIO_SODR=1<<1;

  }
  else if(i==9//3초
  {
    PIO_CODR=1<<1;
    PIO_SODR=1<<2;

  }
  else if(i==12//4초
  {
    PIO_CODR=1<<2;
    PIO_SODR=1<<3;

    i=0;
  }
}


int main(void)
{
  AIC_SVR[1]=(unsigned int) shift_LED; //인터럽트 발생시 shift_LED()함수 호출
  AIC_IECR=1<<1//PIT, system
  PIT_MR=0xF4240|1<<24|1<<25;  //MCK/16/3=1/3초=백만|PIT인에이블|인터럽트 요청
          
  PIO_PER=0xF;
  PIO_OER=0xF;

  while(1)
  {
  }

  return 0;
}


C++ - 링크드 리스트 구조체를 클래스로 바꾸기

list.h
#ifndef LIST_H
#define LIST_H

// 하나의 데이타를 보관할 클래스
class Node
{
  // List 클래스에서 모든 멤버에
  // 접근할 수 있도록 만든다.
  friend class List;

public:
  Node* GetNext() const;
  Node* GetPrev() const;
  void* GetData() const;

private:
  Node* prev; // 이전 Node 구조체
  Node* next;  // 다음 Node 구조체
  void* data;  // 데이타에 대한 포인터
};

// 전체 리스트를 관리하는 클래스
class List
{
public:
  // 데이타 제거를 위한 함수의 포인터
  typedef void (*FN_DELETE)(void* );

public:
  List(FN_DELETE fnDelete = 0bool deleteData = true);
  ~List();

  void InsertNodeAfter(Node* node, void* data);
  void RemoveNode(Node* node);
  Node* GetHead() const;
  Node* GetTail() const;

  void RemoveAll();

private:
  Node* head;      // 헤드(더미) 노드
  bool deleteData;  // 리스트, 노드 제거시 데이터 제거 여부
  FN_DELETE fnDel;  // 데이타 제거시 호출할 함수
};

#endif

list.cpp
#include "list.h"

// 링크드 리스트의 생성자.
// fnDelete : 노드의 데이터 제거시 호출할 함수의 주소
// deleteData : true면 노드를 제거할 때 데이터도 제거한다.
List::List(FN_DELETE fnDelete, bool deleteData)
{
  // 인자를 보관한다.
  this->fnDel = fnDelete;
  this->deleteData = deleteData;

  // 헤드 노드를 만들고 초기화한다.
  head = new Node;
  head->prev = head;
  head->next = head;
  head->data = 0;
}

// 링크드 리스트의 소멸자
List::~List()
{
  // 모든 노드를 제거한다.
  RemoveAll();

  // 헤드 노드를 제거한다.
  delete head;
  head = 0;
}

// 리스트의 모든 노드를 제거한다. 
// 리스트의 모든 노드와 데이터도 제거한다.
void List::RemoveAll()
{
  // 헤드 노드의 다음 노드부터 지운다.
  // ( 이렇게 하면 RemoveAll() 함수를 호출한 후에도
  // List 객체를 다시 사용할 수 있다)
  Node* current = head->next;

  while(current != head)
  {
    // 현재 노드를 지울 것이므로
    // 다음 노드를 구해둔다.
    Node* next = current->next;

    // 현재 노드의 데이터를 제거한다.
    if (deleteData)
    {
      if (fnDel)
        (*fnDel)( current->data );
      else
        delete current->data;
    }

    // 현재 노드를 제거한다.
    delete current;

    // current가 다음 노드를 가리키게 한다.
    current = next;
  }

  // 헤드 노드를 초기화한다.
  head->next = head;
  head->prev = head;
}

// 첫번째 노드를 구한다.
// 반환값 : 리스트의 첫번째 노드
Node* List::GetHead() const
{
  // 헤드 노드를 반환한다.
  return head;
}

// 마지막 노드를 구한다.
// 반환값 : 리스트의 마지막 노드
Node* List::GetTail() const
{
  // 헤드 노드의 이전 노드를 반환한다.
  // (헤드 노드 자기 자신일 수도 있다.)
  return head->prev;
}

// 새로운 노드를 추가한다.
// node : 이 노드 뒤에 새 노드가 추가된다.
// data : 새 노드의 데이타
void List::InsertNodeAfter(Node* node, void* data)
{
  // 삽입되려는 곳의 앞, 뒤 노드를 구해놓으면
  // 읽기 쉬운 소스 코드를 만들 수 있다.
  Node* before = node;
  Node* after = node->next;

  // 새 노드를 만들고 초기화한다.
  Node* newNode = new Node;
  newNode->data = data;
  newNode->next = after;
  newNode->prev = before;

  // node의 뒤에 있던 노드가 새 노드를 가리키도록 만든다.
  after->prev = newNode;

  // 매개변수 node가 새 노드를 가리키도록 만든다.
  before->next = newNode;
}

// 노드를 제거한다.
// node : 제거할 노드
void List::RemoveNode(Node* node)
{
  // node의 앞, 뒤 노드를 구해놓으면
  // 읽기 쉬운 소스 코드를 만들 수 있다.
  Node* before = node->prev;
  Node* after = node->next;

  // node의 이전 노드와 다음 노드를 연결해준다.
  before->next = after;
  after->prev = before;

  // 현재 노드의 데이터를 제거한다.
  if (deleteData)
  {
    if (fnDel)
      (*fnDel)( node->data );
    else
      delete node->data;
  }

  // 현재 노드를 제거한다.
  delete node;
}

// 노드의 다음 노드를 반환한다.
// 반환값 : 다음 노드
Node* Node::GetNext() const
{
  return next;
}

// 노드의 이전 노드를 반환한다.
// 반환값 : 이전 노드
Node* Node::GetPrev() const
{
  return prev;
}

// 노드에 보관된 데이터를 반환한다.
// 반환값 : 보관된 데이타
void* Node::GetData() const
{
  return data;
}

Node와 List가 클래스로 바뀌었고 각각 관련된 함수와 변수들을 멤버로 만들었다.
Node 클래스의 모든 멤버 변수를 private로 만들고 List 클래스를 친구로 설정하여 Node 클래스의 외부에서는 멤버 변수에 접근하지 못하게 하고 오직 List클래스에서만 접근할수 있게 하였다. 즉, 실수로 Node 객체의 값이 바껴 문제가 발생하는것을 막을 수 있다.
728x90