0

I'm currently trying to get a better understanding of what is happening after power-on until I reach the main() function of an embedded project. Furthermore I'll try to understand how startup code and linker scripts are incorporated during build and startup procedure as I never learned these things properly.

So I read and watched a bunch of tutorials (QuantumLeaps, Fastbit, Interrupt, Teivaz,...) and I think I got a basic understanding of what is going on. To see if I really understood everything I tried the following:

For a STM32F0-Nucleo Board (STM32F072RB) I tried to create a bare-metal blinky LED project. The build toolchain I use is the arm-none-eabi-gcc compiler, GNU make and the CubeProgrammer by ST. I want it to be as basic as possible. So linker script, startup code and all the stuff should be self-written, no third party files by ST or other sources should be utilized.

As you can already imagine, I couldn't make it work but also am not sure of where the error resides or what I understood wrongly...

Here you can find the reference manual of the used MCU. And here are the files I wrote (inspired by the above mentioned tutorials):

Linker Script

ENTRY(Reset_Handler)

/*FLASH memory from 0x08000000 with 128K*/
/*RAM memory from 0x20000000 with 16K*/

MEMORY
{
  FLASH(rx) : ORIGIN =0x08000000, LENGTH = 128K
  SRAM(rwx) : ORIGIN =0x20000000, LENGTH = 16K 
}

SECTIONS
{
  .text :
  {
    KEEP(*(.vectors))
    *(.text)
    *(.text*)     /*Maybe?*/
    *(.rodata)
    *(.rodata*)
    . = ALIGN(4);
    _etext = .;
  }> FLASH /*AT> FLASH*/

  .data :
  {
    _sdata = .;
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  }> SRAM AT> FLASH

  .bss :
  {
    _sbss = .;
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    _ebss = .;
  }> SRAM 

}

I saw in the official STM linker scripts that there are always two entries for each section ( *(.bss) and *(.bss*)). I don't understand why this is the case, the tutorials I saw were also inconsistent with this. Can someone explain this to me?

Startup Code (shortend the list of the handlers for displaying reasons)

#include "device.h"

//Tracking variables for memory sections
extern uint32_t _etext;
extern uint32_t _sdata;
extern uint32_t _edata;
extern uint32_t _sbss;
extern uint32_t _ebss;

// Prototypes
extern int main (void);

// Vector Table Prototypes + Default Handler
void Reset_Handler(void);
void Default_Handler(void);
void NMI_Handler(void)  __attribute__((weak, alias("Default_Handler")));
void HardFault_Handler(void)    __attribute__((weak, alias("Default_Handler")));
void SVCall_Handler(void)   __attribute__((weak, alias("Default_Handler")));
void PendSV_Handler(void)   __attribute__((weak, alias("Default_Handler")));
void SysTick_Handler(void)  __attribute__((weak, alias("Default_Handler")));
.
.
.


#define SRAM_START  0x20000000U
#define SRAM_SIZE   (16U * 1024U) // 16KB
#define SRAM_END    ((SRAM_START)+(SRAM_SIZE))

#define STACK_START SRAM_END //Stack will grow from high to low 
//This can also be done in Linker script with PROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));

// Vector Array
 __attribute__ ((section(".vectors"))) uint32_t vectors[] = 
{
  (uint32_t)STACK_START, //First Entry holds address of initial Stack Pointer (MSP) which points at end of SRAM, note that only the address is kept here
    (uint32_t)&Reset_Handler,
    //(uint32_t)&NMI_Handler,
    //(uint32_t)&HardFault_Handler,
  (uint32_t)&NMI_Handler, //NMI Handler
  (uint32_t)&HardFault_Handler, //HardFault Handler (0x0000 000C)
  (uint32_t)0,
  (uint32_t)0,
  (uint32_t)0,
  (uint32_t)0,
  (uint32_t)0,
  (uint32_t)0,
  (uint32_t)0,
  (uint32_t)&SVCall_Handler, //SVCall (0x0000 002C)
  (uint32_t)0,
  (uint32_t)0,
  (uint32_t)&PendSV_Handler, //PendSV (0x000 0038)
  (uint32_t)&SysTick_Handler, //Systick
.
.
.
 
};

//Definitions

