본문 바로가기
코스웨어/13년 스마트컨트롤러

20130530 정리_진종영

by 알 수 없는 사용자 2013. 5. 30.
728x90
반응형

 

포팅(porting)

이식(移植) 또는 포팅(porting)은 컴퓨터 과학에서 실행 가능한 프로그램이 원래 설계된 바와 다른

컴퓨팅 환경(이를테면 CPU, 운영 체제, 서드 파티 라이브러리 등)에서 동작할 수 있도록 하는 과정을 가리킨다.

이 용어는 소프트웨어나 하드웨어가 다른 환경에서 사용할 수 있게 변경되는 것에도 해당한다. 소스 하나로

여러 플랫폼에서 사용할 수 있는 것을 크로스 플랫폼으로 부른다.

 

 

 

  BSD(Berkeley Software Distribution)는 1977년 미국 캘리포니아 대학교

  버클리(University of California, Berkeley)에서 개발한 유닉스 계열의 컴퓨터 운영 체제이다.

 NetBSD

 

NetBSD는 BSD 계열의 오픈 소스 운영 체제이다. 64비트 옵테론 서버 같은 최신 하드웨어 뿐 아니라 구식 하드웨어, 심지어 임베디드 시스템에 이르기까지 사용할 수 있을 정도로 폭넓은 이식성이 특징이다. NetBSD는 4.3BSD로부터 갈라져 나왔으며, 1995년 말에 OpenBSD가 NetBSD로부터 파생되었다.

NetBSD는 다양한 아키텍처로 이식되어, 같은 소스로부터 54가지 이상의 아키텍처용 바이너리를 만들 수 있다.

자체 패키지 시스템으로 6500개가 넘는 패키지를 제공하는 pkgsrc가 있다.

 FreeBSD

 

FreeBSD는 BSD 계열의 오픈 소스 운영 체제로서, 캘리포니아 대학교

버클리(UC Berkeley) CSRG(Computer Systems Research Group)의

4.4BSD 라이트를 바탕으로 개발되었다. 2011년 2월 현재 배포본은 FreeBSD 8.2이며,

기본적으로 x86 및 x86-64 기종을 중심으로 개발되고 있는데, 다른 주요 기종에도 이식되어 있다.

 

 PC-BSD

 FreeBSD에 기반한 유닉스 계열의 데스크톱용 운영 체제이다.

 

 DesktopBSD

 FreeBSD에 기반한 유닉스 계열의 데스크톱 지향 운영 체제이다.

 DragonFly BSD

(드래곤플라이 BSD)

 BSD계 운영 체제 가운데 하나로 FreeBSD-4.8에서 갈라져 나왔다.

1.4부터 pkgsrc를 기본 패키지 시스템으로 채택하고 있다.

전직 아미가 컴퓨터 프로그래머 매튜 딜론(Matthew Dillon)의 주도로 개발한다.

 

 

 OpenBSD

 

OpenBSD는 NetBSD에서 파생된 BSD 계열의 오픈 소스 운영 체제이다.

OpenBSD는 컴퓨터 보안 쪽으로 특화되어 개발하고 있으며, 현재 프로젝트는 Theo de Raadt가 이끌고 있다.

OpenBSD의 개발자들은 보안을 위해 소스 코드를 한줄 한줄 검사하는 것을 마다하지 않으며, 보안이 문제가 되는

부분들은 자체적인 구현으로 대체하기도 한다. 유명한 예로 OpenSSH와 OpenSSL, OpenNTPD 등이 있다.

다른 한가지 OpenBSD가 다른 오픈 소스 운영 체제들과 특화를 보이고 있는 것은, 어떠한 오류가 발생할지도

모르고, 오류가 발생하였을 경우 이를 직접 수정할 수 없는 바이너리 blob을 거부한다는 점이라고 할 수 있다.

다른 운영 체제들이 소스가 공개되어 있지 않은 여러 그래픽 카드와 네트워크 카드를 지원하기 위해 업체가

제공하는 바이너리 드라이버를 사용할 수 있도록 하는 것과는 반대로, 필요한 하드웨어의 드라이버를 업체에

스펙 문서를 요구하거나 직접 역공학을 하거나 혹은 다른 운영 체제에서 구현한 드라이버 소스를 참고로 하여

개발하여 제공한다. 이것은 OpenBSD를 더욱 신뢰할 수 있도록 해준다.

OpenBSD가 가장 널리 쓰이는 부분은 네트워크의 가장 중요한 부분이라 할 수 있는 게이트웨이와 방화벽이라

할 수 있다. 유연하고 강력한 패킷 필터링 도구인 pf가 이부분에서 상당한 공로를 하고 있는데, 이 패킷필터는

같은 BSD 계열인 FreeBSD와 NetBSD 뿐만 아니라 리눅스에도 포팅되어 있다.

 

