We are developing for the STM32F103 MCU. We use bare-metal C++ code with the ARM GCC toolchain. After some hours of struggling with a suspicious expression, we found that the constant keyword triggers different results of that expression. When testing the same piece of code with the x86 GCC toolchain, the problem is nonexistent.
We are using the STM's GPIOS for debugging.
This is the code that 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 that code compiles, we are expecting the result 0b111110 at the GPIOS. When we change
const unsigned short RTC_FREQ = 62500;
to
unsigned short RTC_FREQ = 62500;
we get 0b111111111.
This is the Makefile that 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
Does anybody have a clue what can cause a problem like that? Is that a compiler bug? Have we missed something?