void Reset_Handler ( void )
{
  // Copy Data section to SRAM
  uint32_t size = (uint32_t)&_edata - (uint32_t)&_sdata;

  uint8_t *pDst = (uint8_t*)&_sdata; //SRAM
  uint8_t *pSrc = (uint8_t*)&_etext; //FLASH

  for(uint32_t i = 0 ; i<size ; i++)
  {
    *pDst++ = *pSrc++;
  };

  // Init bss section to 0
  size = (uint32_t)&_ebss - (uint32_t)&_sbss;
  pDst = (uint8_t*)&_sbss; //SRAM


  for(uint32_t i = 0 ; i<size ; i++)
  {
    *pDst++ = 0;
  };

  //Call Main
  main();
}

void Default_Handler(void)
{
  
}

The makefile:

CC=arm-none-eabi-gcc
CORE=cortex-m4
CFLAG= -c -mcpu=$(CORE) -std=gnu11 -mthumb -O0 -Wall -v -save-temps -fno-common 
LDFLAG= -mcpu=$(CORE) -mthumb -nostdlib -T mySTM32_linkerScript.ld -Wl,-Map=final.Map

all: main.o myStartup.o final.elf

main.o: main.c
        $(CC) $(CFLAG) -o $@ $^

myStartup.o: myStartup.c
        $(CC) $(CFLAG) -o $@ $^

final.elf: main.o myStartup.o
        $(CC) $(LDFLAG) -o $@ $^

clean:
        rm -rf *.o *.elf

test:
    echo "This works"

The main file:

/* Includes */

#include "device.h"

void delay (int a);

int main(void)
{
  
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN;

  GPIOA->MODER |= GPIO_MODER_MODER5_0;

  GPIOA->OTYPER &= ~GPIO_OTYPER_OT_5;

  GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5_0;

  GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR5_0;
  
  /* Infinite loop */

  while (1)
  {
    GPIOA->BSRR |= GPIO_BSRR_BS_5;
    delay(50000);
    GPIOA->BSRR |= GPIO_BSRR_BR_5;
    delay(50000);
  }
  return 0;
}

void delay (int a)
{
    int i,j;

    for (i=0 ; i < a ; i++)
    {
        j++;
    }
    return;
}

I tried this code inside the CubeIDE with the #include "stm32f72xx.h" and it worked without problems. LED is blinking and registers got set correctly.

Lastly the corresponding device header file

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;

#define     __IO    volatile          /*!< Defines 'read / write' permissions */

typedef struct
{
  __IO uint32_t CR;                   /*!< RCC clock control register,                                   Address offset: 0x00 */
  __IO uint32_t CFGR;                 /*!< RCC clock configuration register,                            Address offset: 0x04 */
  __IO uint32_t CIR;                  /*!< RCC clock interrupt register,                                Address offset: 0x08 */
  __IO uint32_t APB2RSTR;             /*!< RCC APB2 peripheral reset register,                          Address offset: 0x0C */
  __IO uint32_t APB1RSTR;             /*!< RCC APB1 peripheral reset register,                          Address offset: 0x10 */
  __IO uint32_t AHBENR;               /*!< RCC AHB peripheral clock register,                           Address offset: 0x14 */
  __IO uint32_t APB2ENR;              /*!< RCC APB2 peripheral clock enable register,                   Address offset: 0x18 */
  __IO uint32_t APB1ENR;              /*!< RCC APB1 peripheral clock enable register,                   Address offset: 0x1C */
  __IO uint32_t BDCR;                 /*!< RCC Backup domain control register,                          Address offset: 0x20 */
  __IO uint32_t CSR;                  /*!< RCC clock control & status register,                         Address offset: 0x24 */
  __IO uint32_t AHBRSTR;              /*!< RCC AHB peripheral reset register,                           Address offset: 0x28 */
  __IO uint32_t CFGR2;                /*!< RCC clock configuration register 2,                          Address offset: 0x2C */
  __IO uint32_t CFGR3;                /*!< RCC clock configuration register 3,                          Address offset: 0x30 */
  __IO uint32_t CR2;                  /*!< RCC clock control register 2,                                Address offset: 0x34 */
} RCC_TypeDef;

