c - AVR/GNU C 编译器和静态内存分配

标签 c debugging avr avr-gcc

更新 - 改写问题:

因为我知道错误是什么!如何知道嵌入式编译时静态分配何时失败?

年长者:

我在下面的“C”中有这个简单易懂的代码,它在带有 2K SRAM 的 Atmega328P-AU 中运行。我使用行为良好的 UART 库(我在调试期间使用了很多)在我的 PC 终端中获取调试字符串。

这段代码中有一个错误:它卡住了。我得到的只是这个输出...

Hello World - Loading

我应该为每个循环得到一个'+'

你能解释一下为什么是卡住的吗?为什么编译器没有通知我静态分配比 uC 可以获得的更多的内存。

代码中包含您可能需要的所有信息。

/**************************************************************************************************
   Info
**************************************************************************************************/
/*
    Device:     Atmega328P-AU - No arduino
    IDE:        Atmel Studio 6.2
    Compiler:   AVR/GNU C Compiler : 4.8.1
    F_CPU:      8000000 Hz defined in makefile
    Fuses:
                Extended:   0x07
                High:       0xD9
                Low:        0xE2
                Lockbit:    0xFF

    When compiled it show in build output these:            

           text    data     bss     dec     hex filename
           1088       0      57    1145     479 Bug Catcher.elf
           Done executing task "RunCompilerTask".
           Task "RunOutputFileVerifyTask"
           Program Memory Usage     :   1088 bytes   3,3 % Full
           Data Memory Usage        :   57 bytes   2,8 % Full
           Done executing task "RunOutputFileVerifyTask".
           Done building target "CoreBuild" in project "Bug Catcher.cproj".
           Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
           Target "Build" in file "C:\Program Files\Atmel\Atmel Studio 6.2\Vs\Avr.common.targets" from project "C:\Users\Tedi\Desktop\Bug Catcher\Bug Catcher\Bug Catcher.cproj" (entry point):
           Done building target "Build" in project "Bug Catcher.cproj".
           Done building project "Bug Catcher.cproj".

           Build succeeded.
           ========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

*/

/**************************************************************************************************
   Definitions
**************************************************************************************************/

#define BIG_NUMBER                  1000

// Atmega328P - Pin 12
#define SOFT_UART_RX_DDR            DDRB
#define SOFT_UART_RX_DDR_bit        DDB0
#define SOFT_UART_RX_PORT           PORTB
#define SOFT_UART_RX_PORT_bit       PORTB0
#define SOFT_UART_RX_PIN            PINB
#define SOFT_UART_RX_PIN_bit        PINB0

// Atmega328P Pin 13
#define SOFT_UART_TX_DDR            DDRB
#define SOFT_UART_TX_DDR_bit        DDB1
#define SOFT_UART_TX_PORT           PORTB
#define SOFT_UART_TX_PORT_bit       PORTB1
#define SOFT_UART_TX_PIN            PINB
#define SOFT_UART_TX_PIN_bit        PINB1

/**************************************************************************************************
   Includes
**************************************************************************************************/

#include "softuart.h"

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>

/**************************************************************************************************
   Main function
**************************************************************************************************/

int main()
{   
    /**********************************************************************************************
       Setup
    **********************************************************************************************/

    softuart_init(  &SOFT_UART_TX_DDR, SOFT_UART_TX_DDR_bit,
                    &SOFT_UART_TX_PORT, SOFT_UART_TX_PORT_bit,
                    &SOFT_UART_RX_DDR, SOFT_UART_RX_DDR_bit,
                    &SOFT_UART_RX_PIN, SOFT_UART_RX_PIN_bit );

    sei();

    softuart_puts_P( "\r\n\r\nHello World - Loading\r\n\r\n" ); // Can use custom UART function.
    _delay_ms( 200 );

    /**********************************************************************************************
       Forever loop
    **********************************************************************************************/
    while(1)
    {
        char temp[BIG_NUMBER];
        memset( temp, '\0', sizeof( temp ) );
        {
            char temp[BIG_NUMBER];
            memset( temp, '\0', sizeof( temp ) );
            {
                char temp[BIG_NUMBER];
                memset( temp, '\0', sizeof( temp ) );
            }
        }
        softuart_puts_P("+"); // BUG!!!!! It never reaches here.
        _delay_ms( 500 );
    }
}

最佳答案

链接器分配静态存储,在您的情况下为 57 个字节(数据加上 bss 段)。因此,只要您的静态存储变量太大,您就会看到链接器的错误消息。

temp[1000] 变量是一个自动变量,它在运行时分配在堆栈上。链接器未静态分配的 RAM 用于堆栈。这个错误很简单,你分配的是一个比设备整个 RAM 都大的变量,但通常这种错误真的很难检测到。一种解决方案是在运行时检查可用堆栈空间。作为一个简单的规则:不要在堆栈上分配大的东西。您只会在调用该函数时看到它失败。

temp[1000] 用于程序的整个运行时,因此您只需将它移入静态存储就不会丢失任何东西。在它前面放一个“static”,您将(希望)看到来自链接器的错误消息。

关于c - AVR/GNU C 编译器和静态内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32693013/

相关文章:

c++ - 由于未打包的非 POD 字段而忽略打包属性

C - 允许函数显示遇到错误的正确格式是什么?

c - Windows Defender 防病毒 API

c - 在 C 中编辑/修改和删除随机访问文件中的记录

c++ - 是否应该为没有副作用的丢弃值表达式发出诊断?

debugging - 在 lldb 中使用 `expr` 命令计算表达式时如何查看 printf 输出?

发布时的 android.util.Log - 我能做什么/不能做什么

c - 数据请求仅返回地址值(I2C)

C - 取消链接/删除对带空格的文件名产生错误

c - ATtiny85 上的 ws2812b