2014-10-10 8 views
3

저는 Arduino 대신 Arduino 부트 로더를 사용하기는하지만, 이 아닌 ATmega328p에서 실행되는 프로그램을 작성하고 있습니다. 그래도).avr-libc의 fprintf()가 즉시 충돌합니다.

는 I는 희망 명백한 방식으로 UART에 쓸 stdout을 설정 한 :

void uart_putc(char c) 
{ 
    // Turn LFs into CRLFs 
    if(c == '\n') 
    uart_putc('\r'); 

    while(!(UCSR0A & _BV(UDRE0))) 
    ; 

    UDR0 = c; 
} 

static int _putc(char c, FILE *_) 
{ 
    uart_putc(c); 
    return 0; 
} 

... 
    fdev_setup_stream(stdout, &_putc, NULL, _FDEV_SETUP_WRITE); 

나는 이제 fputcfputs 모든 작품을 잘 사용하여 내 프로그램을 작성합니다. snprintf()을 호출하여 서식이 지정된 문자열을 char buffer[16]으로 렌더링 한 다음 fputs()으로 렌더링 할 수도 있습니다. 이 모든 것들이 잘 작동합니다.

fputs("Hello, world\n", stdout); /* works fine */ 

char buffer[16]; 
snprintf(buffer, sizeof buffer, "Hello, %s\n", "world"); 
fputs(buffer, stdout);    /* also works fine */ 

그러나, 순간 나는 ATMEGA를 진정한 fprintf()stdout에 프로그램이 충돌을 수행하려고하고 재부팅 :

fprintf(stdout, "Hello, %s\n", "world"); 

심지어 여기에 초기 H를 출력하기 전에 즉시 충돌합니다.

누구나 누락 될 수있는 것을 제안 할 수 있습니까? snprintf()fputs() 모두 잘 작동하면 fprintf()이 작동하지 않을 수 있습니까?

+0

실행할 수있는 디버거가있는 시뮬레이터가 있는지 확인할 수 있습니다. –

+1

'fprintf'에 들어가서 크래시가 발생할 때까지 해체를 '걸음'합니다. 그런 다음 다시 실행하고 충돌을 유발하는 명령을 실행하기 직전에 레지스터보기를 열고 모든 레지스터를 복사 한 다음 여기에 게시하십시오. 또한 충돌을 일으키는 지침을 게시하십시오. 이것은 중요한 정보를 우리에게 제공 할 수 있습니다. BTW, 당신은'fputs'와 똑같이 할 수 있고, 하나가 어떻게 작동하고 다른 하나는 작동하지 않는지 스스로를 볼 수 있습니다. –

+0

printf 함수와 관련된 충돌로 인해 스택 오버플로가 발생합니다. 스택 크기를 늘려보십시오. – kkrambo

답변

0

fdev_setup_stream()을 사용하여 stdout의 할당을 업데이트합니다. documentation of fdev_setup_stream() 명시 적으로하지만 상태 :

참고 : 표준 스트림 어떤 과제가 fdev_setup_stream에 의해 수행되지 않습니다(). 표준 스트림을 사용하려면이 스트림을 사용자가 지정해야합니다.

동일한 문서는 code example for using stdio without malloc을 가리 킵니다. 코드는 두 가지를 제외하고 당신과 매우 비슷가 같습니다

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); 
  • stdout이 사용자 정의 스트림에 초기화 :

    1. 사용자 정의 스트림은 FDEV_SETUP_STREAM() 매크로를 사용하여 정의됩니다

      stdout = &mystdout; 
      

    내 생각에, 귀하의 대구 e가 초기화되지 않은 stdout 스트림을 사용 중입니다. 은 "표준 IO 시설 소개"(www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#details)의 상태 :

    표준 스트림 stdin, stdout 및 stderr이 제공되며, 그러나 C 표준과 달리 avr-libc는 적용 가능한 장치에 대한 지식이 없기 때문에 이러한 스트림은 응용 프로그램 시작시 미리 초기화되지 않았습니다.

    초기화되지 않은 경우 stdout을 사용하는 모든 함수 호출의 동작은 정의되지 않습니다.실제로 stdout이 가리키는 위치에 따라 일부 호출이 여전히 작동 할 수 있습니다.