#define ISR() 문 분석을 통해서 #define 전처리 언어에 대해서 공부해보자
interrrup.h 안에 있는 ISR() 정의
#ifdef __cplusplus
# define ISR(vector, ...)
extern "C" void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
void vector (void)
#else
# define ISR(vector, ...) \
void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
void vector (void)
#endif
1. extern "C"
C++ 문법 네임맹글링 ( Name Mangling)
c++ 의 경우 컴파일 할때 컴파일러는 함수이름에 앞뒤로 여러가지 문자가 추가 되는데 이를 네임 맹글링이라 한다.
네임 맹글링은 함수의 오버로드 기능 또는 링커가 똑같은 이름의 함수를 구분 할 수 있기위해서 컴파일러에서 자동으로 추가 되는 부분으로 네임맹글링 규칙은 컴파일러마다 다르다.
c 언어의 경우 이러한 맹글링을 지원하지 않아 c++ 로 컴파일된 언어와 호환되지 않는데 extern "C" 를 사용하면 맹글링된 함수가 C 라는 것을 링커에게 알려줘서 C 작성된 프로그램과도 호환이 가능하다.
출처:
2. __attribute__
이는 gcc 에만 있는 기능으로 컴파일러에게 추가적인 지시를 할 수 있는 기능이다.
https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Function-Attributes.html
위의 사이트에 signal 속성에 대해 읽어보면
컴파일러에게
이 기능이 인터럽트 핸들러임을 알려줘서 컴파일러가 인터럽트 핸들러에게 사용하기 적합한 함수 진입 및 종료 시쿼스를 생성 하도록 명령한다.
cf) attribute 심화 내용
https://indra17.tistory.com/entry/GNU-C-attribute
3. __VA_ARGS__ (가변인수 매크로 )
매크로 함수를 사용할때 변수의 갯수가 변할 수 있다. 이러한 경우 가변인수 매크로를 사용한다.
즉 ... 부분이 __VA_ARGS__ 와 치환 된다.
참고로 ##__VA_ARGS__ 의 경우는 가변인자가 들어 오지 않는경우
즉 printlog_(fmt,) 과 같이 치환 될 경우 , 을 없애준다.
ISR() 에서 가변인수 자리에 들어 올 수 있는 값은
- ISR_BLOCK ;속성을 지정 안하면 기본으로 선택됨
- ISR_NOBLOCK
- ISR_NAKED ;
- ISR_ALIASOF( target_vector )
이고 interrup.h 안에 정의를 보면 attribute 를 통해서 정의되어 있는 모습을 봇수 있다.
# define ISR_BLOCK
# define ISR_NOBLOCK __attribute__((interrupt))
# define ISR_NAKED __attribute__((naked))
# define ISR_ALIASOF(v) __attribute__((alias(__STRINGIFY(v))))
https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=ioizzzzzz&logNo=220068978054
에서 확인 해라
4. \
# define 문에서 줄바꿈은 \ 로 표시해줘야지 줄바꿈이라고 인식한다.
마지막으로 gcc 에서 어떻게 전처리문으로 바꾸는지 실제로 사용해보자 (우분투에서 gcc 깔아서 실행함)
c 언어 코드 test.c
#define ISR(vector, ...) \
extern "C" void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
void vector (void)
ISR(INT0_vect, ISR_NAKED ) {
PORTD ^= 0x1;
}
int main ()
{
return 0;
}
~
~
~
전처리후 파일 test.i
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "test.c"
extern "C" void INT0_vect (void) __attribute__ ((signal,__INTR_ATTRS)) ISR_NAKED;
void INT0_vect (void) {
PORTD ^= 0x1;
}
int main ()
{
return 0;
}
질문 1. 왜 ISR_NAKED 가 __attribute__((naked)) 로 변경 되지 않는가 ?
'공부,일 > atmega328P' 카테고리의 다른 글
atmega 328p PWM & timer counter (2) 구조 및 레지스터 (0) | 2021.07.27 |
---|---|
atmega 328p PWM & timer counter (1) 분주비 , 타이머 vs 카운터 (0) | 2021.07.27 |
i/o register 0x0(0x20)메모리 주소의 의미 (기본기) (0) | 2021.07.20 |
EEPROM 사용하기 (0) | 2021.07.18 |
Register 이용해서 LED 켜기 (0) | 2021.07.16 |
댓글