1

Update - Rephrase question:

Since I know what the bug is! How to know when statical allocation fails at compile time in embedded?

Older:

I have this simple and easy to understand code in "C" below running in Atmega328P-AU with 2K SRAM. I use a well behaved UART library( I used many during debugging ) to get debug strings in my PC terminal.

There is a bug in this code: It freezes. All I get is this output...

Hello World - Loading

I should get a '+' for every loop.

Can you explain me why is freezes and why the compiler does not inform me about allocating statically more memory than the uC can get.

In the code there are all the info you may need.

/**************************************************************************************************
   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 );
    }
}
13
  • 3
    As the compiler does not know how much RAM your target has, how should it warn? It is the linker which does the relocation and binding, so you have to check the linker command file. You might ahve specified the wrong target, the file might be wrong, etc.Anyway "my code freezed" is no specific error statement. Please fire up the debugger to get a more precise cause. Commented Sep 21, 2015 at 10:42
  • I use a USBasp programmer and a FTDI chip as a way to get strings from the uC. I do not have a debugger :( With the IDE simulator when I try to debug it freezes in the trird memset function. Commented Sep 21, 2015 at 10:54
  • "I do not have a debugger " and "when I try to debug it freezes" don't get together. There are debuggers available for AVR, just search. However, in the simulator, you should be able to inspect the status - that is exactly why you use it! Commented Sep 21, 2015 at 10:57
  • I learned programming by myself so many thinks that are obvious to other people I luck the understanding. Lets start from the beginning. By the phrase "freeze" I mean that the simulator is inside third memset function all the time and never gets to the next command. What do you mean about status? What to check? Commented Sep 21, 2015 at 11:03
  • 1
    @Olaf Likely he wants it to fail at compile time, which might be possible if you provide a suitable linker file. (At least you can do that for global memory) Commented Sep 21, 2015 at 15:09

1 Answer 1

1

The linker allocates the static storage, in your case 57 bytes (data plus bss segments). So as long as you have a too big variable with static storage, you should see an error message from the linker.

The variable temp[1000] is an automatic variable, it is allocated at run time on the stack. The RAM that is not statically allocated by the linker is used for the stack. This bug is an easy case, you are allocating a single variable that is bigger than the entire RAM of the device, but normally this kind of error is really really hard to detect. One solution is to check the available stack space at runtime. As a simple rule: don't allocate big stuff on the stack. You will only see it fail when that function is called.

temp[1000] is used for the entire runtime of the program, so you don't loose anything by just moving it into static storage. Put a "static" in front of it and you will (hopefully) see an error message from the linker.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.