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

时间:2015-09-21 10:32:09

标签: c debugging avr avr-gcc

更新 - 改述问题:

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

旧版:

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

此代码中存在错误:它冻结了。我得到的就是这个输出......

  

Hello World - 正在加载

我应该为每个循环获得' +'

你能解释一下为什么冻结,为什么编译器没有告诉我有关静态分配比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 );
    }
}

1 个答案:

答案 0 :(得分:1)

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

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

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