유닉스 리눅스 프로그래밍 필수 유틸리티(개정판) : vim make, gcc, gdb, svn, binutils, autoconf, autotools

시스템 개발쪽이나 임베디드 쪽으로 관심이 많다면 꼭 한번 보시길!!


Auto build tool


Auto build tool - make와 같이 자동으로 build 시켜주는 도구를 의미한다.

makefile은 리눅스에서 makefile로 자동인식한다.

makefile


makefile 설정 해놓은 소스이다. 위의 사진처럼 CC변수를 gcc로 선언해 놓았다.


makefile 있을 때

makefile이 존재하면 make 시에 선언해놓은 것 처럼 gcc로 컴파일을 한다.


makefile 없을 때

makefile 파일을 지워보았다. make 시 기본인 CC로 컴파일 된다는 것을 

알 수 있다.


makefile이용해서 clean 선언하여 지우기


:w (파일이름)    -    다른이름으로 저장



TARGET = main            TARGET을 main으로 정의 해준다.

:clean                                                     다 지우기 위한 라벨.

@rm -rf(지워라 묻지말고) $(TARGET)    정의한 main 실행파일을 묻지도 따지지도

    않고 지워라.

@rm -rf(지워라 묻지말고) $(TARGET).i   

@rm -rf(지워라 묻지말고) $(TARGET).o

@rm -rf(지워라 묻지말고) $(TARGET).s  선언된 각 중간 파일들을 묻지도 

따지지도 않고 지워라.


(TARGET) make하기 전


(TARGET) make 하고 나서


파일이 지워진 것을 확인할 수 있다.


makefile 그럴듯하게 써보자!!

각각 변수 선언을 해주고 나서 각각 라벨을 선언한다.

1. run: 라벨은 rebuild: 라벨 실행 후에 run: 라벨이 실행된다.

2. rebuild 라벨은 clean라벨을 실행하여 먼저 main, main.i, main.o, main.s를 

   묻지도 따지지도 않고 삭제 후에 build를 실행시키는데

3. build에서 begin과 end는 그냥 구분해주는 메시지이다. build에서 main.c를 

   컴파일 시켜준다.

4. 이렇게 rebuild 실행이 완료되면, main을 실행시켜서 위와 같이 실행화면이 

   출력된다.


makefile의 지능화 툴

main.c        13:40

main           13:41


main.c는 컴파일 시간이 41분이다. 고로 main.c는 수정되지 않았다.

이를 make는 알 수 있다. (시간으로 판단하여)


main.c를 갱신하기 전에 make를 해보았다.


main.c를 갱신하고 나서는


make는 시간으로 판단하여 갱신할 필요가 있는지 없는지 판단한다.



makefile에서 define하기



makefile에서 CFLAGS에 -DNUMBER=50을 삽입한다.

-DNUMBER=50은 어딘가에 있는 NUMBER를 50이라 define하겠다는 의미이다.


main.c에서 이전에 선언했던 define문을 주석처리한다.

저장하고, 밑에 처럼 make를 치면, 맨 위에 있는 run 라벨을 실행하는데 

하기 전에 rebuild를 먼저 실행한다. 우선 실행파일(main) 및 중간파일(main.i, o, s)를 

지우고, main.c를 컴파일하여 실행파일을 다시 만들면서 중간파일도 다시 생성한다. 

그리고 실행을 시킨다.

위의 그림과 같이 makefile에서 NUMBER를 define하여 사용할 수 있다.



추가적으로!!

실제 source insight에서 makefile이 사용되는 예이다.

우리는 리눅스에서 동일하게 흉내내어 봤다.

clean 라벨의 begin과 end는 알 것이고, clean_list라벨에서 

각 파일들을 소스파일 빼고 거의 다 지운다. ATMega128을 실습할 때 우리는

make파일을 사용하여 컴파일을 하였다. 기억나지?(make clean!!)


source insight에서 makefile을 이용한 define

위 그림과 같이 makefile에서 F_CPU를 16000000정의 하였고,

그 F_CPU를 이용해 smart.h에서 define시켜주었다.


CFLAGS 분할 정의

위 그림처럼 CFLAGS를 분할 정의하면 수정할 때도 편하고 

관리도 편리하다는 CM의 말씀.



결론적으로 makefile에 대해서 모르면 무엇이 변수인지도 모르고, 사용할 줄도 모른다는 것이다. makefile은 겁나게 복잡할 뿐 하나하나 보면서 분석해나간다면, 어느 정도 파악할 수 있을 것이다. 결론은 열심히 하자는 말씀;; 


20140519 - make파일이란?