typedef struct
{
  __IO uint32_t MODER;                /*!< GPIO port mode register,                     Address offset: 0x00      */
  __IO uint32_t OTYPER;               /*!< GPIO port output type register,              Address offset: 0x04      */
  __IO uint32_t OSPEEDR;              /*!< GPIO port output speed register,             Address offset: 0x08      */
  __IO uint32_t PUPDR;                /*!< GPIO port pull-up/pull-down register,        Address offset: 0x0C      */
  __IO uint32_t IDR;                  /*!< GPIO port input data register,               Address offset: 0x10      */
  __IO uint32_t ODR;                  /*!< GPIO port output data register,              Address offset: 0x14      */
  __IO uint32_t BSRR;                 /*!< GPIO port bit set/reset register,      Address offset: 0x1A */
  __IO uint32_t LCKR;                 /*!< GPIO port configuration lock register,       Address offset: 0x1C      */
  __IO uint32_t AFR[2];               /*!< GPIO alternate function low register,  Address offset: 0x20-0x24 */
  __IO uint32_t BRR;                  /*!< GPIO bit reset register,                     Address offset: 0x28      */
} GPIO_TypeDef;

#define PERIPH_BASE                   0x40000000UL  
#define AHBPERIPH_BASE                (PERIPH_BASE + 0x00020000UL)
#define AHB2PERIPH_BASE               (PERIPH_BASE + 0x08000000UL)
#define RCC_BASE                      (AHBPERIPH_BASE + 0x00001000UL)
#define RCC                           ((RCC_TypeDef *) RCC_BASE)

#define GPIOA_BASE                    (AHB2PERIPH_BASE + 0x00000000UL)
#define GPIOA                         ((GPIO_TypeDef *) GPIOA_BASE)

#define RCC_AHBENR_GPIOAEN_Pos        (17U)                         
#define RCC_AHBENR_GPIOAEN_Msk        (0x1UL << RCC_AHBENR_GPIOAEN_Pos)         /*!< 0x00020000 */
#define RCC_AHBENR_GPIOAEN                       RCC_AHBENR_GPIOAEN_Msk         /*!< GPIOA clock enable */

#define GPIO_MODER_MODER5_Pos         (10U)                                  
#define GPIO_MODER_MODER5_Msk         (0x3UL << GPIO_MODER_MODER5_Pos)          /*!< 0x00000C00 */
#define GPIO_MODER_MODER5             GPIO_MODER_MODER5_Msk                  
#define GPIO_MODER_MODER5_0           (0x1UL << GPIO_MODER_MODER5_Pos)          /*!< 0x00000400 */
#define GPIO_MODER_MODER5_1           (0x2UL << GPIO_MODER_MODER5_Pos)          /*!< 0x00000800 */

#define GPIO_OTYPER_OT_5              (0x00000020U)  

#define GPIO_OSPEEDR_OSPEEDR5_Pos     (10U)                                  
#define GPIO_OSPEEDR_OSPEEDR5_Msk     (0x3UL << GPIO_OSPEEDR_OSPEEDR5_Pos)      /*!< 0x00000C00 */
#define GPIO_OSPEEDR_OSPEEDR5         GPIO_OSPEEDR_OSPEEDR5_Msk              
#define GPIO_OSPEEDR_OSPEEDR5_0       (0x1UL << GPIO_OSPEEDR_OSPEEDR5_Pos)      /*!< 0x00000400 */
#define GPIO_OSPEEDR_OSPEEDR5_1       (0x2UL << GPIO_OSPEEDR_OSPEEDR5_Pos)      /*!< 0x00000800 */

#define GPIO_OSPEEDER_OSPEEDR5        GPIO_OSPEEDR_OSPEEDR5
#define GPIO_OSPEEDER_OSPEEDR5_0      GPIO_OSPEEDR_OSPEEDR5_0
#define GPIO_OSPEEDER_OSPEEDR5_1      GPIO_OSPEEDR_OSPEEDR5_1

#define GPIO_PUPDR_PUPDR5_Pos         (10U)                                  
#define GPIO_PUPDR_PUPDR5_Msk         (0x3UL << GPIO_PUPDR_PUPDR5_Pos)          /*!< 0x00000C00 */
#define GPIO_PUPDR_PUPDR5             GPIO_PUPDR_PUPDR5_Msk                  
#define GPIO_PUPDR_PUPDR5_0           (0x1UL << GPIO_PUPDR_PUPDR5_Pos)          /*!< 0x00000400 */
#define GPIO_PUPDR_PUPDR5_1           (0x2UL << GPIO_PUPDR_PUPDR5_Pos)          /*!< 0x00000800 */

#define GPIO_BSRR_BS_5                (0x00000020U)   

#define GPIO_BSRR_BR_5                (0x00200000U)  

