avr-libc上的fprintf()立即崩溃

时间:2014-10-10 20:47:06

标签: c microcontroller avr libc

我正在编写一个程序在ATmega328p上运行 - 裸avr-libc而不是Arduino,虽然它确实使用Arduino引导程序而不是串行(我不认为这会影响以下问题)。

我已设置stdout以希望明显的方式写入UART:

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 */

但是,当我尝试执行真正的fprintf()stdout时,程序会崩溃并重新启动ATmega:

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

在此处输出初始H之前,它会立即崩溃。

fprintf()snprintf()都可以正常工作时,有人可以提出可能会遗漏的内容,这会阻止fputs()工作吗?

1 个答案:

答案 0 :(得分:0)

您正在使用fdev_setup_stream()更新stdout的分配。 documentation of fdev_setup_stream()明确指出:

  

注意:   fdev_setup_stream()不会对标准流进行任何分配。   如果要使用标准流,则需要由用户分配这些流。

同一文件指向code example for using stdio without malloc。 除了两件事之外,那里的代码与你的代码非常相似:

  1. 使用宏FDEV_SETUP_STREAM()定义自定义流:

    static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
    
  2. stdout已初始化为此自定义流:

    stdout = &mystdout;
    
  3. 我认为,您的代码使用的是未初始化的stdout流。 "标准IO设施简介" (www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#details)声明:

      

    提供了标准流stdin,stdout和stderr,但与C标准相反,由于avr-libc不了解适用的设备,因此这些流在应用程序启动时尚未预先初始化。

    未初始化时,使用stdout的所有函数调用的行为未定义。根据{{​​1}}实际指向的位置,某些调用可能仍然有效。