study!!! 2014. 5. 19. 10:36 Posted by Owen.K


makefile이란?


make or build이라고도 한다.

make는 실행파일을 뜻한다. 빌드 툴로 분류된다.

어떠한 작업을 잘 완료할 수 있도록 도와준다. 프로그램을 컴파일 하는데에 도움을 준다.

gcc -o main main.c

 main.c를 컴파일하여 main이라는 실행파일을 output한다. 

 

vi 편집기 단축키

YY : 한줄 복사

D + 아래방향키 : 해당줄부터 두줄 잘라내기

P : 붙여넣기



make main이라 치면

이렇게 나온다. 실행하고 싶은 이름만 치면 위처럼 자동으로 컴파일을 해준다.

cc는 바로가기 gcc와 cc는 같다. cc는 나에게 설치된 컴파일러 아무거나 써라.

gcc는 gcc컴파일러만 써라.



makefile 생성하는 법 



test: 라벨을 실행 시

  단어 앞에 @가 붙으면 단어는 출력이 되지 않는다.

tab    @clear는 화면의 모든 것을 클리어 시킨다. tab은 test라벨의 

     tab 안의 것들을 포함시키겠다는 의미.

tab    @echo는 echo 뒤의 글들을 출력한다. 

tab    @ls -al은 리스트 all 명령을 실행한다.

나름의 문법이있다.




make에서 실행 순서 

 



makefile은 실행순서를 알아두는 것이 중요하다. 저장 후에 라벨이름없이 make만 치면,

제일 첫 번째 라벨이 기본으로 실행된다. 여기서 첫 번째 라벨 옆에 test, smart와 같은 다른 라벨들을

적어 놓으면 적은 순서에 따라서 라벨들이 먼저 실행되고나서 첫 번째 라벨의 내용이 실행된다.


makefile에 대해




makefile을 이용해 중간파일 생성하기

CC=gcc는 makefile에서 변수 선언이다. 다른 언어들 처럼 변수선언을 할 때 타입을 적는 것은 

편견이다. 변수 이름은 CC이고, 변수 사용 시에는 $(CC)로 적어서 사용한다.

smart라벨에 위와 같이 적으면....음 이해할 수 있을거라 본다. 


'study!!!' 카테고리의 다른 글

20140502 - 0429일 오전시간 복습!!!  (0) 2014.05.02

초음파 센서 타이밍도(mode1)에 따른 소스구현


 

 

 

 

 

 

 

 

 

 

20140514 - Time Counter

ATMega128 2014. 5. 14. 13:47 Posted by Owen.K

14. 8bit Timer/Counter0 with PWM and Asynchronous operation


TIMSK 레지스터

Bit 1 – OCIE0: Timer/Counter0 Output Compare Match Interrupt Enable

- 비교해서 일치하면 인터럽트 발생.

Bit 0 – TOIE0: Timer/Counter0 Overflow Interrupt Enable

- 255를 넘어서면 인터럽트 발생.



 

 

 

 

 

 

 

 

 

 

 


 


20140513 - Timer Count 수정중

ATMega128 2014. 5. 13. 11:17 Posted by Owen.K


인터럽트  -  H/W(외부 인터럽트)

    -  S/W OS 

JAVA는 이벤트

Win은 메시지

Linux는 시그널

Android는 푸쉬(Push)


external -> INT0~7

internal -> ADC ->(interrupt request) Vector 22번 -> 21번 함수

     -> USART ->(interrupt request) Vector 19번 -> 18번 함수


Timer Count

 

 

 

 

 

 

 

 

 

 

 




LCD에 대한 의존성


위는 INT.c의 소스이다.

위 처럼 LCD_Str없이는 Interrupt를 쓸 수 없게 된다. 이를 의존성(Depandency)라고 한다.


다른곳에도 인터럽트 활용해 보기

인터럽트를 여러곳에 사용하기 위해 INT.h에 있던 인터럽트 활성화 소스 부분을 smart.h로 이동하여 전체적으로 사용 가능하도록 위치를 바꿔주었다.




ADC에 인터럽트 활성화 


ADC인터럽트를 활성화 하기 위해서는 레지스터 ADCSRA의 3번 포트인 ADIE를 통하여 인터럽트 활성화를 해주어야 한다.

인터럽트 벡터를 보면 ADC인터럽트 22번에 있는것을 확인할 수 있다. 그렇기 때문에 함수로 선언하기 위해서는 1을 뺀 __vector_21로 함수를 선언해 주어야 한다.(ADC 변환이 완료되면 인터럽트 발생)

