AVR

11 자주 묻는 질문들

siwall 2014. 4. 17. 16:50

자주 발생하는 문제점에 대한 해결 방안을 설명


11.2 My program doesn’t recognize a variable updated within an interrupt routine

다음과 같은 loop 코드에서:


uint8_t flag;

...

ISR(SOME_vect) {

flag = 1;

}

...

while (flag == 0) {

...

}


코드 최적화 레벨을 사용하면 flag 변수가 최적화 되면서 버그가 생길수 있다.

다음과 같이 선언해서 사용해야 한다.

volatile uint8_t flag;


11.3 I get ”undefined reference to...” for functions like ”sin()”

수학 함수에 접근하려면 <math.h>를 포함해야 한다. 

링커에게도 libm.a 라이브러리를 사용하도록 지정해 주어야 한다. 

linker flag에 -lm을 추가해주면 된다.


11.4 How to permanently bind a variable to a register?

다음 방법으로 이것을 구현할 수 있다.

register unsigned char counter asm("r3");

보통, r2 부터 r7을 이와같은 방법으로 사용해도 안전하다.

r8 부터 r15는 argument 전달을 위해 컴파일러에 의해 사용된다.


11.5 How to modify MCUCR or WDTCR early?



11.6 What is all this BV() stuff about?



11.7 Can I use C++ on the AVR?


11.8 Shouldn’t I initialize all my variables?




11.9 Why do some 16-bit timer registers sometimes get trashed?



11.10 How do I use a #define’d constant in an asm statement?



11.11 Why does the PC randomly jump around when single-stepping through my

program in avr-gdb?




11.12 How do I trace an assembler file in avr-gdb?



11.13 How do I pass an IO port as a parameter to a function?




11.14 What registers are used by the C compiler?





11.15 How do I put an array of strings completely in ROM?




11.16 How to use external RAM?

이 질문에 대한 보편적인 대답은 없다. 

기본적으로, 외부 메모리 인터페이스를 Enable 시키기 위해서 MCUCR 레지스터의 SRE 비트를 Set해야 한다.

어떤 메모리가 사용되는지에 따라 XMCRA, XMCRB, MCUCR 의 여러 비트들을 설정해야 할 필요가 있다. 


만일 외부메모리가 C프로그램에서 변수 저장을 위해 사용된다면, (.data, .bss 영역) 



11.17 Which -O flag to use?



11.18 How do I relocate code to a fixed address?

첫째, 새로운 named section을 만들어서 코드를 집어 넣는 방법

__attribute__ ((section (".bootloader")))

이 예제에서, .bootloader는 새로운 섹션의 이름이다.

void boot(void) __attribute__ ((section (".bootloader")));

고정된 주소에 섹션을 재배치 시키기 위해서는  --section-start  링커 flag이 사용된다.

이 옵션은 링커에게 -Wl 컴파일러 옵션을 사용해서 전해질 수 있다. (This option can be passed to the linker using the -Wl compiler option:)

-Wl,--section-start=.bootloader=0x1E000

section-start 뒤에 있는 이름은 재배치할 섹션의 이름이다. 섹션 이름 뒤에 있는 숫자는 섹션의 시작주소이다.


11.19 My UART is generating nonsense! My ATmega128 keeps crashing! Port F

is completely broken!



11.20 Why do all my ”foo...bar” strings eat up the SRAM?





11.21 Why does the compiler compile an 8-bit operation that uses bitwise operators

into a 16-bit operation in assembly?




11.22 How to detect RAM memory and variable overlap problems?



11.23 Is it really impossible to program the ATtinyXX in C?



11.24 What is this ”clock skew detected” message?



11.25 Why are (many) interrupt flags cleared by writing a logical 1?



11.26 Why have ”programmed” fuses the bit value 0?




11.27 Which AVR-specific assembler operators are available?



11.28 Why are interrupts re-enabled in the middle of writing the stack pointer?



11.29 Why are there five different linker scripts?

From a comment in the source code:

Which one of the five linker script files is actually used depends on command line options given to ld.

A .x script file is the default script 

A .xr script is for linking without relocation (-r flag) 

A.xu script is like .xr but do create constructors (-Ur flag) 

A .xn script is for linking with -n flag (mix text and data on same page). 

A .xbn script is for linking with -N flag (mix text and data on same page).



11.30 How to add a raw binary image to linker output?



11.31 소프트웨어 리셋을 사용하려면?

소프트웨어 리셋을 허용하는 규정된 방법은 watch Dog Timer를 사용하는 것이다.

오래된 AVR 에서는 리셋시에 와치독 타이머가 disable된다. 이러한 경우에는 소프트 리셋된 다음에 다시 와치독 타이머를 enable시킨다. 

최근의 AVR에서는 한번 와치독 타이머가 enable되면, 리셋이 되더라도 설정이 유지된다. 

이러한 경우에는 와치독에 의해 AVR이 계속해서 리셋되는 것을 방지하기 위해 .init3 섹션에 와치독을 disable 하도록 함수를 추가해야 한다. 


#include <avr/wdt.h>

...

#define soft_reset() \

do{ \

wdt_enable(WDTO_15MS); \

for(;;) { \

} \

} while(0)


새로운 AVR에서 와치독 리셋후에 와치독 타이머를 중지시키도록 다음 코드를 사용할 수 있다.

#include <avr/wdt.h>

...

// Function Pototype

void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));

...

// Function Implementation

void wdt_init(void)

{

MCUSR = 0;

wdt_disable();

return;

}


11.32 I am using floating point math. Why is the compiled code so big? Why

does my code not work?




11.33 What pitfalls exist when writing reentrant code?



11.34 Why are some addresses of the EEPROM corrupted (usually address

zero)?




11.35 Why is my baud rate wrong?

AVR 데이터시트에 다음과 같은 공식이 있다. 

(F_CPU/(UART_BAUD_RATE*16L)-1)

이 공식이 모든 클럭 스피드에 대해 잘 동작하지는 않는다. 


다음 공식을 사용하라.

((F_CPU + UART_BAUD_RATE * 8L) / (UART_BAUD_RATE * 16L) - 1)


이것은 이미  <util/setbaud.h> 파일에 구현되어 있다.


11.36 128KByte 이상의 Flash 메모리를 가진 디바이스에서는 함수 포인터가 어떤식으로 동작하는가?

이 문제를 해결하기 위해서 반드시 컴파일러 커맨드라인에 -mrelax 옵션이 주어져야 한다. 



11.37 Why is assigning ports in a ”chain” a bad idea?

여러개의 IO 포트 레지스터에 0xff의 값을 할당하는 것을 생각해볼수 있다.

간단히 다음과 같이 구현될 수 있다.


DDRB = DDRD = 0xff;


C언어의 규칙에 따라서, 이것은 0xff를 DDRD에 할당하고 나서, DDRD의 값을 다시 읽은 다음 그 값을 DDRB에 할당한다.

컴파일러는 레지스터를 "volatile"로 선언하는 등의 최적화를 수행할 기회를 잃게 된다.

따라서 체인 형태로 IO Port를 할당하는 것은 피하는 것이 좋다

대신 다음과 같이 명시적으로 할당하라.


DDRB = 0xff;

DDRD = 0xff;