다윈

(Darwin)

다윈(Darwin)은 2000년에 애플에서 만든 오픈 소스 유닉스 컴퓨터 운영 체제이다. 프리BSD와 다른 자유 소프트웨어

프로젝트뿐 아니라 넥스트스텝의 소스를 따라 애플에서 개발한 코드로 구성되어 있다.

다윈은 맥 OS X과 iOS를 기반으로 한 구성 요소를 형성하고 있다. 또, 독립형 운영 체제로 실행할 수도 있다.

단일 유닉스 규격 버전 3 (SUSv3)와 POSIX 유닉스 응용 프로그램, 유틸리티와 비슷하다.

 

 

 

 

 ATmega2560의 구조와 기능 (교재 34페이지~155페이지 수업내용, SKIP한 부분있음)

 

프로그램 메모리

 

 ☞ 8비트씩 2개가 합해져서 기본적으로 1개의 번지가 16비트 단위로 구성되어
    마치 16비트 마이크로 프로세서인 것처럼 동작,  따라서 16비트 또는 32비트
    길이로 구성되어 있음
 

 ☞ 플래시 메모리로 되어 있는 내부 프로그램 메모리는 부트로더 섹션과
     응용 프로그램 섹션의 2가지 영역으로 나누어짐 
    

     ※ ATmega2560은 8비트 마이크로 컨트롤러지만  이 프로그램 메모리는

         각 번지가 16비트 구조로 되어 있어서 128K x 16비트 = 256KB의 용량을 갖는다.

 데이터 메모리

 

 ☞ ATmega2560의 데이터 메모리는 크게 3종류로 나눌수 있음

      → 내부 데이터 메모리(SRAM) (64KB의 데이터 메모리 영역에 맵핑 되어 있음)

      → 외부확장 데이터 메모리 (64KB의 데이터 메모리 영역에 맵핑 되어 있음)   

      → 내부 EEPROM( 별도의 I/O 레지스터를 통하여 액세스)

 

  

 

※ ARM에서는 Flash와 SRAM 모두 포인터로 접근가능

※ AVR에서는 SRAM에만 포인터로 접근가능(하버드 구조라서 Flash 접근안됨)

     대신 EEPROM은 EEPROM Address Register와 EEPROM Data Register를

     이용해 주소를 지정해주고 값을 쓰거나 읽을수 있음. 

(EEPROM Address Register는 EEARH 4bit와 EEARL 8bit로 구성되기 때문에 2바이트가 쓰임)

 

☞ EEPROM Write 동작

1. 앞의 라이트 동작이 완료되어 EEPE = 0 으로 될떄 까지 기다린다.

2. SPMCSR 레지스터에서 SPMEN = 0 으로 될때까지 기다린다.

3. 새로 라이트할 EEPROM 어드레스를 EEAR 레지스터에 저장한다.

4. 새로 라이트할 EEPROM 데이터를  EEDR 레지스터에 저장한다.

5. EECR 레지스터에 EEMPE = 1, EEPE = 0 으로 설정한다.

6. 4사이클 이내에 EEPE = 1 로 설정한다.

 

☞ EEPROM Read 동작

1. 앞의 라이트 동작이 완료되어 EEPE = 0 으로 될떄 까지 기다린다.

2. 리드할 EEPROM 어드레스를 EEAR 레지스터에 저장한다.

3. EECR 레지스터에  EERE = 1 로 설정한다.

4. EEPROM 데이터를 EEDR 레지스터로부터 읽는다.

 

    

 

 

 

 

EEPROM은 온보드 상태에서 사용자가 내용을 바이트 단위로 리드하거나 라이트 할수 있으므로 SRAM 처럼 사용 할수

    있는 불휘발성 메모리이나 Write 동작을 수행하는 경우 1바이트를 라이트 할때마다 수[ms] 이상의 시간지연이 필요하므로

    SRAM과 동일하게 사용할수는 없으며 한번 내용을 저장하면 비교적 오랫동안 이를 기억하고 있으면서 주로 이를 읽어 사용하기만

    하거나 전원을 꺼도 지워져서는 안되는 중요한 데이터를 백업하여 두어야 하는 설정값 저장용 메모리로 적합하다.

 

플래시 메모리는 온보드 상태에서 사용자가 내용을 바이트 단위로 자유로이 리드할수는 있지만 Write 는 페이지 또는 섹터라고

    불리는 블록 단위로만 수행할수 있다. 플래시 메모리 역시 SRAM 같이 실시간 데이터 메모리로 사용하는 것은 불가능하지만

    셀의 구조가 간단하므로 훨씬 대용량의 메모리 소자를 만드는데 적합하여 마치 하드 디스크처럼 사용이 가능하다.

   (플래시 메모리는 내부구조에 따라 NOR형과 NAND형으로 나눌수 있으며 NOR형이NAND형보다 속도는 빠르지만 복잡하고 비쌈)

  

 

 

 

 

 

 

 

 

 LCD.h