As you probably already realized, I was extremly lazy and just copied the relevant register defines from the official stm32f072 header.

After a "make all" the build proceeds without errors or warnings. The generated map file looks ok to me:

Memory Configuration

Name             Origin             Length             Attributes
FLASH            0x08000000         0x00020000         xr
SRAM             0x20000000         0x00004000         xrw
*default*        0x00000000         0xffffffff

Linker script and memory map

LOAD main.o
LOAD myStartup.o

.text           0x08000000      0x204
 *(.vectors)
 .vectors       0x08000000       0xc0 myStartup.o
                0x08000000                vectors
 *(.text)
 .text          0x080000c0       0xb4 main.o
                0x080000c0                main
                0x08000148                delay
 .text          0x08000174       0x90 myStartup.o
                0x08000174                Reset_Handler
                0x080001f8                EXTI2_3_Handler
                0x080001f8                SVCall_Handler
                0x080001f8                HardFault_Handler
                0x080001f8                SysTick_Handler
                0x080001f8                I2C1_Handler
                0x080001f8                PendSV_Handler
                0x080001f8                NMI_Handler
                0x080001f8                PVD_VDDIO2_Handler
                0x080001f8                WWDG_Handler
                0x080001f8                RTC_Handler
                0x080001f8                TIM1_CC_Handler
                0x080001f8                USART3_8_Handler
                0x080001f8                EXTI4_15_Handler
                0x080001f8                DMA_Ch4_7_Handler
                0x080001f8                TSC_Handler
                0x080001f8                FLASH_Handler
                0x080001f8                USB_Handler
                0x080001f8                TIM2_Handler
                0x080001f8                USART1_Handler
                0x080001f8                TIM3_Handler
                0x080001f8                Default_Handler
                0x080001f8                CEC_CAN_Handler
                0x080001f8                TIM17_Handler
                0x080001f8                EXTI0_1_Handler
                0x080001f8                SPI2_Handler
                0x080001f8                TIM16_Handler
                0x080001f8                DMA_Ch1_Handler
                0x080001f8                I2C2_Handler
                0x080001f8                TIM6_DAC_VDDIO2_Handler
                0x080001f8                TIM14_Handler
                0x080001f8                USART2_Handler
                0x080001f8                SPI1_Handler
                0x080001f8                RCC_CRS_Handler
                0x080001f8                TIM15_Handler
                0x080001f8                TIM7_Handler
                0x080001f8                TIM1_BRK_UP_Handler
                0x080001f8                ADC_COMP_Handler
                0x080001f8                DMA_Ch2_3_Handler
 *(.text*)
 *(.rodata)
 *(.rodata*)
                0x08000204                . = ALIGN (0x4)
                0x08000204                _etext = .

.glue_7         0x08000204        0x0
 .glue_7        0x08000204        0x0 linker stubs

.glue_7t        0x08000204        0x0
 .glue_7t       0x08000204        0x0 linker stubs

.vfp11_veneer   0x08000204        0x0
 .vfp11_veneer  0x08000204        0x0 linker stubs

.v4_bx          0x08000204        0x0
 .v4_bx         0x08000204        0x0 linker stubs

.iplt           0x08000204        0x0
 .iplt          0x08000204        0x0 main.o

.rel.dyn        0x08000204        0x0
 .rel.iplt      0x08000204        0x0 main.o

.data           0x20000000        0x0 load address 0x08000204
                0x20000000                _sdata = .
 *(.data)
 .data          0x20000000        0x0 main.o
 .data          0x20000000        0x0 myStartup.o
 *(.data*)
                0x20000000                . = ALIGN (0x4)
                0x20000000                _edata = .

.igot.plt       0x20000000        0x0 load address 0x08000204
 .igot.plt      0x20000000        0x0 main.o

.bss            0x20000000        0x0 load address 0x08000204
                0x20000000                _sbss = .
 *(.bss)
 .bss           0x20000000        0x0 main.o
 .bss           0x20000000        0x0 myStartup.o
 *(.bss*)
 *(COMMON)
                0x20000000                . = ALIGN (0x4)
                0x20000000                _ebss = .
OUTPUT(final.elf elf32-littlearm)
LOAD linker stubs

.comment        0x00000000       0x49
 .comment       0x00000000       0x49 main.o
                                 0x4a (size before relaxing)
 .comment       0x00000049       0x4a myStartup.o