기존의 ADC.c 소스를 활용하여 인트럽트 함수를 따로 선언하고 인터럽트 전체를 0으로 만드는 함수인 cli() 을 호출해 준 뒤 기존의 소스의 오른쪽 정렬을 왼쪽 정렬로 바꾸고 인터럽트 활성화 부분인 ADCSRA의 ADIE를 1로 바꿔준다.

그런 뒤 변환부분에서 while로 돌리던 부분을 없애주고 반환값도 없애준 뒤 벡터함수 21(vocter 22번 ADC)을 선언해 준다. 이 인터럽트는 ADC 변환이 완료되면 자동으로 이 함수로 이동하여 LCD_Num(ADC); 를 호출해 준다. 그렇게 변환이 완료된 값이 10비트이나 LCD에 숫자로 출력하는 함수가 8비트까지 출력하도록 설정 해 놓았기 때문에 변환된 값을 가지는 ADCH,ADCL 레지스터의 H레지스터를 사용하기 위해 초기 선언을 왼쪽 정렬로 하고 ADC의 주소설정값을 H로 바꿔주었다.


Main.c

인터럽트 설정은 다 끝이났기 때문에 메인 부분에서 호출을 해주면 된다.

먼저 LCD로 출력된 값을 보여주기 때문에 LCD초기화 부터 해준다.  다음에 ADC인터럽트 부분을 초기화 해준다. 인터럽트를 한꺼번에 켜기 위해 sei()함수를 호출해 준다. 마지막으로 LCD 동작을 알아보기 위해 먼저  Start를 출력하고 ADC변환 함수를 호출 한다.

ATMega 칩의 ADC0 번에 선을 연결하여 사용하여 채널 0을 설정한다.

ADC에 Interrupt 활성화 시키기 +에 꽂을 때


ADC에 Interrupt 활성화 시키기 -에 꽂을 때

 +일때 uart 통신을 통하여 값을 알아본 결과 1023이 출력되었었다.

그러나 지금은 8비트로 11 두개가 날라가고 1111 1111이 출력되어 최대 255 가 출력되는 것을 확인 가능하다.

가운데는 아무곳도 연결 안한 상태로 값이 reset을 눌러줄 때 마다 값이 계속 바뀐다.

마지막은 GND(-)에 연결했을 때의 출력 모습이다.


USART에 인터럽트 활성화


 

UART에서도 인터럽트를 활성화 하기 위해서는 레지스터를 봐야 하는데 보게되면 인터럽트 활성화 하는 부분이 여러개 있다. 그러나 우리는 RX 송신시 인터럽트 발생이 되도록 설정하려고 한다.

벡터표를 보게 되면 우리가 사용중인 UART0에서 RX 인터럽트 부분의 벡터 번호는 19번이다. 그렇기 때문에  함수 선언부분의 번호는 18번이 된다.

먼저 마찬가지로 인터럽트들을 모두 활성화를 꺼준다.

RX 인터럽트 활성화가 있는 UCSR0B에 RXCIE를 1로 송신이 완료되면 인터럽트가 발생하도록 설정해 준다.

인터럽트 함수 벡터_18을 선언 해주고 인터럽트 발생시 수행하는 함수호출을 넣어주면 끝!

송신이 완료되면 인터럽트 함수가 호출되면서 LCD_Data(UDR0); 를 호출하여 LCD에 찍어주게 된다.


Main.c에서 호출을 하고 하이퍼터미널을 통하여 통신을 하게 하고

키보드로 입력해 주게 되면 한 문자씩 LCD로 출력이 된다.

USART에 Interrupt 활성화 시키기



하이퍼터미널에서 USART통신으로 키보드에 입력 받아 LCD에 보이는 모습

HI!!I'm Owen.K

인터럽트 EICRA(External Interrupt Control Register A), EICRB(External Interrupt Control Register B) 설명


 ISC71

ISC70 

ISC61 

ISC60 

ISC51 

ISC50 

ISC41 

ISC40 

 Bit 7

Bit 6 

Bit 5 

Bit 4 

Bit 3

Bit 2 

Bit 1 

Bit 0 

Bit 0 과 1, Bit 2 와 3, Bit 4 와 5, Bit 6 과 7은 위 그림의 표처럼 한 쌍이다.

EICRA, EICRB는 각각 두 개 씩 묶어서 INT0(ISC00, ISC01) : INT7(ISC70, ISC71)까지를 의미한다.

이들의 값에 따라 어떤 식으로 작동이 되느냐는 밑의 표에 나와있다.    



 ISCn1

ISCn0 