#ifndef _LCD_H_
#define _LCD_H_

 

//------------------------------------------Data bus line(PC 0~7)
#define  PORTC  ( *((volatile unsigned char *)0x28) )
#define  DDRC    ( *((volatile unsigned char *)0x27) )
#define  PINC     ( *((volatile unsigned char *)0x26) )
//-------------------------------------------------------------

 

 

//-------------------------------------RS(PD7), RW(PD6), EN(PD5)
#define  PORTD  ( *((volatile unsigned char *)0x2B) )
#define  DDRD  ( *((volatile unsigned char *)0x2A) )
#define  PIND  ( *((volatile unsigned char *)0x29) )
//-------------------------------------------------------------


#define LCD_RS (1<<7)   
#define LCD_RW (1<<6)  
#define LCD_EN (1<<5)   
#define LCD_BS (0xFF)   
       


#define LCD_CLEAR 0x01   //0000 0001,  P13, 화면 클리어
#define LCD_HOME 0x02   //0000 0010,  P13, 커서 맨 처음으로
#define LCD_ENTRY 0x06   //0000 0110,  P13, 커서 오른쪽 시프트, 화면고정
#define LCD_DISPLAY 0x0C  //0000 1100, P13, 화면 ON, 커서 OFF, cursor blink OFF
#define LCD_CURSOR 0x1C  //0001 1100,  P13, displayshift, shift to the right 
#define LCD_FUNC     0x38  //0011 1000,  P13, 8bit, 2lines, 5x7dots


#define LCD_DELAY 2500 // 최소 지연시간( 타이밍도에 맞게 동작하기위한 필요 지연시간)
#define LCD_DELAY1 0  
#define LCD_DELAY2 0
#define LCD_DELAY3 150
#define LCD_DELAY4 50


//---------UserFont
#define LCD_CGRAM  0x40 // 사용자 정의 문자를 저장하여 사용할수 있는 주소(시작주소)
//---------------


void LCD_Init (void);

void LCD_Cmd_write (unsigned char);

void LCD_Data_write (unsigned char);

void LCD_String(void *);

void LCD_Number(unsigned int, unsigned int );

void LCD_UserFont(void);

 

#endif //_LCD_H_

 


 

 LCD.c (포팅한것 위주...)

#include "LCD.h"

 

void LCD_Init (void)
{
     DDRD = (LCD_RS) |(LCD_RW) |(LCD_EN); //0xE0, PD5, PD6, PD7 출력 방향활성
     DDRC = 0xFF;                                      //PORTC는 모두 출력방향으로 활성

 
     LCD_Cmd_write(LCD_FUNC); 
     LCD_Cmd_write(LCD_ENTRY);
     LCD_Cmd_write(LCD_CURSOR);
     LCD_Cmd_write(LCD_DISPLAY);
     LCD_Cmd_write(LCD_CLEAR);
     LCD_Cmd_write(LCD_HOME);
                     
     return ;
}


void LCD_Cmd_write (unsigned char ucdata)    //타이밍도에 맞춘 write operation
{
      volatile unsigned int iCnt;

      PORTD = ( (PORTD) & (~LCD_EN) ); // 이전 PORTD의 값을 유지하면서 부분 비트만 0으로 바꾸고 싶을때
                                                                    // 바꾸고 싶은 비트를 ~(비트반전) 시켜서 기존 값과 & 해줌
         
      PORTD = ( (PORTD) & (~LCD_RS) ); //RS clear
     PORTD = ( (PORTD) & (~LCD_RW) );//RW clear

 

      for(iCnt = 0; LCD_DELAY - LCD_DELAY1> iCnt; ++iCnt);  //시간지연

     

      PORTD = ( (PORTD) | (LCD_EN) );  // 이전에 PORTD의 값을 유지하면서 부분 비트만 1로 바꾸려면
                                                                 // 바꾸고 싶은 비트에 1을 넣고(1<<)  기존 값과 | 해줌
                                                                 // EN set

 

      for(iCnt = 0; LCD_DELAY - LCD_DELAY2 > iCnt; ++iCnt);  //시간지연

     

      PORTC = (ucdata);                             // BUS data  input

     

      for(iCnt = 0; LCD_DELAY - LCD_DELAY3 > iCnt; ++iCnt);  //시간지연

     

      PORTD = ( (PORTD) & (~LCD_EN) );  //EN clear

     

      for(iCnt = 0; LCD_DELAY - LCD_DELAY4 > iCnt; ++iCnt);  //시간지연


 
      return;
}

 


void LCD_Data_write (unsigned char ucdata)  

