├── .clang-format ├── .gitignore ├── Makefile ├── README.md ├── config.mk ├── lib ├── link.ld └── mem.ld ├── scripts ├── bytecode.mk ├── cortex-m0.mk ├── cortex-m0plus.mk ├── cortex-m3.mk ├── cortex-m4.mk ├── cortex-m7.mk └── native.mk └── src ├── main.c └── start.c /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -1 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: true 7 | AlignConsecutiveDeclarations: true 8 | AlignEscapedNewlines: Left 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: None 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: true 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | BeforeCatch: false 33 | BeforeElse: false 34 | IndentBraces: false 35 | SplitEmptyFunction: true 36 | SplitEmptyRecord: true 37 | SplitEmptyNamespace: true 38 | BreakBeforeBinaryOperators: None 39 | BreakBeforeBraces: Attach 40 | BreakBeforeInheritanceComma: false 41 | BreakBeforeTernaryOperators: true 42 | BreakConstructorInitializersBeforeComma: false 43 | BreakConstructorInitializers: BeforeColon 44 | BreakAfterJavaFieldAnnotations: false 45 | BreakStringLiterals: true 46 | ColumnLimit: 160 47 | CommentPragmas: '^ IWYU pragma:' 48 | CompactNamespaces: false 49 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 50 | ConstructorInitializerIndentWidth: 4 51 | ContinuationIndentWidth: 4 52 | Cpp11BracedListStyle: true 53 | DerivePointerAlignment: true 54 | DisableFormat: false 55 | ExperimentalAutoDetectBinPacking: false 56 | FixNamespaceComments: true 57 | ForEachMacros: 58 | - foreach 59 | - Q_FOREACH 60 | - BOOST_FOREACH 61 | IncludeCategories: 62 | - Regex: '^<.*\.h>' 63 | Priority: 1 64 | - Regex: '^<.*' 65 | Priority: 2 66 | - Regex: '.*' 67 | Priority: 3 68 | IncludeIsMainRegex: '([-_](test|unittest))?$' 69 | IndentCaseLabels: true 70 | IndentWidth: 2 71 | IndentWrappedFunctionNames: false 72 | JavaScriptQuotes: Leave 73 | JavaScriptWrapImports: true 74 | KeepEmptyLinesAtTheStartOfBlocks: false 75 | MacroBlockBegin: '' 76 | MacroBlockEnd: '' 77 | MaxEmptyLinesToKeep: 1 78 | NamespaceIndentation: None 79 | ObjCBlockIndentWidth: 2 80 | ObjCSpaceAfterProperty: false 81 | ObjCSpaceBeforeProtocolList: false 82 | PenaltyBreakAssignment: 2 83 | PenaltyBreakBeforeFirstCallParameter: 1 84 | PenaltyBreakComment: 300 85 | PenaltyBreakFirstLessLess: 120 86 | PenaltyBreakString: 1000 87 | PenaltyExcessCharacter: 1000000 88 | PenaltyReturnTypeOnItsOwnLine: 200 89 | PointerAlignment: Left 90 | ReflowComments: true 91 | SortIncludes: true 92 | SortUsingDeclarations: true 93 | SpaceAfterCStyleCast: false 94 | SpaceAfterTemplateKeyword: true 95 | SpaceBeforeAssignmentOperators: true 96 | SpaceBeforeParens: ControlStatements 97 | SpaceInEmptyParentheses: false 98 | SpacesBeforeTrailingComments: 2 99 | SpacesInAngles: false 100 | SpacesInContainerLiterals: true 101 | SpacesInCStyleCastParentheses: false 102 | SpacesInParentheses: false 103 | SpacesInSquareBrackets: false 104 | Standard: Auto 105 | TabWidth: 8 106 | UseTab: Never 107 | ... 108 | 109 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | *.elf 15 | *.bin 16 | *.lst 17 | *.rd 18 | *.map 19 | 20 | out/ 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include config.mk 2 | 3 | include scripts/$(BUILD_FLOW).mk 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | 3 | Use instread [LLVM embedded toolchain for Arm](https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm) from ARM-Software 4 | 5 | # cortex-m-llvm 6 | 7 | Cortex M with LLVM toolkit. 8 | 9 | Example firmware for cortex-m using LLVM toolchain. 10 | 11 | Tested well with LLVM/CLANG 6.0 or high from [LLVM download site](http://releases.llvm.org/download.html) 12 | 13 | # Usage 14 | 15 | This project provide a simple makefile set for working with LLVM/CLANG on cortex-m. 16 | Due to configure your target you need: 17 | 18 | - Modify `config.mk` with preferred parameters for your project (self explained into file) 19 | - Ensure memory configuration is correct for your MCU (on `lib/mem.ld`) 20 | - Ensure linker script is correct (review `lib/link.ld`) 21 | - Add vendor dependent reset vectors to `src/start.c` 22 | 23 | Next, add your sources to `src/*.c` or modify `Makefile` to include others directories 24 | 25 | ### Makefile targets 26 | - **all**: Compile and link all files. Produce **elf**, **bin**, list and map 27 | - **clean**: Remove compilation results 28 | - **size**: Print size of result binary 29 | - **list**: Create list file using objdump (llvm version) 30 | 31 | # Required packages 32 | 33 | - clang 6.0 or higher 34 | - llvm 6.0 or higher 35 | - lld 6.0 or higher 36 | -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | # Use command line to change prefix as: $> make PREFIX=/path/to/llvm/bin/prefix- 2 | PREFIX ?= 3 | # y: verbose output, other: silent mode 4 | VERBOSE ?= n 5 | # Project name 6 | PRJ := llvm-project 7 | # Linker script in lib/* 8 | LDSCRIPT := link.ld 9 | # Optimization level: 0, 1, 2, 3, fast, s, z, g 10 | OPT_LEVEL := z 11 | # Arch flags (translated to scripts/$(ARCH).mk) 12 | ARCH := cortex-m7 13 | # C standard: c89, c99, c11 14 | C_STD := c11 15 | # Debug level: 0, 1, 2, 3 16 | DBG_LEVEL := 3 17 | # Flow of build: bytecode, native 18 | BUILD_FLOW := bytecode 19 | -------------------------------------------------------------------------------- /lib/link.ld: -------------------------------------------------------------------------------- 1 | INCLUDE mem.ld 2 | 3 | ENTRY(Reset_Handler) 4 | 5 | SECTIONS 6 | { 7 | .text : { 8 | KEEP(*(.isr_vector)) 9 | *(.text*) 10 | KEEP(*(.init)) 11 | KEEP(*(.fini)) 12 | *crtbegin.o(.ctors) 13 | *crtbegin?.o(.ctors) 14 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 15 | *(SORT(.ctors.*)) 16 | *(.ctors) 17 | *crtbegin.o(.dtors) 18 | *crtbegin?.o(.dtors) 19 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 20 | *(SORT(.dtors.*)) 21 | *(.dtors) 22 | *(.rodata*) 23 | KEEP(*(.eh_frame*)) 24 | } > FLASH 25 | 26 | .ARM.extab : { 27 | *(.ARM.extab* .gnu.linkonce.armextab.*) 28 | } > FLASH 29 | 30 | __exidx_start = .; 31 | 32 | .ARM.exidx : { 33 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 34 | } > FLASH 35 | 36 | __exidx_end = .; 37 | __etext = .; 38 | 39 | .data : { 40 | __data_start__ = .; 41 | *(vtable) 42 | *(.data*) 43 | . = ALIGN(4); 44 | PROVIDE_HIDDEN (__preinit_array_start = .); 45 | KEEP(*(.preinit_array)) 46 | PROVIDE_HIDDEN (__preinit_array_end = .); 47 | 48 | . = ALIGN(4); 49 | /* init data */ 50 | PROVIDE_HIDDEN (__init_array_start = .); 51 | KEEP(*(SORT(.init_array.*))) 52 | KEEP(*(.init_array)) 53 | PROVIDE_HIDDEN (__init_array_end = .); 54 | 55 | 56 | . = ALIGN(4); 57 | /* finit data */ 58 | PROVIDE_HIDDEN (__fini_array_start = .); 59 | KEEP(*(SORT(.fini_array.*))) 60 | KEEP(*(.fini_array)) 61 | PROVIDE_HIDDEN (__fini_array_end = .); 62 | 63 | KEEP(*(.jcr*)) 64 | . = ALIGN(4); 65 | /* All data end */ 66 | __data_end__ = .; 67 | 68 | } > RAM AT>FLASH 69 | 70 | .bss : 71 | { 72 | . = ALIGN(4); 73 | __bss_start__ = .; 74 | *(.bss*) 75 | *(COMMON) 76 | . = ALIGN(4); 77 | __bss_end__ = .; 78 | } > RAM 79 | 80 | .heap : 81 | { 82 | __end__ = .; 83 | end = __end__; 84 | *(.heap*) 85 | __HeapLimit = .; 86 | } > RAM 87 | 88 | /* .stack_dummy section doesn't contains any symbols. It is only 89 | * used for linker to calculate size of stack sections, and assign 90 | * values to stack symbols later */ 91 | .stack_dummy : 92 | { 93 | *(.stack*) 94 | } > RAM 95 | 96 | /DISCARD/ : { 97 | *(.note.*) 98 | } 99 | 100 | /* Set stack top to end of RAM, and stack limit move down by 101 | * size of stack_dummy section */ 102 | __StackTop = ORIGIN(RAM) + LENGTH(RAM); 103 | __StackLimit = __StackTop - SIZEOF(.stack_dummy); 104 | PROVIDE(__stack = __StackTop); 105 | 106 | /* Check if data + heap + stack exceeds RAM limit */ 107 | ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") 108 | } 109 | -------------------------------------------------------------------------------- /lib/mem.ld: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1M 3 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 112K 4 | } 5 | -------------------------------------------------------------------------------- /scripts/bytecode.mk: -------------------------------------------------------------------------------- 1 | include scripts/$(ARCH).mk 2 | 3 | OUT := out 4 | CSRC:= $(wildcard src/*.c) 5 | OBJ := $(addprefix $(OUT)/, $(CSRC:.c=.o)) 6 | BCO := $(addprefix $(OUT)/, $(CSRC:.c=.bc)) 7 | 8 | CC = $(PREFIX)clang -emit-llvm 9 | BCLD = $(PREFIX)llvm-link 10 | BC2OBJ = $(PREFIX)llc --filetype=obj 11 | LD = $(PREFIX)ld.lld 12 | SIZE = $(PREFIX)llvm-size 13 | # LLVM PR35281 14 | COPY = $(PREFIX)llvm-objcopy 15 | DUMP = $(PREFIX)llvm-objdump 16 | RM = $(PREFIX)rm -fr 17 | 18 | TARGET:=$(OUT)/$(PRJ).elf 19 | TARGET_LST:=$(OUT)/$(PRJ).lst 20 | TARGET_BIN:=$(OUT)/$(PRJ).bin 21 | TARGET_MAP:=$(OUT)/$(PRJ).map 22 | 23 | CFLAGS := $(ARCH_FLAGS) 24 | CFLAGS += -ffreestanding 25 | CFLAGS += -O$(OPT_LEVEL) 26 | CFLAGS += -std=$(C_STD) 27 | CFLAGS += -Wall 28 | CFLAGS += -g$(DBG_LEVEL) 29 | 30 | LDFLAGS := --Bstatic 31 | LDFLAGS += --build-id 32 | LDFLAGS += --gc-sections 33 | LDFLAGS += --Map $(TARGET_MAP) 34 | LDFLAGS += --script $(LDSCRIPT) 35 | LDFLAGS += -Llib 36 | 37 | ifeq ($(VERBOSE),n) 38 | Q:=@ 39 | else 40 | Q:= 41 | endif 42 | 43 | all: $(TARGET_BIN) $(TARGET_LST) size 44 | 45 | $(OUT)/%.bc: %.c 46 | @echo CC $^ 47 | @mkdir -p $(dir $@) 48 | $(Q)$(CC) -o $@ $(CFLAGS) -c $< 49 | 50 | $(TARGET).bc: $(BCO) 51 | @echo BCLD $@ 52 | $(Q)$(BCLD) -o=$@ $(BCO) 53 | 54 | $(TARGET).o: $(TARGET).bc 55 | @echo BC to OBJ $< 56 | $(Q)$(BC2OBJ) -o=$@ $< 57 | 58 | $(TARGET): $(TARGET).o 59 | @echo LD $@ 60 | $(Q)$(LD) -o $@ $(LDFLAGS) $< 61 | 62 | $(TARGET_LST): $(TARGET) 63 | @echo LIST on $@ 64 | $(Q)$(DUMP) -x -s -S $< > $@ 65 | 66 | $(TARGET_BIN): $(TARGET) 67 | @echo COPY to $@ 68 | $(Q)$(COPY) -O binary $< $@ 69 | 70 | size: $(TARGET) 71 | $(Q)$(SIZE) $< 72 | 73 | clean: 74 | @echo CLEAN 75 | $(Q)$(RM) $(OUT) 76 | 77 | rebuild: clean all 78 | 79 | .PHONY: all clean list size rebuild 80 | -------------------------------------------------------------------------------- /scripts/cortex-m0.mk: -------------------------------------------------------------------------------- 1 | ARCH_FLAGS := --target=thumbv6m-unknown-none-eabi 2 | ARCH_FLAGS += -mthumb 3 | ARCH_FLAGS += -march=armv6m 4 | ARCH_FLAGS += -mcpu=cortex-m0 5 | ARCH_FLAGS += -mfloat-abi=soft 6 | ARCH_FLAGS += -mfpu=none 7 | -------------------------------------------------------------------------------- /scripts/cortex-m0plus.mk: -------------------------------------------------------------------------------- 1 | ARCH_FLAGS := --target=thumbv6m-unknown-none-eabi 2 | ARCH_FLAGS += -mthumb 3 | ARCH_FLAGS += -march=armv6m 4 | ARCH_FLAGS += -mcpu=cortex-m0plus 5 | ARCH_FLAGS += -mfloat-abi=soft 6 | ARCH_FLAGS += -mfpu=none 7 | -------------------------------------------------------------------------------- /scripts/cortex-m3.mk: -------------------------------------------------------------------------------- 1 | ARCH_FLAGS := --target=thumbv7m-unknown-none-eabi 2 | ARCH_FLAGS += -mthumb 3 | ARCH_FLAGS += -march=armv7m 4 | ARCH_FLAGS += -mcpu=cortex-m3 5 | ARCH_FLAGS += -mfloat-abi=soft 6 | ARCH_FLAGS += -mfpu=none 7 | -------------------------------------------------------------------------------- /scripts/cortex-m4.mk: -------------------------------------------------------------------------------- 1 | ARCH_FLAGS := --target=thumbv7em-unknown-none-eabi 2 | ARCH_FLAGS += -mthumb 3 | ARCH_FLAGS += -march=armv7e-m 4 | ARCH_FLAGS += -mcpu=cortex-m4 5 | ARCH_FLAGS += -mfloat-abi=hard 6 | ARCH_FLAGS += -mfpu=fpv4-sp-d16 7 | -------------------------------------------------------------------------------- /scripts/cortex-m7.mk: -------------------------------------------------------------------------------- 1 | ARCH_FLAGS := --target=thumbv7em-unknown-none-eabi 2 | ARCH_FLAGS += -mthumb 3 | ARCH_FLAGS += -march=armv7e-m 4 | ARCH_FLAGS += -mcpu=cortex-m7 5 | ARCH_FLAGS += -mfloat-abi=hard 6 | ARCH_FLAGS += -mfpu=fpv5-sp-d16 7 | -------------------------------------------------------------------------------- /scripts/native.mk: -------------------------------------------------------------------------------- 1 | include scripts/$(ARCH).mk 2 | 3 | OUT := out 4 | CSRC:= $(wildcard src/*.c) 5 | OBJ := $(addprefix $(OUT)/, $(CSRC:.c=.o)) 6 | 7 | CC = $(PREFIX)clang 8 | LD = $(PREFIX)ld.lld 9 | SIZE = $(PREFIX)llvm-size 10 | # LLVM PR35281 11 | COPY = $(PREFIX)llvm-objcopy 12 | DUMP = $(PREFIX)llvm-objdump 13 | 14 | TARGET:=$(OUT)/$(PRJ).elf 15 | TARGET_LST:=$(OUT)/$(PRJ).lst 16 | TARGET_BIN:=$(OUT)/$(PRJ).bin 17 | TARGET_MAP:=$(OUT)/$(PRJ).map 18 | 19 | CFLAGS := $(ARCH_FLAGS) 20 | CFLAGS += -ffreestanding 21 | CFLAGS += -O$(OPT_LEVEL) 22 | CFLAGS += -std=$(C_STD) 23 | CFLAGS += -Wall 24 | CFLAGS += -g$(DBG_LEVEL) 25 | 26 | LDFLAGS := --Bstatic 27 | LDFLAGS += --build-id 28 | LDFLAGS += --gc-sections 29 | LDFLAGS += --Map $(TARGET_MAP) 30 | LDFLAGS += --script $(LDSCRIPT) 31 | LDFLAGS += -Llib 32 | 33 | ifeq ($(VERBOSE),y) 34 | Q:= 35 | else 36 | Q:=@ 37 | endif 38 | 39 | all: $(TARGET_BIN) $(TARGET_LST) size 40 | 41 | $(OUT)/%.o: %.c 42 | @echo CC $^ 43 | @mkdir -p $(dir $@) 44 | $(Q)$(CC) -o $@ $(CFLAGS) -c $< 45 | 46 | $(TARGET): $(OBJ) 47 | @echo LD $@ 48 | $(Q)$(LD) -o $@ $(LDFLAGS) $(OBJ) 49 | 50 | $(TARGET_LST): $(TARGET) 51 | @echo LIST on $@ 52 | $(Q)$(DUMP) -x -s -S $< > $@ 53 | 54 | $(TARGET_BIN): $(TARGET) 55 | @echo COPY to $@ 56 | $(Q)$(COPY) -O binary $< $@ 57 | 58 | size: $(TARGET) 59 | $(Q)$(SIZE) $< 60 | 61 | clean: 62 | @echo CLEAN 63 | @rm -fR $(OUT) 64 | 65 | rebuild: clean all 66 | 67 | .PHONY: all clean list size rebuild 68 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #define VADDR(addr) (*((volatile unsigned int*)addr)) 2 | #define OUT VADDR(0xDEADBEEF) 3 | #define INP VADDR(0xCAFEBABE) 4 | 5 | int idx = 0; 6 | char buffer[1024]; 7 | 8 | int rand_start = 0x48A235E2; 9 | 10 | void SysTick_Handler() 11 | { 12 | buffer[idx] = rand_start; 13 | rand_start ^= (1 << 3) | (1 << 7); 14 | if (++idx > sizeof(buffer)) 15 | idx = 0; 16 | } 17 | 18 | int main() { 19 | for (int k = 0; k < INP; k++) 20 | OUT = k; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/start.c: -------------------------------------------------------------------------------- 1 | extern unsigned int __etext, __data_start__, __data_end__, __bss_start__, __bss_end__, __stack; 2 | 3 | extern int main(); 4 | 5 | void Default_Reset_Handler(void); 6 | void Default_Handler(void); 7 | 8 | _Noreturn void Default_Reset_Handler(void) { 9 | unsigned int *src = &__etext; 10 | unsigned int *dst = &__data_start__; 11 | 12 | /* ROM has data at end of text; copy it. */ 13 | while (dst < &__data_end__) 14 | *dst++ = *src++; 15 | 16 | /* Zero bss. */ 17 | for (dst = &__bss_start__; dst < &__bss_end__; dst++) 18 | *dst = 0; 19 | 20 | main(); 21 | 22 | while (1) 23 | __asm__ volatile ("WFI"); 24 | } 25 | 26 | _Noreturn void Default_Handler(void) { 27 | while (1) 28 | ; 29 | } 30 | 31 | void Reset_Handler(void) __attribute((weak, alias("Default_Reset_Handler"))); 32 | void NMI_Handler(void) __attribute((weak, alias("Default_Handler"))); 33 | void HardFault_Handler(void) __attribute((weak, alias("Default_Handler"))); 34 | void MemManage_Handler(void) __attribute((weak, alias("Default_Handler"))); 35 | void BusFault_Handler(void) __attribute((weak, alias("Default_Handler"))); 36 | void UsageFault_Handler(void) __attribute((weak, alias("Default_Handler"))); 37 | void SVCall_Handler(void) __attribute((weak, alias("Default_Handler"))); 38 | void DebugMon_Handler(void) __attribute((weak, alias("Default_Handler"))); 39 | void PendSV_Handler(void) __attribute((weak, alias("Default_Handler"))); 40 | void SysTick_Handler(void) __attribute((weak, alias("Default_Handler"))); 41 | 42 | __attribute__((section(".isr_vector"),used)) static void *vectors[] = { 43 | (void *)&__stack, 44 | (void *)&Reset_Handler, /* Reset Handler */ 45 | (void *)&NMI_Handler, /* NMI Handler */ 46 | (void *)&HardFault_Handler, /* Hard Fault Handler */ 47 | (void *)&MemManage_Handler, /* MPU Fault Handler */ 48 | (void *)&BusFault_Handler, /* Bus Fault Handler */ 49 | (void *)&UsageFault_Handler, /* Usage Fault Handler */ 50 | 0, /* Reserved */ 51 | 0, /* Reserved */ 52 | 0, /* Reserved */ 53 | 0, /* Reserved */ 54 | (void *)&SVCall_Handler, /* SVCall Handler */ 55 | (void *)&DebugMon_Handler, /* Debug Monitor Handler */ 56 | 0, /* Reserved */ 57 | (void *)&PendSV_Handler, /* PendSV Handler */ 58 | (void *)&SysTick_Handler, /* SysTick Handler */ 59 | }; 60 | --------------------------------------------------------------------------------