.ARM.attributes
                0x00000000       0x2e
 .ARM.attributes
                0x00000000       0x2e main.o
 .ARM.attributes
                0x0000002e       0x2e myStartup.o

I still don't know what the additional added sections are for but decided to ingore them for the time being.

So I tried to load the .elf file onto my board using the CubeProgrammer but I see no blinking LED. The cube programmer has the option to access the registers and they also show that my code was not executed at all. Nonetheless I can see that the vector table handlers got set (all pointing to the default handler) like I would expect them to. (If wanted I can add screenshots).

Because of that, my guess would be, that there is something missing or wrong with my startup code, linker script and/or makefile...

I'm sorry for the long post but if you find the time, can someone please help me to get this project running and helping me understand what is going on behind the curtains?

Thank you in advance Best regards Evox402

edit(21-12-09):

final.elf:     file format elf32-littlearm


Disassembly of section .text:

08000000 <vectors>:
 8000000:   20004000    andcs   r4, r0, r0
 8000004:   08000175    stmdaeq r0, {r0, r2, r4, r5, r6, r8}
 8000008:   080001f9    stmdaeq r0, {r0, r3, r4, r5, r6, r7, r8}
 800000c:   080001f9    stmdaeq r0, {r0, r3, r4, r5, r6, r7, r8}
    ...
 800002c:   080001f9    stmdaeq r0, {r0, r3, r4, r5, r6, r7, r8}
    ...
 8000038:   080001f9    stmdaeq r0, {r0, r3, r4, r5, r6, r7, r8}
 800003c:   080001f9    stmdaeq r0, {r0, r3, r4, r5, r6, r7, r8}
 . . . .

 80000b8:   080001f9    stmdaeq r0, {r0, r3, r4, r5, r6, r7, r8}
 80000bc:   080001f9    stmdaeq r0, {r0, r3, r4, r5, r6, r7, r8}

