0

Some library I use in an embedded (STM32F103) project initializes it's structs with memset() which for some reason causes the program to stop responding/hang.

To test this I used:

typedef struct
{
    uint8_t b;
    uint8_t c;
} testStruct;

testStruct d = { .b = 0, .c = 0 };

memset(&d, 0, sizeof(d));

And sure enough this causes the same behavior. Using memset() on an array appears to work fine.

I have run out of ideas as to what the problem could be and even thought maybe its a memory alignment issue and tried using __attribute__((aligned(4),packed)) on the struct but this also did not help.

I am using GCC for ARM to compile the code:

arm-none-eabi-gcc -std=c11 --specs=nosys.specs -fno-exceptions -Wall -O0 -nostartfiles -mcpu=cortex-m0 -mthumb -mcpu=cortex-m3 -march=armv7-m -I %IncludeDir% -o %WorkingDir%bin\main.elf -T %WorkingDir%stm32f103c8t6.ld %WorkingDir%systick.c %WorkingDir%can.c %WorkingDir%uart.c %WorkingDir%fifo.c %WorkingDir%main.c %WorkingDir%libcanard\canard.c %LibDir%libopencm3_stm32f1.a

Any ideas as to what I am missing here?

EDIT:

Below is the full test code. My test is simple, I am blinking a LED. When memset() is present the code never reaches the main loop to start blinking the LED. When I comment memset() then the LED blinks.

#define STM32F1
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <string.h>
#include "systick.h"

void loopToggleLED(uint32_t tnow)
{
    static uint32_t tPrevToggleLoop;
    static bool LEDisOn;

    if ((tnow - tPrevToggleLoop) < 1000000)
        return;

    tPrevToggleLoop = tnow;

    if (!LEDisOn)
    {
        gpio_clear(GPIOC,GPIO13);       // LED on
        LEDisOn = true;
    }
    else
    {
        gpio_set(GPIOC,GPIO13);         // LED off
        LEDisOn = false;
    }   
}

int main()
{
    rcc_clock_setup_in_hse_8mhz_out_72mhz();
    // Enable GPIOC clock. 
    rcc_periph_clock_enable(RCC_GPIOC);

    // Set GPIO8 (in GPIO port C) to 'output push-pull'.
    gpio_set_mode(GPIOC,GPIO_MODE_OUTPUT_2_MHZ,
              GPIO_CNF_OUTPUT_PUSHPULL,GPIO13);

    systick_Init();

    typedef struct
    {
        uint8_t b;
        uint8_t c;
    } testStruct;

    testStruct d = { .b = 0, .c = 0 };

    // Commenting memset() below allows the code to enter the loop below and blink the LEDs
    memset(&d, 0, sizeof(d));

    uint32_t tnow;
    for (;;) 
    {
        tnow = systick_Micros();    
        loopToggleLED(tnow);            
    }

    return 0;
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
Avalan
  • 159
  • 1
  • 10
  • 2
    Strange: *why* are you using `memset` when you already initialised the `struct` members to `0`? There must be more to this: please post the [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) that shows complete code and will reproduce the problem. – Weather Vane Mar 28 '20 at 20:34
  • 1
    Are you sure this is related to `memset`? Does the program respond if you remove the `memset`? Is this the whole source, like `int main() { memset(...); }`? `-mcpu=cortex-m0 -mcpu=cortex-m3` looks strange. – KamilCuk Mar 28 '20 at 20:37
  • @WeatherVane The initialization part I added afterwards while testing to see if it makes any difference. But with or without it makes no difference, it keeps hanging. My guess is that in the library they use memset to also clear padded bytes. I will add the rest of the test code. – Avalan Mar 28 '20 at 20:47
  • @KamilCuk, jip when I remove the memset the program continues to execute. – Avalan Mar 28 '20 at 20:50
  • 1
    Is "continues to execute" equal to "respond"? I understood "respond" as your debugger being disconnected. What does it mean to "respond" then? How do you know that the code continues to execute? How do you know it stops at `memset`? How are you executing your code? On what platform? Did you debug it to find out that the incorrect instruction happens inside `memset` call and this is the reason you blame `memset`? Did you try placing a breakpoint right before `memset`? Please post a [MCVE]. – KamilCuk Mar 28 '20 at 20:52
  • 2
    What you're missing is that the bug is elsewhere in the program, and adding the `memset` just changes the observable behavior. – user3386109 Mar 28 '20 at 20:57
  • 1
    @KamilCuk, with continue to execute I mean that the program passes that point in the code. I don't have a debugger but for testing I am just flashing some LED after the memset(). When memset is present the LED is not flashing and when I remove it the LED flashes, so my assumption is that memset is the culprit. – Avalan Mar 28 '20 at 21:18
  • Your code _looks_ ok, should work. Connect the debugger and be sure what happens inside your code. Is it normal to compile with `-nostartfiles`? – KamilCuk Mar 28 '20 at 21:22
  • @KamilCuk, now that you mention it, I can't remember why added it. I will remove the flag, create a startup file and give it a try. Since it would mostly just perform the initialization and call main() do you think it could be related to why memset does not work as expected? – Avalan Mar 28 '20 at 21:51
  • Try to change the size of the struct and its members, for example use uint16_t for both; if it solves, then memset() is strangely broken, or a warning about its usage is missing somewhere. – linuxfan says Reinstate Monica Mar 29 '20 at 06:21

1 Answers1

0

Solved! As KamilCuk pointed out, I mistakenly used mcpu flags for both cortex-m0 and cortex-m3. After removing -mcpu=cortex-m0 memset works again as expected! Thanks for pointing it out and helping to solve this!

Avalan
  • 159
  • 1
  • 10