commit e51451b7ed305f7aae17c3fc5df8ce60caa79061 Author: ayabusa Date: Sun Mar 24 13:35:27 2024 +0100 helow diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5c8a98d --- /dev/null +++ b/Makefile @@ -0,0 +1,77 @@ +TARGET = main + +# Directories +SRC_DIR = src +BUILD_DIR = build + +# Define the linker script location and chip architecture. +LD_SCRIPT = $(SRC_DIR)/linker.ld +MCU_SPEC = cortex-m0 + +# Toolchain definitions (ARM bare metal defaults) +TOOLCHAIN = /usr +CC = $(TOOLCHAIN)/bin/arm-none-eabi-gcc +AS = $(TOOLCHAIN)/bin/arm-none-eabi-as +LD = $(TOOLCHAIN)/bin/arm-none-eabi-ld +OC = $(TOOLCHAIN)/bin/arm-none-eabi-objcopy +OD = $(TOOLCHAIN)/bin/arm-none-eabi-objdump +OS = $(TOOLCHAIN)/bin/arm-none-eabi-size + +# Assembly directives. +ASFLAGS += -c +ASFLAGS += -O0 +ASFLAGS += -mcpu=$(MCU_SPEC) +ASFLAGS += -mthumb +ASFLAGS += -Wall +# (Set error messages to appear on a single line.) +ASFLAGS += -fmessage-length=0 + +# C compilation directives +CFLAGS += -mcpu=$(MCU_SPEC) +CFLAGS += -mthumb +CFLAGS += -Wall +CFLAGS += -g +# (Set error messages to appear on a single line.) +CFLAGS += -fmessage-length=0 +# (Set system to ignore semihosted junk) +CFLAGS += --specs=nosys.specs + +# Linker directives. +LSCRIPT = $(LD_SCRIPT) +LFLAGS += -mcpu=$(MCU_SPEC) +LFLAGS += -mthumb +LFLAGS += -Wall +LFLAGS += --specs=nosys.specs +LFLAGS += -nostdlib +LFLAGS += -lgcc +LFLAGS += -T$(LSCRIPT) + +VECT_TBL = $(SRC_DIR)/vector_table.S +AS_SRC = $(SRC_DIR)/core.S +C_SRC = $(SRC_DIR)/main.c + +OBJS = $(BUILD_DIR)/$(notdir $(VECT_TBL:.S=.o)) +OBJS += $(BUILD_DIR)/$(notdir $(AS_SRC:.S=.o)) +OBJS += $(BUILD_DIR)/$(notdir $(C_SRC:.c=.o)) + +.PHONY: all +all: $(BUILD_DIR)/$(TARGET).bin + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.S + $(CC) -x assembler-with-cpp $(ASFLAGS) $< -o $@ + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) -c $(CFLAGS) $(INCLUDE) $< -o $@ + +$(BUILD_DIR)/$(TARGET).elf: $(OBJS) + $(CC) $^ $(LFLAGS) -o $@ + +$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf + $(OC) -S -O binary $< $@ + $(OS) $< + +.PHONY: clean +clean: + rm -f $(BUILD_DIR)/*.o + rm -f $(BUILD_DIR)/$(TARGET).elf + rm -f $(BUILD_DIR)/$(TARGET).bin \ No newline at end of file diff --git a/build/core.o b/build/core.o new file mode 100644 index 0000000..220b643 Binary files /dev/null and b/build/core.o differ diff --git a/build/main.bin b/build/main.bin new file mode 100755 index 0000000..21b570c Binary files /dev/null and b/build/main.bin differ diff --git a/build/main.elf b/build/main.elf new file mode 100755 index 0000000..907ea0b Binary files /dev/null and b/build/main.elf differ diff --git a/build/main.o b/build/main.o new file mode 100644 index 0000000..1870a0e Binary files /dev/null and b/build/main.o differ diff --git a/build/vector_table.o b/build/vector_table.o new file mode 100644 index 0000000..4827e22 Binary files /dev/null and b/build/vector_table.o differ diff --git a/src/core.S b/src/core.S new file mode 100644 index 0000000..e17128d --- /dev/null +++ b/src/core.S @@ -0,0 +1,64 @@ +.syntax unified +.cpu cortex-m0 +.fpu softvfp +.thumb + +// Global values. +.global reset_handler + +/* + * The Reset handler. Called on reset. + */ +.type reset_handler, %function +reset_handler: + // Set the stack pointer to the end of the stack. + // The '_estack' value is defined in our linker script. + LDR r0, =_estack + MOV sp, r0 + + // Copy data from flash to RAM data init section. + // R2 will store our progress along the sidata section. + MOVS r0, #0 + // Load the start/end addresses of the data section, + // and the start of the data init section. + LDR r1, =_sdata + LDR r2, =_edata + LDR r3, =_sidata + B copy_sidata_loop + + copy_sidata: + // Offset the data init section by our copy progress. + LDR r4, [r3, r0] + // Copy the current word into data, and increment. + STR r4, [r1, r0] + ADDS r0, r0, #4 + + copy_sidata_loop: + // Unless we've copied the whole data section, copy the + // next word from sidata->data. + ADDS r4, r0, r1 + CMP r4, r2 + BCC copy_sidata + + // Once we are done copying the data section into RAM, + // move on to filling the BSS section with 0s. + MOVS r0, #0 + LDR r1, =_sbss + LDR r2, =_ebss + B reset_bss_loop + + // Zero out the BSS segment. + reset_bss: + // Store a 0 and increment by a word. + STR r0, [r1] + ADDS r1, r1, #4 + + reset_bss_loop: + // We'll use R1 to count progress here; if we aren't + // done, reset the next word and increment. + CMP r1, r2 + BCC reset_bss + + // Branch to the 'main' method. + B main +.size reset_handler, .-reset_handler diff --git a/src/linker.ld b/src/linker.ld new file mode 100644 index 0000000..9d6a016 --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,82 @@ +/* Label for the program's entry point */ +ENTRY(reset_handler) + +/* the end of the stack */ +_estack = 0x20018000; + +/* Set minimum size for stack and dynamic memory. */ +/* (The linker will generate an error if there is + * less than this much RAM leftover.) */ +/* (1KB) */ +_Min_Leftover_RAM = 0x400; + + +MEMORY +{ + FLASH (rx): ORIGIN = 0x08000000, LENGTH = 512K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 96K +} + +SECTIONS +{ + /* The vector table goes at the start of flash. */ + .vector_table : + { + . = ALIGN(4); + KEEP (*(.vector_table)) + . = ALIGN(4); + } >FLASH + /* The 'text' section contains the main program code. */ + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + . = ALIGN(4); + } >FLASH + /* The 'rodata' section contains read-only data, + * constants, strings, information that won't change. */ + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); + } >FLASH + /* The 'data' section is space set aside in RAM for + * things like variables, which can change. */ + _sidata = .; + .data : AT(_sidata) + { + . = ALIGN(4); + /* Mark start/end locations for the 'data' section. */ + _sdata = .; + *(.data) + *(.data*) + _edata = .; + . = ALIGN(4); + } >RAM + /* The 'bss' section is similar to the 'data' section, + * but its space is initialized to all 0s at the + * start of the program. */ + .bss : + { + . = ALIGN(4); + /* Also mark the start/end of the BSS section. */ + _sbss = .; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >RAM + /* Space set aside for the application's heap/stack. */ + .dynamic_allocations : + { + . = ALIGN(4); + _ssystem_ram = .; + . = . + _Min_Leftover_RAM; + . = ALIGN(4); + _esystem_ram = .; + } >RAM +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..21f4376 --- /dev/null +++ b/src/main.c @@ -0,0 +1,7 @@ +/* Main program. */ +int main(void) { + int val = 0; + while (1) { + val += 1; + } +} diff --git a/src/vector_table.S b/src/vector_table.S new file mode 100644 index 0000000..375a47c --- /dev/null +++ b/src/vector_table.S @@ -0,0 +1,329 @@ +// These instructions define attributes of our chip and +// the assembly language we'll use: +.syntax unified +.cpu cortex-m4 +.fpu softvfp +.thumb + +// Global memory locations. +.global vtable +.global Default_Handler + +/* + * The actual vector table. + */ +.type vtable, %object +.section .vector_table,"a",%progbits +vtable: + .word _estack + .word reset_handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word 0 /* Reserved */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word 0 /* Reserved */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word FPU_IRQHandler /* FPU */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word SPI4_IRQHandler /* SPI4 */ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + +.size vtable, .-vtable + +/* + * A 'Default' interrupt handler. This is where interrupts + * which are not otherwise configured will go. + * It is an infinite loop, because...well, we weren't + * expecting the interrupt, so what can we do? + */ +.section .text.Default_Handler,"ax",%progbits +Default_Handler: + default_interrupt_loop: + B default_interrupt_loop +.size Default_Handler, .-Default_Handler