avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Memory corruption (?) I don't understand


From: Trampas Stern
Subject: Re: Memory corruption (?) I don't understand
Date: Tue, 22 Jun 2021 14:10:17 -0400

So I would recommend that you put in the ASSERT for the LDL_PEDANTIC() macro. 

Secondly, you need to be careful with PROGMEM, that is with AVR being a Harvard machine you can burn up SRAM quickly by not using PROGMEM  for constants.  For example with the LDL library you need to be sure that LDL_ENABLE_AVR is defined.   

Note the AVR is a great processor, however I have personally not used one in about 15 years.  The price and ease of programming ARM Cortex M have gotten such AVR are no longer viable for new development as I can develop products so much faster with ARM Cortex M parts, and their power and price is comparable to AVR. 

Another trick you can do is inside a function do this: 

void printMem(void) {
   uint8_t *ptr;
   printf("stack 0x%X\n", &ptr); //this will be address on stack where ptr is.
   ptr=malloc(10);
   printf("heap 0x%X\n", ptr); //this will be address as to heap 
   free(ptr);
}

This will help as you can do some rough tracking of stack and heap usage, assuming the AVR linker script has stack growing from top of memory to end of heap it will help you check for stack overflow. 


  


On Tue, Jun 22, 2021 at 1:39 PM BERTRAND Joël <joel.bertrand@systella.fr> wrote:
        Strange. Following function runs as expected.

enum ldl_mac_status LDL_MAC_otaa(struct ldl_mac *self)
{
    enum ldl_mac_status retval;
    union ldl_mac_response_arg arg;

    LDL_PEDANTIC(self != NULL)

    if(self->ctx.joined){

        retval = LDL_STATUS_JOINED;
    }
    else if(self->op == LDL_OP_NONE){

        if(self->devNonce <= U32(UINT16_MAX)){

            forgetNetwork(self);

            self->trials = 0;

            self->day = U32(60) * U32(60) * U32(24) * timeTPS;

#if defined(LDL_ENABLE_L2_1_1)
            LDL_OPS_deriveJoinKeys(self);
#endif
            fillJoinBuffer(self, U16(self->devNonce));

            self->devNonce++;

            arg.dev_nonce_updated.nextDevNonce = self->devNonce;

unsigned char t[80];
sprintf(t, "self->handler=%p\r\n", self->handler);
            self->handler(self->app, LDL_MAC_DEV_NONCE_UPDATED, &arg);

            self->tx.power = 0;

            self->op = LDL_OP_JOINING;

            if(self->state == LDL_STATE_IDLE){

                self->state = LDL_STATE_WAIT_OTAA;
                LDL_MAC_timerSet(self, LDL_TIMER_WAITA, 0);
            }

            retval = LDL_STATUS_OK;

            LDL_DEBUG("OTAA is pending")
        }
        else{

            /* need to re-init with a different JoinEUI */
            retval = LDL_STATUS_DEVNONCE;
        }
    }
    else{

        retval = LDL_STATUS_BUSY;
    }

    return retval;
}

        If I comment out sprintf(), it crashes. If I deplace this debug trace
before or _after_ self->handler call, firmware runs as expected. I don't
understand. If there is a memory corruption somewhere, I could
understand that a debug trace _before_ the line that triggers the bug
can change something. But I don't understand why the following function
runs as expected :

enum ldl_mac_status LDL_MAC_otaa(struct ldl_mac *self)
{
    enum ldl_mac_status retval;
    union ldl_mac_response_arg arg;

    LDL_PEDANTIC(self != NULL)

    if(self->ctx.joined){

        retval = LDL_STATUS_JOINED;
    }
    else if(self->op == LDL_OP_NONE){

        if(self->devNonce <= U32(UINT16_MAX)){

            forgetNetwork(self);

            self->trials = 0;

            self->day = U32(60) * U32(60) * U32(24) * timeTPS;

#if defined(LDL_ENABLE_L2_1_1)
            LDL_OPS_deriveJoinKeys(self);
#endif
            fillJoinBuffer(self, U16(self->devNonce));

            self->devNonce++;

            arg.dev_nonce_updated.nextDevNonce = self->devNonce;

            self->handler(self->app, LDL_MAC_DEV_NONCE_UPDATED, &arg);

            self->tx.power = 0;

            self->op = LDL_OP_JOINING;

            if(self->state == LDL_STATE_IDLE){

                self->state = LDL_STATE_WAIT_OTAA;
                LDL_MAC_timerSet(self, LDL_TIMER_WAITA, 0);
            }

            retval = LDL_STATUS_OK;

            LDL_DEBUG("OTAA is pending")
        }
        else{

            /* need to re-init with a different JoinEUI */
            retval = LDL_STATUS_DEVNONCE;
        }
    }
    else{

        retval = LDL_STATUS_BUSY;
    }

unsigned char t[80];
sprintf(t, "self->handler=%p\r\n", self->handler);
    return retval;
}

        Of course, if I comment out :

unsigned char t[80];
sprintf(t, "self->handler=%p\r\n", self->handler);

it crashes again :

hilbert:[~/cvs/firmware-antivol] > simavr -t -vvv -m atmega1284 -f
16000000 firmware.elf
Loaded 95670 .text at address 0x0
Loaded 5654 .data
Loaded 2276 .eeprom
01..
..
=================..
 Systella L100-A..
=================..
..
Booting firmware 2021062218..
SPI initialized..
Reset LORA..
Reset LORA done..
LoRaWAN 1.1..
Initialization SX1262..
Initialization SX1262 done..
0000000000000000..
MAC initialization..
LDL_MAC_addChannel:790>chIndex=0 freq=868100000 minRate=0 maxRate=5..
LDL_MAC_addChannel:790>chIndex=1 freq=868300000 minRate=0 maxRate=5..
LDL_MAC_addChannel:790>chIndex=2 freq=868500000 minRate=0 maxRate=5..
cb type=11..
processInit:994>set radio reset: ticks=151..
processRadioReset:1009>clear radio reset: ticks=151..
MAC initialization done..
lora_send..
processStartRadioForEntropy:1061>listen for entropy: ticks=152..
processEntropy:1078>read entropy: ticks=152 entropy=0..
cb type=0..
LDL_MAC_ready..
LDL_MAC_otaa..
LDL_MAC_addChannel:790>chIndex=0 freq=868100000 minRate=0 maxRate=5..
LDL_MAC_addChannel:790>chIndex=1 freq=868300000 minRate=0 maxRate=5..
LDL_MAC_addChannel:790>chIndex=2 freq=868500000 minRate=0 maxRate=5..
avr_gdb_init listening on port 1234



reply via email to

[Prev in Thread] Current Thread [Next in Thread]