{
      volatile unsigned int iCnt;

   

      PORTD = ( (PORTD) & (~LCD_EN) ); // 이전 PORTD의 값을 유지하면서 부분 비트만 0으로 바꾸고 싶을때
                                                                    // 바꾸고 싶은 비트를 ~(비트반전) 시켜서 기존 값과 & 해줌
         
      PORTD = ( (PORTD) | (LCD_RS) );  //RS set
     PORTD = ( (PORTD) & (~LCD_RW) );//RW clear

 

      for(iCnt = 0; LCD_DELAY - LCD_DELAY1> iCnt; ++iCnt);  //시간지연

     

      PORTD = ( (PORTD) | (LCD_EN) );  // 이전에 PORTD의 값을 유지하면서 부분 비트만 1로 바꾸려면
                                                                 // 바꾸고 싶은 비트에 1을 넣고(1<<)  기존 값과 | 해줌
                                                                 // EN set

 

      for(iCnt = 0; LCD_DELAY - LCD_DELAY2 > iCnt; ++iCnt);  //시간지연

     

      PORTC = (ucdata);                             // BUS data  input

     

      for(iCnt = 0; LCD_DELAY - LCD_DELAY3 > iCnt; ++iCnt);  //시간지연

     

      PORTD = ( (PORTD) & (~LCD_EN) );  //EN clear

     

      for(iCnt = 0; LCD_DELAY - LCD_DELAY4 > iCnt; ++iCnt);  //시간지연


 
      return;
}

 

void LCD_String(void *vp)
{

      while(1)
      {
             if(*((unsigned char *)vp) == 0 )
             {
                  break;
             }
             LCD_Data_write(*((unsigned char*)vp));
             vp = ((unsigned char *)vp) + 1;
       }

       return;
}

 

 

void LCD_Number(unsigned int uiLine, unsigned int uiNum) //LCD 몇번째 라인에 쓸지를 결정
{                                                                                      //65535 까지 가능

      unsigned char ucSting[] = "00000";

      ucSting[0] = '0'+(uiNum / 10000);  // 넘겨받은 usNum값을 단위별로 나누어 각 배열자리에 대입
                                                       // 아스키코드 값으로 넘겨줘야 하기때문에 '0'값에 더함
      ucSting[1] = '0'+((uiNum % 10000) / 1000);

      ucSting[2] = '0'+((uiNum % 1000) / 100);

      ucSting[3] = '0'+((uiNum % 100) / 10);

      ucSting[4] = '0'+(uiNum % 10);

      ucSting[5] = '\0';
 
      if(1 == uiLine)
      {
           LCD_Cmd_write(0x80);
           LCD_String("TEMP :");
      }
      else
      {
          LCD_Cmd_write(0xC0); // LCD 두번째 라인
          LCD_String("LIGHT:");
      }
 
      LCD_String(ucSting);
 
      return;

}


 

main.c

#include "LCD.h"

 

#define  PORTA  ( *((volatile unsigned char *)0x22) )
#define  DDRA  ( *((volatile unsigned char *)0x21) )
#define  PINA  ( *((volatile unsigned char *)0x20) )
/* DDRx : 해당 포트(핀)를 출력(1)으로 쓸지 입력(0)으로 쓸지(입출력 방향)를 쓰기하여 결정  

               해당 핀이 출력방향인지 입력방향인지를 확인하려면 DDRx레지스터를 Read 하면 됨.
   

     PORTx : 해당 포트(핀)의 출력을 H값(1) 또는 L값(0)으로 결정 
                 해당 핀의 출력값(레벨)을 확인하려면 PORTx 레지스터를 Read 하면 됨.

   

    PINx : 포트(핀)의 입력레벨(값)을 읽을때 씀
*/


int main(void)
{
     volatile unsigned int uiCnt1; //AVR에서 int는 16비트(2바이트), 65535
     volatile unsigned int uiCnt2; 

 

     LCD_Init();

     LCD_String("TEST JJY");
  
 
     DDRA = 0xFF;//포트 A 모두 출력으로 설정
     PORTA = 0xFF; // 포트 A 모두 H값 set

 

     while(1)
     {
          for(uiCnt1 = 0; uiCnt1 < 10000; ++uiCnt1) // unsigned int 가 65535까지 카운트 할수 있어서
                                                                  // 1000000까지 카운트하기 위해 2중 for 문을 사용함
                                                                  // ( 100 x 10000)
          for(uiCnt2 = 0; uiCnt2 < 100; ++uiCnt2);
          PORTA = 0;// 출력 값  모두 L 로 셋팅

  

          for(uiCnt1 = 0; uiCnt1 < 10000; ++uiCnt1)
          for(uiCnt2 = 0; uiCnt2 < 100; ++uiCnt2);
          PORTA = 0xFF;//출력 값 모두 H 로 셋팅됨

     }


     while(1);
     return 0;
}

 

 makefile (수정된 내용만...)

# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c LCD.c

 

 

 

728x90