Description 

 0

 Low이면 인터럽트를 요청.

 0

 어떤 변화가 있으면(positive || negative) 인터럽트를 요청.

 1

 falling edge이면 인터럽트를 요청.

 1

 rising edge이면 인터럽트를 요청.

* ISCn1의 n은 INTn의 n을 의미한다.



인터럽트 EIMSK - External Interrupt Mask Register 설명



Bits 7:0은 INT7 : INT0을 의미한다. 이들 중 하나가 무조건 1이어야 하고, 

SREG 레지스터의 Bit 7 I도 1이 되어야 인터럽트가 구동된다.

INT7 : INT0가 방이라 치고 SREG 레지스터의 Bit 7이 대문이라 치면, 

대문을 잠그면(0) 밖에 나갈 수 없다. 그래서 둘 다 1이어야 인터럽트 요청가능.



INT.h부터 살펴보자

#define cli() __asm__ __volatile__ ("cli" ::)

SREG 인터럽트 비활성화 시키는 어셈블리어

#define sei() __asm__ __volatile__ ("sei" ::)

SREG 인터럽트 활성화 시키는 어셈블리어 sei(set enable interrupt)

자동으로 1을 넣는다.

#define sleep() __asm__ __volatile__ ( "sleep" "\n\t" :: )

SREG 인터럽트 슬립 시키는 어셈블리어

c로만은 cpu를 못 건드는 부분을 어셈블리어로 건들인다.

통틀어 inline assembly라고 부른다. 컴파일이 바뀌면 사용할 수 없다. 

void __vector_8(void) __attribute__((signal, used, externally_visible));

gcc컴파일러만 쓰는 문법 이 함수의 속성을 적어줌.

리눅스에서는 시그널....인터럽트이다. 외부에서 이 함수를 호출할 수 있다.

data sheet 59page 벡터 넘버를 보면 실제 코딩할 때는 번호가 0부터 시작이다.

void INT7_Init(void);



다음 INT.c를 보면,

void __vector_8 (void) 

{

LCD_Str("Interrupt1");

상승엣지일 때 위의 것이 적힘.

USART_Str("Interrupt2");

}

void INT7_Init(void)

{

cli();

이 함수를 실행전에 다른장치의 인터럽트를 먼저 꺼둠.

EICRB = (1<<ISC71)|(1<<ISC70);

상승 엣지일 때 인터럽트 요청.

EIMSK = EIMSK|(1<<INT7);

SREG는 직접 건들여서 세팅하거나,

sei();

SREG = SREG|(1<<I)과 같은 의미.

}



마지막으로 main.c

int main(void)

{

LCD_Init();        LCD초기화

INT7_Init();        INT7초기화

while(1)

{

sleep();

일 안시키면 재운다.

}

return 0;

}



실행결과


ATMega 128A에 연결.

푸쉬스위치에 연결

실행 결과


최종 소스는 

20140509.zip


북 연결리스트


Book_DBopen


Book_DBclose


Book_FileIn


Book_FileOut


Book_DBsave

20140508 - ATMega128A(Interrupt) 수정중

ATMega128 2014. 5. 8. 09:38 Posted by Owen.K

Interrupt


Interrupt - 하드웨어 인터럽트와 소프트웨어 인터럽트로 나뉘는데

 우리가 다루는 것은 주로 하드웨어 인터럽트이다. 

       USART통신이 끝날 때까지 ALU가 뭔가를 할 수 없기 때문에 

 거기서 대안한 방식이 인터럽트 방식이다.

       소프트웨어에서 인터럽트는 자바에서는 이벤트, 윈도우에서는 메세지, 

       리눅스에서는 시그널.

       다른말로 IRQ(Interrupt ReQuest), INT(INTerrupt) 인터럽트 요청을 의미한다.

       코드 함수는 ISR(Interrupt Service Routine).




polling - 폴링방식은 정해진 시간 또는 순번에 상태를 확인해서 상태 변화가 

있는지 없는지를 체크하는 방식이다.



위의 두 개는 컴퓨터 용어에서 서로 반대의 개념이다.






gcrt1.s -> 소스파일이고, crt128.o(Entry Code)가 들어온다. 소스파일과 링크 되있다.


make하고 만들어진 파일들이 배치되어있는 파일을 main.map파일이라 한다. 우리가 짜놓은 소스는 Code영역에 들어가 있다.(make시킨 폴더에 들어가보면 확인 할 수 있다.)




인터럽트 함수 만들기




북 연결리스트


Book_Alldel 


LinkedList.c

LinkedList.h

main.c


향후 그림 설명으로 대체하겠음!!

Book_Insert 



Book_Print