080000c0 <main>:
 80000c0:   b580        push    {r7, lr}
 80000c2:   af00        add r7, sp, #0
 80000c4:   4b1f        ldr r3, [pc, #124]  ; (8000144 <main+0x84>)
 80000c6:   695b        ldr r3, [r3, #20]
 80000c8:   4a1e        ldr r2, [pc, #120]  ; (8000144 <main+0x84>)
 80000ca:   f443 3300   orr.w   r3, r3, #131072 ; 0x20000
 80000ce:   6153        str r3, [r2, #20]
 80000d0:   f04f 4390   mov.w   r3, #1207959552 ; 0x48000000
 80000d4:   681b        ldr r3, [r3, #0]
 80000d6:   f04f 4290   mov.w   r2, #1207959552 ; 0x48000000
 80000da:   f443 6380   orr.w   r3, r3, #1024   ; 0x400
 80000de:   6013        str r3, [r2, #0]
 80000e0:   f04f 4390   mov.w   r3, #1207959552 ; 0x48000000
 80000e4:   685b        ldr r3, [r3, #4]
 80000e6:   f04f 4290   mov.w   r2, #1207959552 ; 0x48000000
 80000ea:   f023 0320   bic.w   r3, r3, #32
 80000ee:   6053        str r3, [r2, #4]
 80000f0:   f04f 4390   mov.w   r3, #1207959552 ; 0x48000000
 80000f4:   689b        ldr r3, [r3, #8]
 80000f6:   f04f 4290   mov.w   r2, #1207959552 ; 0x48000000
 80000fa:   f443 6380   orr.w   r3, r3, #1024   ; 0x400
 80000fe:   6093        str r3, [r2, #8]
 8000100:   f04f 4390   mov.w   r3, #1207959552 ; 0x48000000
 8000104:   68db        ldr r3, [r3, #12]
 8000106:   f04f 4290   mov.w   r2, #1207959552 ; 0x48000000
 800010a:   f423 6380   bic.w   r3, r3, #1024   ; 0x400
 800010e:   60d3        str r3, [r2, #12]
 8000110:   f04f 4390   mov.w   r3, #1207959552 ; 0x48000000
 8000114:   699b        ldr r3, [r3, #24]
 8000116:   f04f 4290   mov.w   r2, #1207959552 ; 0x48000000
 800011a:   f043 0320   orr.w   r3, r3, #32
 800011e:   6193        str r3, [r2, #24]
 8000120:   f24c 3050   movw    r0, #50000  ; 0xc350
 8000124:   f000 f810   bl  8000148 <delay>
 8000128:   f04f 4390   mov.w   r3, #1207959552 ; 0x48000000
 800012c:   699b        ldr r3, [r3, #24]
 800012e:   f04f 4290   mov.w   r2, #1207959552 ; 0x48000000
 8000132:   f443 1300   orr.w   r3, r3, #2097152    ; 0x200000
 8000136:   6193        str r3, [r2, #24]
 8000138:   f24c 3050   movw    r0, #50000  ; 0xc350
 800013c:   f000 f804   bl  8000148 <delay>
 8000140:   e7e6        b.n 8000110 <main+0x50>
 8000142:   bf00        nop
 8000144:   40021000    andmi   r1, r2, r0

08000148 <delay>:
 8000148:   b480        push    {r7}
 800014a:   b085        sub sp, #20
 800014c:   af00        add r7, sp, #0
 800014e:   6078        str r0, [r7, #4]
 8000150:   2300        movs    r3, #0
 8000152:   60fb        str r3, [r7, #12]
 8000154:   e005        b.n 8000162 <delay+0x1a>
 8000156:   68bb        ldr r3, [r7, #8]
 8000158:   3301        adds    r3, #1
 800015a:   60bb        str r3, [r7, #8]
 800015c:   68fb        ldr r3, [r7, #12]
 800015e:   3301        adds    r3, #1
 8000160:   60fb        str r3, [r7, #12]
 8000162:   68fa        ldr r2, [r7, #12]
 8000164:   687b        ldr r3, [r7, #4]
 8000166:   429a        cmp r2, r3
 8000168:   dbf5        blt.n   8000156 <delay+0xe>
 800016a:   bf00        nop
 800016c:   3714        adds    r7, #20
 800016e:   46bd        mov sp, r7
 8000170:   bc80        pop {r7}
 8000172:   4770        bx  lr

08000174 <Reset_Handler>:
 8000174:   b580        push    {r7, lr}
 8000176:   b086        sub sp, #24
 8000178:   af00        add r7, sp, #0
 800017a:   4a1a        ldr r2, [pc, #104]  ; (80001e4 <Reset_Handler+0x70>)
 800017c:   4b1a        ldr r3, [pc, #104]  ; (80001e8 <Reset_Handler+0x74>)
 800017e:   1ad3        subs    r3, r2, r3
 8000180:   607b        str r3, [r7, #4]
 8000182:   4b19        ldr r3, [pc, #100]  ; (80001e8 <Reset_Handler+0x74>)
 8000184:   617b        str r3, [r7, #20]
 8000186:   4b19        ldr r3, [pc, #100]  ; (80001ec <Reset_Handler+0x78>)
 8000188:   613b        str r3, [r7, #16]
 800018a:   2300        movs    r3, #0
 800018c:   60fb        str r3, [r7, #12]
 800018e:   e00a        b.n 80001a6 <Reset_Handler+0x32>
 8000190:   693a        ldr r2, [r7, #16]
 8000192:   1c53        adds    r3, r2, #1
 8000194:   613b        str r3, [r7, #16]
 8000196:   697b        ldr r3, [r7, #20]
 8000198:   1c59        adds    r1, r3, #1
 800019a:   6179        str r1, [r7, #20]
 800019c:   7812        ldrb    r2, [r2, #0]
 800019e:   701a        strb    r2, [r3, #0]
 80001a0:   68fb        ldr r3, [r7, #12]
 80001a2:   3301        adds    r3, #1
 80001a4:   60fb        str r3, [r7, #12]
 80001a6:   68fa        ldr r2, [r7, #12]
 80001a8:   687b        ldr r3, [r7, #4]
 80001aa:   429a        cmp r2, r3
 80001ac:   d3f0        bcc.n   8000190 <Reset_Handler+0x1c>
 80001ae:   4a10        ldr r2, [pc, #64]   ; (80001f0 <Reset_Handler+0x7c>)
 80001b0:   4b10        ldr r3, [pc, #64]   ; (80001f4 <Reset_Handler+0x80>)
 80001b2:   1ad3        subs    r3, r2, r3
 80001b4:   607b        str r3, [r7, #4]
 80001b6:   4b0f        ldr r3, [pc, #60]   ; (80001f4 <Reset_Handler+0x80>)
 80001b8:   617b        str r3, [r7, #20]
 80001ba:   2300        movs    r3, #0
 80001bc:   60bb        str r3, [r7, #8]
 80001be:   e007        b.n 80001d0 <Reset_Handler+0x5c>
 80001c0:   697b        ldr r3, [r7, #20]
 80001c2:   1c5a        adds    r2, r3, #1
 80001c4:   617a        str r2, [r7, #20]
 80001c6:   2200        movs    r2, #0
 80001c8:   701a        strb    r2, [r3, #0]
 80001ca:   68bb        ldr r3, [r7, #8]
 80001cc:   3301        adds    r3, #1
 80001ce:   60bb        str r3, [r7, #8]
 80001d0:   68ba        ldr r2, [r7, #8]
 80001d2:   687b        ldr r3, [r7, #4]
 80001d4:   429a        cmp r2, r3
 80001d6:   d3f3        bcc.n   80001c0 <Reset_Handler+0x4c>
 80001d8:   f7ff ff72   bl  80000c0 <main>
 80001dc:   bf00        nop
 80001de:   3718        adds    r7, #24
 80001e0:   46bd        mov sp, r7
 80001e2:   bd80        pop {r7, pc}
 80001e4:   20000000    andcs   r0, r0, r0
 80001e8:   20000000    andcs   r0, r0, r0
 80001ec:   08000204    stmdaeq r0, {r2, r9}
 80001f0:   20000000    andcs   r0, r0, r0
 80001f4:   20000000    andcs   r0, r0, r0

080001f8 <Default_Handler>:
 80001f8:   b480        push    {r7}
 80001fa:   af00        add r7, sp, #0
 80001fc:   bf00        nop
 80001fe:   46bd        mov sp, r7
 8000200:   bc80        pop {r7}
 8000202:   4770        bx  lr

Disassembly of section .comment:

00000000 <.comment>:
   0:   3a434347    bcc 10d0d24 <vectors-0x6f2f2dc>
   4:   4e472820    cdpmi   8, 4, cr2, cr7, cr0, {1}
   8:   72412055    subvc   r2, r1, #85 ; 0x55
   c:   6d45206d    stclvs  0, cr2, [r5, #-436] ; 0xfffffe4c
  10:   64646562    strbtvs r6, [r4], #-1378    ; 0xfffffa9e
  14:   54206465    strtpl  r6, [r0], #-1125    ; 0xfffffb9b
  18:   636c6f6f    cmnvs   ip, #444    ; 0x1bc
  1c:   6e696168    powvsez f6, f1, #0.0
  20:   2e303120    rsfcssp f3, f0, f0
  24:   30322d33    eorscc  r2, r2, r3, lsr sp
  28:   312e3132            ; <UNDEFINED> instruction: 0x312e3132
  2c:   31202930            ; <UNDEFINED> instruction: 0x31202930
  30:   2e332e30    mrccs   14, 1, r2, cr3, cr0, {1}
  34:   30322031    eorscc  r2, r2, r1, lsr r0
  38:   38303132    ldmdacc r0!, {r1, r4, r5, r8, ip, sp}
  3c:   28203432    stmdacs r0!, {r1, r4, r5, sl, ip, sp}
  40:   656c6572    strbvs  r6, [ip, #-1394]!   ; 0xfffffa8e
  44:   29657361    stmdbcs r5!, {r0, r5, r6, r8, r9, ip, sp, lr}^
    ...

Disassembly of section .ARM.attributes:

00000000 <.ARM.attributes>:
   0:   00002d41    andeq   r2, r0, r1, asr #26
   4:   61656100    cmnvs   r5, r0, lsl #2
   8:   01006962    tsteq   r0, r2, ror #18
   c:   00000023    andeq   r0, r0, r3, lsr #32
  10:   2d453705    stclcs  7, cr3, [r5, #-20]  ; 0xffffffec
  14:   0d06004d    stceq   0, cr0, [r6, #-308] ; 0xfffffecc
  18:   02094d07    andeq   r4, r9, #448    ; 0x1c0
  1c:   01140412    tsteq   r4, r2, lsl r4
  20:   03170115    tsteq   r7, #1073741829 ; 0x40000005
  24:   01190118    tsteq   r9, r8, lsl r1
  28:   061e011a            ; <UNDEFINED> instruction: 0x061e011a
  2c:   Address 0x0000002c is out of bounds.
Evox402
  • 111
  • 1
  • 13
  • What address is your cubeprogrammer flashing to? – bigwillydos Dec 08 '21 at 19:39
  • void delay (int a) { int i,j; make that volatile – old_timer Dec 09 '21 at 04:50
  • IMO not a good idea to do the pre-main() work in C, dont really care what the commercial folks do, their libraries are pretty horrible, just look at them. in any case, disassemble it and examine the vector table, post the first part of the table and some of the reset handler – old_timer Dec 09 '21 at 04:51
  • structs across compile domains is also a bad thing to do, but the current fad from the chip folks libraries unfortunately. the disassembly will tell all if there are any language/code issues. disassembly the delay function and you should see the problem there. – old_timer Dec 09 '21 at 04:52
  • Hello and thanks for your answers :) -bigwillydos: I cannot set the address but from the memory view it looks like all is set in the right places (vector table set to 0x0 which is mapped to 0x08000000). @old_timer Thanks for the answers, the problem is, I unfortunately am not familiar with assembly language, its on my bucket list but for the moment I cannot really read it. Regarding the structs: Could you elaborate why one shouldn't use them? And what would be the preferable way, defining absolut addresses for everything seems very cumbersome. – Evox402 Dec 09 '21 at 07:40
  • I added the volatile keyword to the delay variables but nothing changed. I added the disassembly to the main post. In the last line with the .ARM.attributes it tells that address 0x0000002C is out of bounds. But this should normally be the address of the SVCall handler. Is this related to the problem? – Evox402 Dec 09 '21 at 07:52
  • Forgot to ask, the reference manual tells the address for the Hardfault_Handler is 0x0000000C inside the vector table. The next entry would be the SVCall_Handler which is located at 0x0000002C. I filled the space inbetween with 0s, is this correct or should I inserted the Hardfault_Handler address for all entries till 0x0000002C? – Evox402 Dec 09 '21 at 13:37
  • no need to touch the otyper, ospeedr, nor pull up pull down you can remove those, just enable ioport a in the rcc and configure moder to push/pull. no reason to read/modify write bsrr that is the point of that register, simply write the value bsrr = value. – old_timer Dec 09 '21 at 22:30
  • so this is not optimized and that is fine. are you sure you have released the chip to run? is there a boot0 pin, how are you programming this into the flash, what kind of board is this is it a discovery or nucleo board for example? you are sure the led is on port a pin 5 yes? – old_timer Dec 09 '21 at 22:31
  • without a schematic I cant tell but what you can do is write the rcc to enable the port, write the moder and do one of the two bsrr writes (not or equal but just equal) then go into a while(1) continue; infinite loop, no need for other code in this experiment. sometimes based on board design you make the pin high to turn on the led, sometimes you make it low. so try setting pin 5 first with this simplified program if the led goes on then it should stay on. then recompile with the bsrr set to reset the pin, now it should be the opposite, if it was off before should stay on now... – old_timer Dec 09 '21 at 22:34
  • so far the output code looks fine, it really should have blinked. is the led glowing? on but not blinking? (As if you are going to fast?). so it does not appear yet to be a code problem but something else. is it programming the flash, is the chip coming of reset with the straps such that it boots from the flash (and not into the vendor bootloader). do you have the right gpio pin. stuff like that – old_timer Dec 09 '21 at 22:37
  • Thank you for your answer. I use a Nucleo-Board for the STM32F072RB and am programming it with the STM32CubeProgrammer. This tool has a memory viewer and I can verify that my Vector table was set into Flash on the correct addresses (at least I think that). I can also verify that none of the GPIO registers is set so my guess is, that my main code is not executed at all. I'm pretty confident that I have the correct Pin etc. as my code is running correctly when utilizing the STM32CubeIDE and the original device header file and startup code / linker script. – Evox402 Dec 10 '21 at 10:45
  • The programmer has the option to make a Fault analysis, it tells me that the DIV_0_TRP (divided by zero) bit was set. As I don't make a division I'm a bit confused... I also changed the code like you mentioned with no changes in the behaviour. – Evox402 Dec 10 '21 at 10:48
  • I continued to find the error but unfortunately without success. I could set up a OpenOCD debug session but my code seems to jump directly into a Hardfault_Handler. If I go step by step I somehow end up in main (for a single instruction) and then back to the hardfault handler. I cannot bring the debugger to show me if the reset_handler gets called at all. But it seems like there is something wrong with linker-script or startup code... – Evox402 Dec 14 '21 at 15:29

0 Answers0