startup.c

Добавим основной заголовочный файл:

/* include headers */
#include "stm32f4xx.h"

Определим внешние переменные в том числе и начало стека(который необходим для работы С-кода):

/* external vars */
extern unsigned long _estack;

Также определим прототипы функций:

/* prototypes of functions */
void reset_hander(void);

Определим обработчик вектора сброса(куда мк придет следуя указаниям таблицы векторов) а также таблицу векторов:

/* reset handler */
void reset_handler(void) {
}
/* table of Cortex vectors */
void *vector_table[] __attribute__ ((section(".vectors"))) = {
    &_estack,
    reset_handler,
};

Следует отметить что в начале таблицы векторов как следует из теории загрузки мк идет адрес начала стека, а затем указатель на вектор сброса. Также для таблицы векторов задана своя секция - .vectors. Это сделанно для того чтобы вектора находились всегда в начале прошивки.