startupは一般的にはアセンブラで書かれるのですが、Cortex-MではCで書くこともできるようで、startup.cが公開されています。以下(そのまま引用)(自分の覚書用)
GitHubの公開場所は以下
cortex-uni-startup/startup.c at master · pfalcon/cortex-uni-startup · GitHub
linker scriptもかなりシンプルなので、これからはこのstartupを使うつもりです。
このstartup.cと先ほどのLチカを組み合わせてビルドして、BluePillで動作することを確認した。
/* * Unified Cortex Startup - C startup file * * This file is in public domain * * Put together by Paul Sokolovsky based on article by Vanya Sergeev * http://dev.frozeneskimo.com/notes/cortex_cmsis/ , GNU ld documentation * and numerous other public resources. * */ #include <stdint.h> /* Declare linker-defined symbols. The only thing of interest regarding these symbols is their *address*. uint32_t hints of alignment. */ extern uint32_t _end_text; extern uint32_t _start_data; extern uint32_t _end_data; extern uint32_t _start_bss; extern uint32_t _end_bss; extern uint32_t _start_stack; extern uint32_t _end_stack; /* C main function */ extern int main(void); /* Device-specific initialization function. Optional, any Cortex-M should be able to start up in its default mode on its own, though some may have errata for some peripherals (including PLL) which this function may "patch". */ extern void SystemInit(void); void Dummy_Handler(void); /* Cortex-M core interrupt handlers */ #define ALIAS(sym) __attribute__((weak, alias (sym))) void Reset_Handler(void); void NMI_Handler(void) ALIAS("Dummy_Handler"); void HardFault_Handler(void) ALIAS("Dummy_Handler"); void MemManage_Handler(void) ALIAS("Dummy_Handler"); void BusFault_Handler(void) ALIAS("Dummy_Handler"); void UsageFault_Handler(void) ALIAS("Dummy_Handler"); void SVC_Handler(void) ALIAS("Dummy_Handler"); void DebugMon_Handler(void) ALIAS("Dummy_Handler"); void PendSV_Handler(void) ALIAS("Dummy_Handler"); void SysTick_Handler(void) ALIAS("Dummy_Handler"); /* 16 standard Cortex-M vectors - these are present in every MCU */ void *core_vector_table[16] __attribute__ ((section(".cortex_vectors"))) = { // See http://sourceware.org/binutils/docs/ld/Source-Code-Reference.html // why the address is used here (if not intuitive) &_end_stack, Reset_Handler, NMI_Handler, HardFault_Handler, MemManage_Handler, BusFault_Handler, UsageFault_Handler, 0, 0, 0, 0, SVC_Handler, DebugMon_Handler, 0, PendSV_Handler, SysTick_Handler, }; /* Based on http://sourceware.org/binutils/docs/ld/Output-Section-LMA.html */ void Reset_Handler(void) { register uint32_t *src, *dst; /* Copy data section from flash to RAM */ src = &_end_text; dst = &_start_data; while (dst < &_end_data) *dst++ = *src++; /* Clear the bss section, assumes .bss goes directly after .data */ dst = &_start_bss; while (dst < &_end_bss) *dst++ = 0; #ifndef NO_SYSTEMINIT SystemInit(); #endif main(); while (1); } void Dummy_Handler(void) { /* Receiving an unexpected interrupt is considered a bug in the program. Let's make it very visible by just hanging the processing. Ignoring it by just returning may result in very complicated debugging sessions. */ while (1); }
以下がBluePill用のLチカメイン
/* * LED Blink Test for the STM32F103C8 * * original source : Author : Chuck McManis * http://robotics.mcmanis.com/src/arm-blink/blink-example.html * */ #include <stdint.h> #define GPIOC 0x40011000ul #define GPIOC_CRL (*(uint32_t *)(GPIOC+0x00ul)) #define GPIOC_CRH (*(uint32_t *)(GPIOC+0x04ul)) #define GPIOC_IDR (*(uint32_t *)(GPIOC+0x08ul)) #define GPIOC_ODR (*(uint32_t *)(GPIOC+0x0cul)) #define GPIOC_BSRR (*(uint32_t *)(GPIOC+0x10ul)) #define GPIOC_BRR (*(uint32_t *)(GPIOC+0x14ul)) #define GPIOC_LCKR (*(uint32_t *)(GPIOC+0x14ul)) #define RCC_BASE 0x40021000ul #define RCC_APB2ENR (*(uint32_t *)(RCC_BASE + 0x18ul)) #define GPIOC_ENA 0x01 << 4 // C:bit4 #define GPIOC_13 13 #define GPIOC_8 8 #define OUT10MH 0x01 #define CNF13_GENPP 0x00000000ul #define MODE13_OUT10MH OUT10MH << ((GPIOC_13 - GPIOC_8) *4) #define DELAY_TIME 300000 volatile int var; void wait(int delay_time); void blink(void); void main() { blink(); // infinit loop while(1) ; } void blink(void){ // setup GPIOC PORT RCC_APB2ENR = GPIOC_ENA; // Enable clocks to GPIOC GPIOC_CRH = CNF13_GENPP | MODE13_OUT10MH; // set GPIOC_13 as OUTPUT GPIOC_BSRR = 1 << GPIOC_13 ; //LED off while (1) { GPIOC_BRR = 1 << GPIOC_13; // LED on wait(DELAY_TIME); GPIOC_BSRR = 1 << GPIOC_13 ; //LED off wait(DELAY_TIME); } } void wait(int delay_time){ unsigned int i = delay_time; while(i--){ asm("nop"); } }