티스토리 뷰
이번에는 조금 고급 테크닉을 사용하여 LED를 제어해 보도록 하겠다. 앞에서 매크로를 사용해서 코드를 보기 좋게 만들었다. 앞의 코드는 Data memory 공간을 이용했다면, 이번에는 C코드에서 직접 I/O 메모리 공간을 바로 접근하는 방법에 대해서 설명하겠다.
이미 LED 제어 4에서 I/O 메모리 공간에 접근하기 위해서 "in", "out"명령을 사용해야 한다고 설명했었다. 그러나 I/O 주소를 직접 사용할 수 없고 0x20만큼 offset값을 더해서 사용해야된다고 했다.
C프로그램을 하다보면 C코드로는 도저히 사용할 수 없는 명령어를 사용해야 되는 경우와 어셈블러로 구현하는게 훨씬 효율적인 경우가 생긴다. 이런 요구사항을 해결하기 위해서 inline assembler기능을 사용하면 된다.
#define out_io(reg, val) asm volatile ("out %0, %1"::"I" (reg), "r" (val))
위의 코드를 이용하면 C코드에서 직접 "out" 명령어를 사용할 수 있게된다.
위의 inline assembler를 사용하여 코드를 수정하면 다음과 같이 된다.
#define F_CPU 1000000
//#include <avr/io.h>
#include <util/delay.h>
#define PINB 3
#define DDRB 4
#define PORTB 5
#define GREEN_LED 0x01
#define RED_LED 0x02
#define out_io(reg, val) asm volatile ("out %0, %1"::"I" (reg), "r" (val))
int main(void)
{
out_io(DDRB, (GREEN_LED|RED_LED));
out_io(PORTB, (GREEN_LED|RED_LED));
while (1)
{
_delay_ms(500);
out_io(PINB, (GREEN_LED|RED_LED));
}
}
이와 같이 하면 C코드에서 어셈블러코드를 중간에 끼워 넣을 수 있다.
접근하고자 하는 I/O 레지스터 주소값에 0x20을 더하지 않고 I/O레지스터 주소를 그대로 사용하였음을 볼 수 있다.
댓글