Invalid C ++ Keyword Behavior

We are developing the MCU STM32F103. We use simple C ++ - code with the instrumental bundle ARM GCC. After several hours of dealing with a suspicious expression, we found that the keyword constant triggers different results for this expression. When testing the same piece of code using the x86 GCC toolchain, the problem does not exist.
We use STM GPIOS for debugging.
This is the code that fully reproduces the problem:

#include "stm32f10x.h"
#include "system_stm32f10x.h"

#include "stdlib.h"
#include "stdio.h"

  const unsigned short RTC_FREQ = 62500;
  unsigned short prescaler_1ms = RTC_FREQ/1000;

int main()
{

//********** Clock Init **********
   RCC->CFGR |= RCC_CFGR_ADCPRE_0 | RCC_CFGR_ADCPRE_1; // ADC prescaler
   RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Alternate Function I/O clock enable
   RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // I/O port C clock enable
   RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // I/O port A clock enable
   RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // ADC 1 interface clock enable
   RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // Timer 2 clock enable 
   RCC->AHBENR = RCC_AHBENR_DMA1EN; // DMA1 clock enable
   RCC->CSR = RCC_CSR_LSION; // Internal Low Speed oscillator enable
//********************************

/* GPIO Configuration */
   GPIOC->CRH = GPIO_CRH_MODE12_0; //GPIO Port C Pin 12 
   GPIOC->CRH |= GPIO_CRH_MODE13_1 | GPIO_CRH_MODE13_0;
   GPIOC->CRH |= GPIO_CRH_MODE10_0;
   GPIOC->CRH |= GPIO_CRH_MODE9_0;
   GPIOC->CRH |= GPIO_CRH_MODE8_0;
   GPIOC->CRL = GPIO_CRL_MODE7_0;
   GPIOC->CRL |= GPIO_CRL_MODE6_0;
   GPIOC->CRL |= GPIO_CRL_MODE4_0;
   GPIOC->CRL |= GPIO_CRL_MODE3_0;


   while(1){

      if(prescaler_1ms & (1<<0))GPIOC->BSRR |= GPIO_BSRR_BR13;
      else GPIOC->BSRR |= GPIO_BSRR_BS13;
      if(prescaler_1ms & (1<<1))GPIOC->BSRR |= GPIO_BSRR_BR12;
      else GPIOC->BSRR |= GPIO_BSRR_BS12;
      if(prescaler_1ms & (1<<2))GPIOC->BSRR |= GPIO_BSRR_BR10;
      else GPIOC->BSRR |= GPIO_BSRR_BS10;
      if(prescaler_1ms & (1<<3))GPIOC->BSRR |= GPIO_BSRR_BR9;
      else GPIOC->BSRR |= GPIO_BSRR_BS9;
      if(prescaler_1ms & (1<<4))GPIOC->BSRR |= GPIO_BSRR_BR8;
      else GPIOC->BSRR |= GPIO_BSRR_BS8;
      if(prescaler_1ms & (1<<5))GPIOC->BSRR |= GPIO_BSRR_BR7;
      else GPIOC->BSRR |= GPIO_BSRR_BS7;
      if(prescaler_1ms & (1<<6))GPIOC->BSRR |= GPIO_BSRR_BR6;
      else GPIOC->BSRR |= GPIO_BSRR_BS6;
      if(prescaler_1ms & (1<<7))GPIOC->BSRR |= GPIO_BSRR_BR4;
      else GPIOC->BSRR |= GPIO_BSRR_BS4;
      if(prescaler_1ms & (1<<8))GPIOC->BSRR |= GPIO_BSRR_BR3;
      else GPIOC->BSRR |= GPIO_BSRR_BS3;

   }
   return 0;
}

When this code compiles, we expect the result 0b111110 in GPIOS. When we change

const unsigned short RTC_FREQ = 62500;  

to

unsigned short RTC_FREQ = 62500;  

we get 0b111111111 .
This is the Makefile we use:

EABI_PATH=$(ROOT_DIR)"arm_toolchain/gcc-arm-none-eabi-6-2017-q2-update/arm-none-eabi/"
CMSIS_INC_PATH=$(ROOT_DIR)"STMLib/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/"
PROJECT_INC=$(ROOT_DIR)

CXXINCS = -I$(EABI_PATH)"include" -I$(CMSIS_INC_PATH)"CoreSupport" -I$(CMSIS_INC_PATH)"DeviceSupport/ST/STM32F10x" -I$(PROJECT_INC)"Source" -I$(PROJECT_INC)"Includes"

CXXLIBS = -L$(EABI_PATH)"lib" -L$(EABI_PATH)"6.3.1"
CXXFLAGS = --specs=nosys.specs -DSTM32F10X_MD -DVECT_TAB_FLASH -fdata-sections -ffunction-sections -fno-exceptions -mthumb -mcpu=cortex-m3 -march=armv7-m -O2
LDFLAGS = -lstdc++ -Wl,--gc-sections

CC = $(EABI_PATH)"../bin/arm-none-eabi-gcc"
CXX = $(EABI_PATH)"../bin/arm-none-eabi-g++"
LD = $(EABI_PATH)"../bin/arm-none-eabi-ld"
STRIP = $(EABI_PATH)"../bin/arm-none-eabi-strip"

all:
        $(CC) $(CXXINCS) -c $(PROJECT_INC)"Source/syscalls.c" $(PROJECT_INC)"Source/startup.c" $(CXXFLAGS)
        $(CXX) $(CXXINCS) -c $(PROJECT_INC)"Source/main.cpp" $(CMSIS_INC_PATH)"DeviceSupport/ST/STM32F10x/system_stm32f10x.c" $(CXXFLAGS)
        $(CXX) $(CXXLIBS) -o main syscalls.o main.o startup.o -T linker.ld system_stm32f10x.o $(LDFLAGS)
        $(STRIP) --strip-all main
        $(EABI_PATH)"bin/objcopy" -O binary main app
        $(EABI_PATH)"bin/objdump" -b binary -m arm_any -D app > app_disasm
        rm -f *.o main adc timer task solenoid dma startup syscalls system_stm32f10x

- , ​​? ? - ?

+4
1

, LD script.

++, 62 prescaler_1ms, . RTC_FREQ const, , 62 .

++ _Z41__static_initialization_and_destruction_0ii. .init_array .pre_init_array. main() , . , script:

__preinit_array_start, __preinit_array_end
__init_array_start, __init_array_end

_preinit_array __init_array . _init, . _init, gcc, , , .

, ++ __fini_array_start __fini_array_end. , , .

++:

  • .init_array script.

, , , .init_array :

. = ALIGN(4);
__preinit_array_start = .;
KEEP(*(.preinit_array))
__preinit_array_end = .;

. = ALIGN(4);
__init_array_start = .;
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
__init_array_end = .;
  1. , . , , , .

( ) __Init_Data() startup.c:

// usually these are defined with __attribute__((weak)) but I prefer to get errors when required things are missing
extern void (*__preinit_array_start[])(void);
extern void (*__preinit_array_end[])(void);
extern void (*__init_array_start[])(void);
extern void (*__init_array_end[])(void);

void __Init_Data(void) {

    // copying initialized data from flash to RAM
    ...

    // zeroing bss segment
    ...

    // calling C++ initializers
    void (**f)(void);
    for (f = __preinit_array_start; f != __preinit_array_end; f++)
        (*f)();
    // init(); // _init and _fini do not work for me
    for (f = __init_array_start; f != __init_array_end; f++)
        (*f)();
}

, _init, . .

+5

Source: https://habr.com/ru/post/1689131/


All Articles