├── .gitignore ├── .vscode ├── .cortex-debug.peripherals.state.json ├── .cortex-debug.registers.state.json ├── c_cpp_properties.json ├── launch.json └── settings.json ├── Makefile ├── README.md ├── STM32F103.svd ├── docs ├── Application Note (AN2606).pdf ├── AppsNote179.pdf ├── STM32F10xxx Flash programming manual (PM0075).pdf ├── Understanding STM32.pdf ├── cpp-on-stm32-cr.jpg ├── stm32f103c8-datasheet.pdf ├── stm32f103xx-manual.pdf └── stm32f10xx-programming-manual.pdf ├── include ├── cmsis_compiler.h ├── cmsis_gcc.h ├── cmsis_version.h ├── core_cm3.h ├── gpio.hpp ├── stm32f103xb.h ├── stm32f1xx.h └── system_stm32f1xx.h ├── src ├── gpio.cpp ├── main.cpp └── startup_stm32f103.cpp └── stm32f1.ld /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.vscode/.cortex-debug.peripherals.state.json: -------------------------------------------------------------------------------- 1 | [{"node":"GPIOC","expanded":true,"format":0,"pinned":false},{"node":"RCC","expanded":true,"format":0,"pinned":false}] -------------------------------------------------------------------------------- /.vscode/.cortex-debug.registers.state.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "${workspaceFolder}/include", 7 | 8 | ], 9 | "defines": [ 10 | "STM32F103xB" 11 | ], 12 | "macFrameworkPath": [], 13 | "compilerPath": "/Applications/ARM/bin/arm-none-eabi-gcc", 14 | "cStandard": "gnu17", 15 | "cppStandard": "gnu++14", 16 | "intelliSenseMode": "macos-gcc-arm" 17 | } 18 | ], 19 | "version": 4 20 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Cortex Debug", 9 | "cwd": "${workspaceFolder}", 10 | "executable": "./build/final.elf", 11 | "request": "launch", 12 | "type": "cortex-debug", 13 | "runToEntryPoint": "main", 14 | "servertype": "openocd", 15 | "configFiles": [ 16 | "interface/stlink.cfg", 17 | "target/stm32f1x.cfg" 18 | ], 19 | "svdFile": "${workspaceFolder}/STM32F103.svd", 20 | "armToolchainPath": "/Applications/ARM/bin/" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "stm32f103.h": "c", 4 | "system_stm32f1xx.h": "c", 5 | "stm31f1xx.h": "c" 6 | } 7 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET = final 2 | 3 | 4 | # Configure micro-controller 5 | MCU_FAMILY = STM32F103xB 6 | LDSCRIPT = stm32f1.ld 7 | CPU = cortex-m3 8 | INSTR_SET = thumb 9 | FLOAT_ABI = soft 10 | 11 | # compiler option 12 | OPT := -Os 13 | CSTD ?= c11 14 | CXXSTD := c++17 15 | 16 | # Project specific configuration 17 | BUILD_DIR := build 18 | BUILD_TYPE ?= Debug 19 | SRC_DIR := src 20 | INC_DIRS = include 21 | 22 | 23 | PREFIX ?= arm-none-eabi 24 | CC := $(PREFIX)-gcc 25 | CXX := $(PREFIX)-g++ 26 | LD := $(PREFIX)-gcc 27 | AR := $(PREFIX)-ar 28 | AS := $(PREFIX)-as 29 | SIZE := $(PREFIX)-size 30 | OBJCOPY := $(PREFIX)-objcopy 31 | OBJDUMP := $(PREFIX)-objdump 32 | GDB := $(PREFIX)-gdb 33 | 34 | # collect source files and generate object files 35 | SRCS := $(shell find $(SRC_DIR) -name '*.cpp' -or -name '*.c') 36 | OBJS := $(addsuffix .o,$(basename $(SRCS))) # replace .c with .o 37 | OBJS := $(addprefix $(BUILD_DIR)/,$(OBJS)) # replace .c with .o 38 | 39 | 40 | # Define stm32 family macro 41 | DEFS += -D$(MCU_FAMILY) 42 | 43 | # header library include flsgs 44 | INC_FLAGS = $(addprefix -I,$(INC_DIRS)) 45 | 46 | 47 | # Target-specific flags 48 | CPU_FLAGS ?= -mfloat-abi=$(FLOAT_ABI) -m$(INSTR_SET) -mcpu=$(CPU) 49 | 50 | CPPFLAGS ?=$(DEFS) $(INC_FLAGS) 51 | CFLAGS ?=$(CPU_FLAGS) $(OPT) 52 | CXXFLAGS :=$(CFLAGS) -fno-exceptions -fno-rtti 53 | LDFLAGS ?=$(CPU_FLAGS) 54 | 55 | # Do not link stdlib with executable 56 | CFLAGS += -nostdlib -fno-tree-loop-distribute-patterns -fdata-sections -ffunction-sections 57 | CXXFLAGS += -nostdlib -fno-tree-loop-distribute-patterns -fdata-sections -ffunction-sections 58 | LDFLAGS += -nostdlib -fno-tree-loop-distribute-patterns 59 | 60 | 61 | # Warning options for C and CXX compiler 62 | CFLAGS += -Wall -Wextra -Wundef -Wshadow -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes 63 | CXXFLAGS += -Wall -Wextra -Wundef -Wshadow -Wredundant-decls -Weffc++ -Werror 64 | 65 | 66 | LDFLAGS += -T $(LDSCRIPT) 67 | LDFLAGS += -Wl,-Map=$(basename $@).map 68 | 69 | all: bin size 70 | size: $(BUILD_DIR)/$(TARGET).size 71 | elf: $(BUILD_DIR)/$(TARGET).elf 72 | bin: $(BUILD_DIR)/$(TARGET).bin 73 | hex: $(BUILD_DIR)/$(TARGET).hex 74 | srec: $(BUILD_DIR)/$(TARGET).srec 75 | list: $(BUILD_DIR)/$(TARGET).list 76 | 77 | 78 | %.size: %.elf 79 | @$(SIZE) $< 80 | 81 | %.bin: %.elf 82 | @echo "COPY " $< " => " $@ 83 | @$(OBJCOPY) -Obinary $(*).elf $(*).bin 84 | 85 | $(BUILD_DIR)/%.o:%.c 86 | @mkdir -p $(dir $@) 87 | @echo "CC" $< " ==> " $@ 88 | $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< 89 | 90 | $(BUILD_DIR)/%.o:%.cpp 91 | @mkdir -p $(dir $@) 92 | @echo "CXX" $< " ==> " $@ 93 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $< 94 | 95 | $(BUILD_DIR)/$(TARGET).elf: $(OBJS) 96 | @echo "Linking sources into "$@ 97 | @$(CC) $(LDFLAGS) -o $@ $^ 98 | 99 | 100 | flash: bin 101 | st-flash write $(BUILD_DIR)/$(TARGET).bin 0x8000000 102 | 103 | debug: CFLAGS += -g -gdwarf-2 104 | debug: CXXFLAGS += -g -gdwarf-2 105 | debug: all 106 | 107 | clean: 108 | rm -rf build 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Writing Startup script for Cortex M controllers in C++ 2 | 3 | A definitive guide to developing the entire embedded C++ project for ARM Cortexm-M micro-controllers. This projects ais to provide as deep insight into the development of startup script in c++. 4 | 5 | ## Project Working 6 | 7 | This project configures SysTick timer and uses it to generate time accurate delay for blinking an LED. The onboard LED connected to pin C13 blinks every second. 8 | 9 | ## Dependencies 10 | 11 | * **make**\ 12 | Make utility is required for configuring and building this project. You can install make on linux by running command: 13 | 14 | ```bash 15 | sudo apt install build-essential 16 | ``` 17 | 18 | * **gcc-arm-none-eabi toolchain**\ 19 | ARM cross-platform toolchain is required to build applications for arm mcus. Toolchain can be installed by running following command: 20 | 21 | ```bash 22 | sudo apt install gcc-arm-none-eabi 23 | ``` 24 | 25 | * **openocd**\ 26 | It is an Open On Circuit Debugging tool used to flash and debug arm micro controllers. You can install openocd on linux by running command: 27 | 28 | ```bash 29 | sudo apt install openocd -y 30 | ``` 31 | 32 | * **st-link**\ 33 | This package is provided by STMicro-electronics for flashing the binary on the micro-controller 34 | 35 | ```bash 36 | sudo apt install stlink 37 | ``` 38 | 39 | * **Cortex Debug extension**\ 40 | This extension for VSCode is helpful for debugging the application on Blue Pill. The contents of registers as well as memory are visible in the context menu. 41 | Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter. 42 | 43 | ```bash 44 | ext install marus25.cortex-debug 45 | ``` 46 | 47 | ## Project Structure 48 | 49 | * `src` directory contains all source files for the project 50 | * `include` directory contains all header files for the project 51 | 52 | ### Source file description 53 | 54 | * `stm31f1.ld` - linker script for STM32F103 MCU 55 | * `src\main.cpp` - application code 56 | * `src\startup_stm32f103.cpp` - startup script in cpp 57 | * `include\gpio.hpp` - slibrary for handling gpio functions 58 | * `system_stm32f1xx.c` - clock configuration and system initialization functions 59 | * `STM32F103.svd` - contains the description of the system contained in Arm Cortex-M processor-based microcontrollers, in particular, the memory mapped registers of peripherals. 60 | 61 | ## Run Locally 62 | 63 | Running the project is super easy. Just clone, build, and flash. 64 | 65 | ### Clone the project 66 | 67 | 1. Using https 68 | 69 | ```bash 70 | git clone https://github.com/csrohit/stm32-startup-cpp.git 71 | cd stm32-startup-cpp 72 | ``` 73 | 74 | 2. Using ssh 75 | 76 | ```bash 77 | git clone git@github.com:csrohit/stm32-startup-cpp.git 78 | cd stm32-startup-cpp 79 | ``` 80 | 81 | ## Configuration 82 | 83 | All the configuration required for building this project is given below. 84 | 85 | 1. Build output directory 86 | In `Makefile`, output directory can be configured using variable `BUILD_DIR`. 87 | 88 | 2. Binary name 89 | In `Makefile`, the name of binary can be configured using variable `TARGET`. 90 | 91 | 3. MCU 92 | In `Makefile`, the target mcu can be selected by seting the following flags/variables 93 | * `MCU_FAMILY`: Specifies the family, it used to define a maco for inclusion of header files 94 | * `LD_SCRIPT`: Specifies path to linker script of the target controller 95 | * `INSTR_SET`: Specifies the instruction set to use. e.g. `thumb`, `arm`, etc 96 | * `FLOAT_ABI`: Specifies the floating point implementation 97 | * `CPU`: Specifies the processor on the MCU. e.g. `cortex-m3`, `cortex-m4`, etc 98 | 99 | ## Build 100 | 101 | Run following command in terminal to generate flashable binaries for blue pill board. Build files will be written to **Build Output Directory** as configured. 102 | 103 | ```bash 104 | make all 105 | ``` 106 | 107 | ## Flash 108 | 109 | 1. Connect STlink to PC and blue pill board using swd headers. 110 | 2. Put blue pill board in programming mode. 111 | 3. Run following to flash board with binary. 112 | 113 | ```C 114 | make flash 115 | ``` 116 | 117 | Output 118 | 119 | Onboard led connected to Pin C13 can be observed to be blinking every second. 120 | 121 | ## Debug 122 | 123 | 1. Run the following make command to build the program using debugging flags 124 | 125 | ```bash 126 | make debug 127 | ``` 128 | 129 | 2. Flash the controller using following command 130 | 131 | ```bash 132 | make flash 133 | ``` 134 | 135 | 3. Click in Run and Debug option in VsCode sidebar. Then launch Cortex Debug target. 136 | 137 | Happy debugging.... 138 | -------------------------------------------------------------------------------- /docs/Application Note (AN2606).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/Application Note (AN2606).pdf -------------------------------------------------------------------------------- /docs/AppsNote179.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/AppsNote179.pdf -------------------------------------------------------------------------------- /docs/STM32F10xxx Flash programming manual (PM0075).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/STM32F10xxx Flash programming manual (PM0075).pdf -------------------------------------------------------------------------------- /docs/Understanding STM32.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/Understanding STM32.pdf -------------------------------------------------------------------------------- /docs/cpp-on-stm32-cr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/cpp-on-stm32-cr.jpg -------------------------------------------------------------------------------- /docs/stm32f103c8-datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/stm32f103c8-datasheet.pdf -------------------------------------------------------------------------------- /docs/stm32f103xx-manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/stm32f103xx-manual.pdf -------------------------------------------------------------------------------- /docs/stm32f10xx-programming-manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/docs/stm32f10xx-programming-manual.pdf -------------------------------------------------------------------------------- /include/cmsis_compiler.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_compiler.h 3 | * @brief CMSIS compiler generic header file 4 | * @version V5.0.4 5 | * @date 10. January 2018 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2018 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #ifndef __CMSIS_COMPILER_H 26 | #define __CMSIS_COMPILER_H 27 | 28 | #include 29 | 30 | /* 31 | * Arm Compiler 4/5 32 | */ 33 | #if defined ( __CC_ARM ) 34 | #include "cmsis_armcc.h" 35 | 36 | 37 | /* 38 | * Arm Compiler 6 (armclang) 39 | */ 40 | #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 41 | #include "cmsis_armclang.h" 42 | 43 | 44 | /* 45 | * GNU Compiler 46 | */ 47 | #elif defined ( __GNUC__ ) 48 | #include "cmsis_gcc.h" 49 | 50 | 51 | /* 52 | * IAR Compiler 53 | */ 54 | #elif defined ( __ICCARM__ ) 55 | #include 56 | 57 | 58 | /* 59 | * TI Arm Compiler 60 | */ 61 | #elif defined ( __TI_ARM__ ) 62 | #include 63 | 64 | #ifndef __ASM 65 | #define __ASM __asm 66 | #endif 67 | #ifndef __INLINE 68 | #define __INLINE inline 69 | #endif 70 | #ifndef __STATIC_INLINE 71 | #define __STATIC_INLINE static inline 72 | #endif 73 | #ifndef __STATIC_FORCEINLINE 74 | #define __STATIC_FORCEINLINE __STATIC_INLINE 75 | #endif 76 | #ifndef __NO_RETURN 77 | #define __NO_RETURN __attribute__((noreturn)) 78 | #endif 79 | #ifndef __USED 80 | #define __USED __attribute__((used)) 81 | #endif 82 | #ifndef __WEAK 83 | #define __WEAK __attribute__((weak)) 84 | #endif 85 | #ifndef __PACKED 86 | #define __PACKED __attribute__((packed)) 87 | #endif 88 | #ifndef __PACKED_STRUCT 89 | #define __PACKED_STRUCT struct __attribute__((packed)) 90 | #endif 91 | #ifndef __PACKED_UNION 92 | #define __PACKED_UNION union __attribute__((packed)) 93 | #endif 94 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 95 | struct __attribute__((packed)) T_UINT32 { uint32_t v; }; 96 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 97 | #endif 98 | #ifndef __UNALIGNED_UINT16_WRITE 99 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 100 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) 101 | #endif 102 | #ifndef __UNALIGNED_UINT16_READ 103 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 104 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 105 | #endif 106 | #ifndef __UNALIGNED_UINT32_WRITE 107 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 108 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 109 | #endif 110 | #ifndef __UNALIGNED_UINT32_READ 111 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 112 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 113 | #endif 114 | #ifndef __ALIGNED 115 | #define __ALIGNED(x) __attribute__((aligned(x))) 116 | #endif 117 | #ifndef __RESTRICT 118 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 119 | #define __RESTRICT 120 | #endif 121 | 122 | 123 | /* 124 | * TASKING Compiler 125 | */ 126 | #elif defined ( __TASKING__ ) 127 | /* 128 | * The CMSIS functions have been implemented as intrinsics in the compiler. 129 | * Please use "carm -?i" to get an up to date list of all intrinsics, 130 | * Including the CMSIS ones. 131 | */ 132 | 133 | #ifndef __ASM 134 | #define __ASM __asm 135 | #endif 136 | #ifndef __INLINE 137 | #define __INLINE inline 138 | #endif 139 | #ifndef __STATIC_INLINE 140 | #define __STATIC_INLINE static inline 141 | #endif 142 | #ifndef __STATIC_FORCEINLINE 143 | #define __STATIC_FORCEINLINE __STATIC_INLINE 144 | #endif 145 | #ifndef __NO_RETURN 146 | #define __NO_RETURN __attribute__((noreturn)) 147 | #endif 148 | #ifndef __USED 149 | #define __USED __attribute__((used)) 150 | #endif 151 | #ifndef __WEAK 152 | #define __WEAK __attribute__((weak)) 153 | #endif 154 | #ifndef __PACKED 155 | #define __PACKED __packed__ 156 | #endif 157 | #ifndef __PACKED_STRUCT 158 | #define __PACKED_STRUCT struct __packed__ 159 | #endif 160 | #ifndef __PACKED_UNION 161 | #define __PACKED_UNION union __packed__ 162 | #endif 163 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 164 | struct __packed__ T_UINT32 { uint32_t v; }; 165 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 166 | #endif 167 | #ifndef __UNALIGNED_UINT16_WRITE 168 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 169 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 170 | #endif 171 | #ifndef __UNALIGNED_UINT16_READ 172 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 173 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 174 | #endif 175 | #ifndef __UNALIGNED_UINT32_WRITE 176 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 177 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 178 | #endif 179 | #ifndef __UNALIGNED_UINT32_READ 180 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 181 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 182 | #endif 183 | #ifndef __ALIGNED 184 | #define __ALIGNED(x) __align(x) 185 | #endif 186 | #ifndef __RESTRICT 187 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 188 | #define __RESTRICT 189 | #endif 190 | 191 | 192 | /* 193 | * COSMIC Compiler 194 | */ 195 | #elif defined ( __CSMC__ ) 196 | #include 197 | 198 | #ifndef __ASM 199 | #define __ASM _asm 200 | #endif 201 | #ifndef __INLINE 202 | #define __INLINE inline 203 | #endif 204 | #ifndef __STATIC_INLINE 205 | #define __STATIC_INLINE static inline 206 | #endif 207 | #ifndef __STATIC_FORCEINLINE 208 | #define __STATIC_FORCEINLINE __STATIC_INLINE 209 | #endif 210 | #ifndef __NO_RETURN 211 | // NO RETURN is automatically detected hence no warning here 212 | #define __NO_RETURN 213 | #endif 214 | #ifndef __USED 215 | #warning No compiler specific solution for __USED. __USED is ignored. 216 | #define __USED 217 | #endif 218 | #ifndef __WEAK 219 | #define __WEAK __weak 220 | #endif 221 | #ifndef __PACKED 222 | #define __PACKED @packed 223 | #endif 224 | #ifndef __PACKED_STRUCT 225 | #define __PACKED_STRUCT @packed struct 226 | #endif 227 | #ifndef __PACKED_UNION 228 | #define __PACKED_UNION @packed union 229 | #endif 230 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 231 | @packed struct T_UINT32 { uint32_t v; }; 232 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 233 | #endif 234 | #ifndef __UNALIGNED_UINT16_WRITE 235 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 236 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 237 | #endif 238 | #ifndef __UNALIGNED_UINT16_READ 239 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 240 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 241 | #endif 242 | #ifndef __UNALIGNED_UINT32_WRITE 243 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 244 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 245 | #endif 246 | #ifndef __UNALIGNED_UINT32_READ 247 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 248 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 249 | #endif 250 | #ifndef __ALIGNED 251 | #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. 252 | #define __ALIGNED(x) 253 | #endif 254 | #ifndef __RESTRICT 255 | #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. 256 | #define __RESTRICT 257 | #endif 258 | 259 | 260 | #else 261 | #error Unknown compiler. 262 | #endif 263 | 264 | 265 | #endif /* __CMSIS_COMPILER_H */ 266 | 267 | -------------------------------------------------------------------------------- /include/cmsis_gcc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_gcc.h 3 | * @brief CMSIS compiler GCC header file 4 | * @version V5.0.4 5 | * @date 09. April 2018 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2018 Arm Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #ifndef __CMSIS_GCC_H 26 | #define __CMSIS_GCC_H 27 | 28 | /* ignore some GCC warnings */ 29 | #pragma GCC diagnostic push 30 | #pragma GCC diagnostic ignored "-Wsign-conversion" 31 | #pragma GCC diagnostic ignored "-Wconversion" 32 | #pragma GCC diagnostic ignored "-Wunused-parameter" 33 | 34 | /* Fallback for __has_builtin */ 35 | #ifndef __has_builtin 36 | #define __has_builtin(x) (0) 37 | #endif 38 | 39 | /* CMSIS compiler specific defines */ 40 | #ifndef __ASM 41 | #define __ASM __asm 42 | #endif 43 | #ifndef __INLINE 44 | #define __INLINE inline 45 | #endif 46 | #ifndef __STATIC_INLINE 47 | #define __STATIC_INLINE static inline 48 | #endif 49 | #ifndef __STATIC_FORCEINLINE 50 | #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline 51 | #endif 52 | #ifndef __NO_RETURN 53 | #define __NO_RETURN __attribute__((__noreturn__)) 54 | #endif 55 | #ifndef __USED 56 | #define __USED __attribute__((used)) 57 | #endif 58 | #ifndef __WEAK 59 | #define __WEAK __attribute__((weak)) 60 | #endif 61 | #ifndef __PACKED 62 | #define __PACKED __attribute__((packed, aligned(1))) 63 | #endif 64 | #ifndef __PACKED_STRUCT 65 | #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) 66 | #endif 67 | #ifndef __PACKED_UNION 68 | #define __PACKED_UNION union __attribute__((packed, aligned(1))) 69 | #endif 70 | #ifndef __UNALIGNED_UINT32 /* deprecated */ 71 | #pragma GCC diagnostic push 72 | #pragma GCC diagnostic ignored "-Wpacked" 73 | #pragma GCC diagnostic ignored "-Wattributes" 74 | struct __attribute__((packed)) T_UINT32 { uint32_t v; }; 75 | #pragma GCC diagnostic pop 76 | #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) 77 | #endif 78 | #ifndef __UNALIGNED_UINT16_WRITE 79 | #pragma GCC diagnostic push 80 | #pragma GCC diagnostic ignored "-Wpacked" 81 | #pragma GCC diagnostic ignored "-Wattributes" 82 | __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; 83 | #pragma GCC diagnostic pop 84 | #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) 85 | #endif 86 | #ifndef __UNALIGNED_UINT16_READ 87 | #pragma GCC diagnostic push 88 | #pragma GCC diagnostic ignored "-Wpacked" 89 | #pragma GCC diagnostic ignored "-Wattributes" 90 | __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; 91 | #pragma GCC diagnostic pop 92 | #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) 93 | #endif 94 | #ifndef __UNALIGNED_UINT32_WRITE 95 | #pragma GCC diagnostic push 96 | #pragma GCC diagnostic ignored "-Wpacked" 97 | #pragma GCC diagnostic ignored "-Wattributes" 98 | __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; 99 | #pragma GCC diagnostic pop 100 | #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) 101 | #endif 102 | #ifndef __UNALIGNED_UINT32_READ 103 | #pragma GCC diagnostic push 104 | #pragma GCC diagnostic ignored "-Wpacked" 105 | #pragma GCC diagnostic ignored "-Wattributes" 106 | __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; 107 | #pragma GCC diagnostic pop 108 | #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) 109 | #endif 110 | #ifndef __ALIGNED 111 | #define __ALIGNED(x) __attribute__((aligned(x))) 112 | #endif 113 | #ifndef __RESTRICT 114 | #define __RESTRICT __restrict 115 | #endif 116 | 117 | 118 | /* ########################### Core Function Access ########################### */ 119 | /** \ingroup CMSIS_Core_FunctionInterface 120 | \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions 121 | @{ 122 | */ 123 | 124 | /** 125 | \brief Enable IRQ Interrupts 126 | \details Enables IRQ interrupts by clearing the I-bit in the CPSR. 127 | Can only be executed in Privileged modes. 128 | */ 129 | __STATIC_FORCEINLINE void __enable_irq(void) 130 | { 131 | __ASM volatile ("cpsie i" : : : "memory"); 132 | } 133 | 134 | 135 | /** 136 | \brief Disable IRQ Interrupts 137 | \details Disables IRQ interrupts by setting the I-bit in the CPSR. 138 | Can only be executed in Privileged modes. 139 | */ 140 | __STATIC_FORCEINLINE void __disable_irq(void) 141 | { 142 | __ASM volatile ("cpsid i" : : : "memory"); 143 | } 144 | 145 | 146 | /** 147 | \brief Get Control Register 148 | \details Returns the content of the Control Register. 149 | \return Control Register value 150 | */ 151 | __STATIC_FORCEINLINE uint32_t __get_CONTROL(void) 152 | { 153 | uint32_t result; 154 | 155 | __ASM volatile ("MRS %0, control" : "=r" (result) ); 156 | return(result); 157 | } 158 | 159 | 160 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 161 | /** 162 | \brief Get Control Register (non-secure) 163 | \details Returns the content of the non-secure Control Register when in secure mode. 164 | \return non-secure Control Register value 165 | */ 166 | __STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) 167 | { 168 | uint32_t result; 169 | 170 | __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); 171 | return(result); 172 | } 173 | #endif 174 | 175 | 176 | /** 177 | \brief Set Control Register 178 | \details Writes the given value to the Control Register. 179 | \param [in] control Control Register value to set 180 | */ 181 | __STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) 182 | { 183 | __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); 184 | } 185 | 186 | 187 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 188 | /** 189 | \brief Set Control Register (non-secure) 190 | \details Writes the given value to the non-secure Control Register when in secure state. 191 | \param [in] control Control Register value to set 192 | */ 193 | __STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) 194 | { 195 | __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); 196 | } 197 | #endif 198 | 199 | 200 | /** 201 | \brief Get IPSR Register 202 | \details Returns the content of the IPSR Register. 203 | \return IPSR Register value 204 | */ 205 | __STATIC_FORCEINLINE uint32_t __get_IPSR(void) 206 | { 207 | uint32_t result; 208 | 209 | __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); 210 | return(result); 211 | } 212 | 213 | 214 | /** 215 | \brief Get APSR Register 216 | \details Returns the content of the APSR Register. 217 | \return APSR Register value 218 | */ 219 | __STATIC_FORCEINLINE uint32_t __get_APSR(void) 220 | { 221 | uint32_t result; 222 | 223 | __ASM volatile ("MRS %0, apsr" : "=r" (result) ); 224 | return(result); 225 | } 226 | 227 | 228 | /** 229 | \brief Get xPSR Register 230 | \details Returns the content of the xPSR Register. 231 | \return xPSR Register value 232 | */ 233 | __STATIC_FORCEINLINE uint32_t __get_xPSR(void) 234 | { 235 | uint32_t result; 236 | 237 | __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); 238 | return(result); 239 | } 240 | 241 | 242 | /** 243 | \brief Get Process Stack Pointer 244 | \details Returns the current value of the Process Stack Pointer (PSP). 245 | \return PSP Register value 246 | */ 247 | __STATIC_FORCEINLINE uint32_t __get_PSP(void) 248 | { 249 | uint32_t result; 250 | 251 | __ASM volatile ("MRS %0, psp" : "=r" (result) ); 252 | return(result); 253 | } 254 | 255 | 256 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 257 | /** 258 | \brief Get Process Stack Pointer (non-secure) 259 | \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. 260 | \return PSP Register value 261 | */ 262 | __STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) 263 | { 264 | uint32_t result; 265 | 266 | __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); 267 | return(result); 268 | } 269 | #endif 270 | 271 | 272 | /** 273 | \brief Set Process Stack Pointer 274 | \details Assigns the given value to the Process Stack Pointer (PSP). 275 | \param [in] topOfProcStack Process Stack Pointer value to set 276 | */ 277 | __STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) 278 | { 279 | __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); 280 | } 281 | 282 | 283 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 284 | /** 285 | \brief Set Process Stack Pointer (non-secure) 286 | \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. 287 | \param [in] topOfProcStack Process Stack Pointer value to set 288 | */ 289 | __STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) 290 | { 291 | __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); 292 | } 293 | #endif 294 | 295 | 296 | /** 297 | \brief Get Main Stack Pointer 298 | \details Returns the current value of the Main Stack Pointer (MSP). 299 | \return MSP Register value 300 | */ 301 | __STATIC_FORCEINLINE uint32_t __get_MSP(void) 302 | { 303 | uint32_t result; 304 | 305 | __ASM volatile ("MRS %0, msp" : "=r" (result) ); 306 | return(result); 307 | } 308 | 309 | 310 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 311 | /** 312 | \brief Get Main Stack Pointer (non-secure) 313 | \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. 314 | \return MSP Register value 315 | */ 316 | __STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) 317 | { 318 | uint32_t result; 319 | 320 | __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); 321 | return(result); 322 | } 323 | #endif 324 | 325 | 326 | /** 327 | \brief Set Main Stack Pointer 328 | \details Assigns the given value to the Main Stack Pointer (MSP). 329 | \param [in] topOfMainStack Main Stack Pointer value to set 330 | */ 331 | __STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) 332 | { 333 | __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); 334 | } 335 | 336 | 337 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 338 | /** 339 | \brief Set Main Stack Pointer (non-secure) 340 | \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. 341 | \param [in] topOfMainStack Main Stack Pointer value to set 342 | */ 343 | __STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) 344 | { 345 | __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); 346 | } 347 | #endif 348 | 349 | 350 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 351 | /** 352 | \brief Get Stack Pointer (non-secure) 353 | \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. 354 | \return SP Register value 355 | */ 356 | __STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) 357 | { 358 | uint32_t result; 359 | 360 | __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); 361 | return(result); 362 | } 363 | 364 | 365 | /** 366 | \brief Set Stack Pointer (non-secure) 367 | \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. 368 | \param [in] topOfStack Stack Pointer value to set 369 | */ 370 | __STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) 371 | { 372 | __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); 373 | } 374 | #endif 375 | 376 | 377 | /** 378 | \brief Get Priority Mask 379 | \details Returns the current state of the priority mask bit from the Priority Mask Register. 380 | \return Priority Mask value 381 | */ 382 | __STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) 383 | { 384 | uint32_t result; 385 | 386 | __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); 387 | return(result); 388 | } 389 | 390 | 391 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 392 | /** 393 | \brief Get Priority Mask (non-secure) 394 | \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. 395 | \return Priority Mask value 396 | */ 397 | __STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) 398 | { 399 | uint32_t result; 400 | 401 | __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); 402 | return(result); 403 | } 404 | #endif 405 | 406 | 407 | /** 408 | \brief Set Priority Mask 409 | \details Assigns the given value to the Priority Mask Register. 410 | \param [in] priMask Priority Mask 411 | */ 412 | __STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) 413 | { 414 | __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); 415 | } 416 | 417 | 418 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 419 | /** 420 | \brief Set Priority Mask (non-secure) 421 | \details Assigns the given value to the non-secure Priority Mask Register when in secure state. 422 | \param [in] priMask Priority Mask 423 | */ 424 | __STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) 425 | { 426 | __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); 427 | } 428 | #endif 429 | 430 | 431 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 432 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 433 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 434 | /** 435 | \brief Enable FIQ 436 | \details Enables FIQ interrupts by clearing the F-bit in the CPSR. 437 | Can only be executed in Privileged modes. 438 | */ 439 | __STATIC_FORCEINLINE void __enable_fault_irq(void) 440 | { 441 | __ASM volatile ("cpsie f" : : : "memory"); 442 | } 443 | 444 | 445 | /** 446 | \brief Disable FIQ 447 | \details Disables FIQ interrupts by setting the F-bit in the CPSR. 448 | Can only be executed in Privileged modes. 449 | */ 450 | __STATIC_FORCEINLINE void __disable_fault_irq(void) 451 | { 452 | __ASM volatile ("cpsid f" : : : "memory"); 453 | } 454 | 455 | 456 | /** 457 | \brief Get Base Priority 458 | \details Returns the current value of the Base Priority register. 459 | \return Base Priority register value 460 | */ 461 | __STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) 462 | { 463 | uint32_t result; 464 | 465 | __ASM volatile ("MRS %0, basepri" : "=r" (result) ); 466 | return(result); 467 | } 468 | 469 | 470 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 471 | /** 472 | \brief Get Base Priority (non-secure) 473 | \details Returns the current value of the non-secure Base Priority register when in secure state. 474 | \return Base Priority register value 475 | */ 476 | __STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) 477 | { 478 | uint32_t result; 479 | 480 | __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); 481 | return(result); 482 | } 483 | #endif 484 | 485 | 486 | /** 487 | \brief Set Base Priority 488 | \details Assigns the given value to the Base Priority register. 489 | \param [in] basePri Base Priority value to set 490 | */ 491 | __STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) 492 | { 493 | __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); 494 | } 495 | 496 | 497 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 498 | /** 499 | \brief Set Base Priority (non-secure) 500 | \details Assigns the given value to the non-secure Base Priority register when in secure state. 501 | \param [in] basePri Base Priority value to set 502 | */ 503 | __STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) 504 | { 505 | __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); 506 | } 507 | #endif 508 | 509 | 510 | /** 511 | \brief Set Base Priority with condition 512 | \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, 513 | or the new value increases the BASEPRI priority level. 514 | \param [in] basePri Base Priority value to set 515 | */ 516 | __STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) 517 | { 518 | __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); 519 | } 520 | 521 | 522 | /** 523 | \brief Get Fault Mask 524 | \details Returns the current value of the Fault Mask register. 525 | \return Fault Mask register value 526 | */ 527 | __STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) 528 | { 529 | uint32_t result; 530 | 531 | __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); 532 | return(result); 533 | } 534 | 535 | 536 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 537 | /** 538 | \brief Get Fault Mask (non-secure) 539 | \details Returns the current value of the non-secure Fault Mask register when in secure state. 540 | \return Fault Mask register value 541 | */ 542 | __STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) 543 | { 544 | uint32_t result; 545 | 546 | __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); 547 | return(result); 548 | } 549 | #endif 550 | 551 | 552 | /** 553 | \brief Set Fault Mask 554 | \details Assigns the given value to the Fault Mask register. 555 | \param [in] faultMask Fault Mask value to set 556 | */ 557 | __STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) 558 | { 559 | __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); 560 | } 561 | 562 | 563 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 564 | /** 565 | \brief Set Fault Mask (non-secure) 566 | \details Assigns the given value to the non-secure Fault Mask register when in secure state. 567 | \param [in] faultMask Fault Mask value to set 568 | */ 569 | __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) 570 | { 571 | __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); 572 | } 573 | #endif 574 | 575 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 576 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 577 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 578 | 579 | 580 | #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 581 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 582 | 583 | /** 584 | \brief Get Process Stack Pointer Limit 585 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 586 | Stack Pointer Limit register hence zero is returned always in non-secure 587 | mode. 588 | 589 | \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). 590 | \return PSPLIM Register value 591 | */ 592 | __STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) 593 | { 594 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 595 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 596 | // without main extensions, the non-secure PSPLIM is RAZ/WI 597 | return 0U; 598 | #else 599 | uint32_t result; 600 | __ASM volatile ("MRS %0, psplim" : "=r" (result) ); 601 | return result; 602 | #endif 603 | } 604 | 605 | #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) 606 | /** 607 | \brief Get Process Stack Pointer Limit (non-secure) 608 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 609 | Stack Pointer Limit register hence zero is returned always. 610 | 611 | \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. 612 | \return PSPLIM Register value 613 | */ 614 | __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) 615 | { 616 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 617 | // without main extensions, the non-secure PSPLIM is RAZ/WI 618 | return 0U; 619 | #else 620 | uint32_t result; 621 | __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); 622 | return result; 623 | #endif 624 | } 625 | #endif 626 | 627 | 628 | /** 629 | \brief Set Process Stack Pointer Limit 630 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 631 | Stack Pointer Limit register hence the write is silently ignored in non-secure 632 | mode. 633 | 634 | \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). 635 | \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set 636 | */ 637 | __STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) 638 | { 639 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 640 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 641 | // without main extensions, the non-secure PSPLIM is RAZ/WI 642 | (void)ProcStackPtrLimit; 643 | #else 644 | __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); 645 | #endif 646 | } 647 | 648 | 649 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 650 | /** 651 | \brief Set Process Stack Pointer (non-secure) 652 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 653 | Stack Pointer Limit register hence the write is silently ignored. 654 | 655 | \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. 656 | \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set 657 | */ 658 | __STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) 659 | { 660 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 661 | // without main extensions, the non-secure PSPLIM is RAZ/WI 662 | (void)ProcStackPtrLimit; 663 | #else 664 | __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); 665 | #endif 666 | } 667 | #endif 668 | 669 | 670 | /** 671 | \brief Get Main Stack Pointer Limit 672 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 673 | Stack Pointer Limit register hence zero is returned always in non-secure 674 | mode. 675 | 676 | \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). 677 | \return MSPLIM Register value 678 | */ 679 | __STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) 680 | { 681 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 682 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 683 | // without main extensions, the non-secure MSPLIM is RAZ/WI 684 | return 0U; 685 | #else 686 | uint32_t result; 687 | __ASM volatile ("MRS %0, msplim" : "=r" (result) ); 688 | return result; 689 | #endif 690 | } 691 | 692 | 693 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 694 | /** 695 | \brief Get Main Stack Pointer Limit (non-secure) 696 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 697 | Stack Pointer Limit register hence zero is returned always. 698 | 699 | \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. 700 | \return MSPLIM Register value 701 | */ 702 | __STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) 703 | { 704 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 705 | // without main extensions, the non-secure MSPLIM is RAZ/WI 706 | return 0U; 707 | #else 708 | uint32_t result; 709 | __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); 710 | return result; 711 | #endif 712 | } 713 | #endif 714 | 715 | 716 | /** 717 | \brief Set Main Stack Pointer Limit 718 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 719 | Stack Pointer Limit register hence the write is silently ignored in non-secure 720 | mode. 721 | 722 | \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). 723 | \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set 724 | */ 725 | __STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) 726 | { 727 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ 728 | (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) 729 | // without main extensions, the non-secure MSPLIM is RAZ/WI 730 | (void)MainStackPtrLimit; 731 | #else 732 | __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); 733 | #endif 734 | } 735 | 736 | 737 | #if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) 738 | /** 739 | \brief Set Main Stack Pointer Limit (non-secure) 740 | Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure 741 | Stack Pointer Limit register hence the write is silently ignored. 742 | 743 | \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. 744 | \param [in] MainStackPtrLimit Main Stack Pointer value to set 745 | */ 746 | __STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) 747 | { 748 | #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) 749 | // without main extensions, the non-secure MSPLIM is RAZ/WI 750 | (void)MainStackPtrLimit; 751 | #else 752 | __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); 753 | #endif 754 | } 755 | #endif 756 | 757 | #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 758 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 759 | 760 | 761 | /** 762 | \brief Get FPSCR 763 | \details Returns the current value of the Floating Point Status/Control register. 764 | \return Floating Point Status/Control register value 765 | */ 766 | __STATIC_FORCEINLINE uint32_t __get_FPSCR(void) 767 | { 768 | #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ 769 | (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) 770 | #if __has_builtin(__builtin_arm_get_fpscr) 771 | // Re-enable using built-in when GCC has been fixed 772 | // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) 773 | /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ 774 | return __builtin_arm_get_fpscr(); 775 | #else 776 | uint32_t result; 777 | 778 | __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); 779 | return(result); 780 | #endif 781 | #else 782 | return(0U); 783 | #endif 784 | } 785 | 786 | 787 | /** 788 | \brief Set FPSCR 789 | \details Assigns the given value to the Floating Point Status/Control register. 790 | \param [in] fpscr Floating Point Status/Control value to set 791 | */ 792 | __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) 793 | { 794 | #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ 795 | (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) 796 | #if __has_builtin(__builtin_arm_set_fpscr) 797 | // Re-enable using built-in when GCC has been fixed 798 | // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) 799 | /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ 800 | __builtin_arm_set_fpscr(fpscr); 801 | #else 802 | __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); 803 | #endif 804 | #else 805 | (void)fpscr; 806 | #endif 807 | } 808 | 809 | 810 | /*@} end of CMSIS_Core_RegAccFunctions */ 811 | 812 | 813 | /* ########################## Core Instruction Access ######################### */ 814 | /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface 815 | Access to dedicated instructions 816 | @{ 817 | */ 818 | 819 | /* Define macros for porting to both thumb1 and thumb2. 820 | * For thumb1, use low register (r0-r7), specified by constraint "l" 821 | * Otherwise, use general registers, specified by constraint "r" */ 822 | #if defined (__thumb__) && !defined (__thumb2__) 823 | #define __CMSIS_GCC_OUT_REG(r) "=l" (r) 824 | #define __CMSIS_GCC_RW_REG(r) "+l" (r) 825 | #define __CMSIS_GCC_USE_REG(r) "l" (r) 826 | #else 827 | #define __CMSIS_GCC_OUT_REG(r) "=r" (r) 828 | #define __CMSIS_GCC_RW_REG(r) "+r" (r) 829 | #define __CMSIS_GCC_USE_REG(r) "r" (r) 830 | #endif 831 | 832 | /** 833 | \brief No Operation 834 | \details No Operation does nothing. This instruction can be used for code alignment purposes. 835 | */ 836 | #define __NOP() __ASM volatile ("nop") 837 | 838 | /** 839 | \brief Wait For Interrupt 840 | \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. 841 | */ 842 | #define __WFI() __ASM volatile ("wfi") 843 | 844 | 845 | /** 846 | \brief Wait For Event 847 | \details Wait For Event is a hint instruction that permits the processor to enter 848 | a low-power state until one of a number of events occurs. 849 | */ 850 | #define __WFE() __ASM volatile ("wfe") 851 | 852 | 853 | /** 854 | \brief Send Event 855 | \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. 856 | */ 857 | #define __SEV() __ASM volatile ("sev") 858 | 859 | 860 | /** 861 | \brief Instruction Synchronization Barrier 862 | \details Instruction Synchronization Barrier flushes the pipeline in the processor, 863 | so that all instructions following the ISB are fetched from cache or memory, 864 | after the instruction has been completed. 865 | */ 866 | __STATIC_FORCEINLINE void __ISB(void) 867 | { 868 | __ASM volatile ("isb 0xF":::"memory"); 869 | } 870 | 871 | 872 | /** 873 | \brief Data Synchronization Barrier 874 | \details Acts as a special kind of Data Memory Barrier. 875 | It completes when all explicit memory accesses before this instruction complete. 876 | */ 877 | __STATIC_FORCEINLINE void __DSB(void) 878 | { 879 | __ASM volatile ("dsb 0xF":::"memory"); 880 | } 881 | 882 | 883 | /** 884 | \brief Data Memory Barrier 885 | \details Ensures the apparent order of the explicit memory operations before 886 | and after the instruction, without ensuring their completion. 887 | */ 888 | __STATIC_FORCEINLINE void __DMB(void) 889 | { 890 | __ASM volatile ("dmb 0xF":::"memory"); 891 | } 892 | 893 | 894 | /** 895 | \brief Reverse byte order (32 bit) 896 | \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. 897 | \param [in] value Value to reverse 898 | \return Reversed value 899 | */ 900 | __STATIC_FORCEINLINE uint32_t __REV(uint32_t value) 901 | { 902 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 903 | return __builtin_bswap32(value); 904 | #else 905 | uint32_t result; 906 | 907 | __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 908 | return result; 909 | #endif 910 | } 911 | 912 | 913 | /** 914 | \brief Reverse byte order (16 bit) 915 | \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. 916 | \param [in] value Value to reverse 917 | \return Reversed value 918 | */ 919 | __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) 920 | { 921 | uint32_t result; 922 | 923 | __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 924 | return result; 925 | } 926 | 927 | 928 | /** 929 | \brief Reverse byte order (16 bit) 930 | \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. 931 | \param [in] value Value to reverse 932 | \return Reversed value 933 | */ 934 | __STATIC_FORCEINLINE int16_t __REVSH(int16_t value) 935 | { 936 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 937 | return (int16_t)__builtin_bswap16(value); 938 | #else 939 | int16_t result; 940 | 941 | __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 942 | return result; 943 | #endif 944 | } 945 | 946 | 947 | /** 948 | \brief Rotate Right in unsigned value (32 bit) 949 | \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 950 | \param [in] op1 Value to rotate 951 | \param [in] op2 Number of Bits to rotate 952 | \return Rotated value 953 | */ 954 | __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) 955 | { 956 | op2 %= 32U; 957 | if (op2 == 0U) 958 | { 959 | return op1; 960 | } 961 | return (op1 >> op2) | (op1 << (32U - op2)); 962 | } 963 | 964 | 965 | /** 966 | \brief Breakpoint 967 | \details Causes the processor to enter Debug state. 968 | Debug tools can use this to investigate system state when the instruction at a particular address is reached. 969 | \param [in] value is ignored by the processor. 970 | If required, a debugger can use it to store additional information about the breakpoint. 971 | */ 972 | #define __BKPT(value) __ASM volatile ("bkpt "#value) 973 | 974 | 975 | /** 976 | \brief Reverse bit order of value 977 | \details Reverses the bit order of the given value. 978 | \param [in] value Value to reverse 979 | \return Reversed value 980 | */ 981 | __STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) 982 | { 983 | uint32_t result; 984 | 985 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 986 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 987 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 988 | __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); 989 | #else 990 | uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ 991 | 992 | result = value; /* r will be reversed bits of v; first get LSB of v */ 993 | for (value >>= 1U; value != 0U; value >>= 1U) 994 | { 995 | result <<= 1U; 996 | result |= value & 1U; 997 | s--; 998 | } 999 | result <<= s; /* shift when v's highest bits are zero */ 1000 | #endif 1001 | return result; 1002 | } 1003 | 1004 | 1005 | /** 1006 | \brief Count leading zeros 1007 | \details Counts the number of leading zeros of a data value. 1008 | \param [in] value Value to count the leading zeros 1009 | \return number of leading zeros in value 1010 | */ 1011 | #define __CLZ (uint8_t)__builtin_clz 1012 | 1013 | 1014 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1015 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1016 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1017 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 1018 | /** 1019 | \brief LDR Exclusive (8 bit) 1020 | \details Executes a exclusive LDR instruction for 8 bit value. 1021 | \param [in] ptr Pointer to data 1022 | \return value of type uint8_t at (*ptr) 1023 | */ 1024 | __STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) 1025 | { 1026 | uint32_t result; 1027 | 1028 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1029 | __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); 1030 | #else 1031 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1032 | accepted by assembler. So has to use following less efficient pattern. 1033 | */ 1034 | __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 1035 | #endif 1036 | return ((uint8_t) result); /* Add explicit type cast here */ 1037 | } 1038 | 1039 | 1040 | /** 1041 | \brief LDR Exclusive (16 bit) 1042 | \details Executes a exclusive LDR instruction for 16 bit values. 1043 | \param [in] ptr Pointer to data 1044 | \return value of type uint16_t at (*ptr) 1045 | */ 1046 | __STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) 1047 | { 1048 | uint32_t result; 1049 | 1050 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1051 | __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); 1052 | #else 1053 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1054 | accepted by assembler. So has to use following less efficient pattern. 1055 | */ 1056 | __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 1057 | #endif 1058 | return ((uint16_t) result); /* Add explicit type cast here */ 1059 | } 1060 | 1061 | 1062 | /** 1063 | \brief LDR Exclusive (32 bit) 1064 | \details Executes a exclusive LDR instruction for 32 bit values. 1065 | \param [in] ptr Pointer to data 1066 | \return value of type uint32_t at (*ptr) 1067 | */ 1068 | __STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) 1069 | { 1070 | uint32_t result; 1071 | 1072 | __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); 1073 | return(result); 1074 | } 1075 | 1076 | 1077 | /** 1078 | \brief STR Exclusive (8 bit) 1079 | \details Executes a exclusive STR instruction for 8 bit values. 1080 | \param [in] value Value to store 1081 | \param [in] ptr Pointer to location 1082 | \return 0 Function succeeded 1083 | \return 1 Function failed 1084 | */ 1085 | __STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) 1086 | { 1087 | uint32_t result; 1088 | 1089 | __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 1090 | return(result); 1091 | } 1092 | 1093 | 1094 | /** 1095 | \brief STR Exclusive (16 bit) 1096 | \details Executes a exclusive STR instruction for 16 bit values. 1097 | \param [in] value Value to store 1098 | \param [in] ptr Pointer to location 1099 | \return 0 Function succeeded 1100 | \return 1 Function failed 1101 | */ 1102 | __STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) 1103 | { 1104 | uint32_t result; 1105 | 1106 | __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 1107 | return(result); 1108 | } 1109 | 1110 | 1111 | /** 1112 | \brief STR Exclusive (32 bit) 1113 | \details Executes a exclusive STR instruction for 32 bit values. 1114 | \param [in] value Value to store 1115 | \param [in] ptr Pointer to location 1116 | \return 0 Function succeeded 1117 | \return 1 Function failed 1118 | */ 1119 | __STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) 1120 | { 1121 | uint32_t result; 1122 | 1123 | __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); 1124 | return(result); 1125 | } 1126 | 1127 | 1128 | /** 1129 | \brief Remove the exclusive lock 1130 | \details Removes the exclusive lock which is created by LDREX. 1131 | */ 1132 | __STATIC_FORCEINLINE void __CLREX(void) 1133 | { 1134 | __ASM volatile ("clrex" ::: "memory"); 1135 | } 1136 | 1137 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1138 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1139 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1140 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 1141 | 1142 | 1143 | #if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1144 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1145 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) 1146 | /** 1147 | \brief Signed Saturate 1148 | \details Saturates a signed value. 1149 | \param [in] ARG1 Value to be saturated 1150 | \param [in] ARG2 Bit position to saturate to (1..32) 1151 | \return Saturated value 1152 | */ 1153 | #define __SSAT(ARG1,ARG2) \ 1154 | __extension__ \ 1155 | ({ \ 1156 | int32_t __RES, __ARG1 = (ARG1); \ 1157 | __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1158 | __RES; \ 1159 | }) 1160 | 1161 | 1162 | /** 1163 | \brief Unsigned Saturate 1164 | \details Saturates an unsigned value. 1165 | \param [in] ARG1 Value to be saturated 1166 | \param [in] ARG2 Bit position to saturate to (0..31) 1167 | \return Saturated value 1168 | */ 1169 | #define __USAT(ARG1,ARG2) \ 1170 | __extension__ \ 1171 | ({ \ 1172 | uint32_t __RES, __ARG1 = (ARG1); \ 1173 | __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1174 | __RES; \ 1175 | }) 1176 | 1177 | 1178 | /** 1179 | \brief Rotate Right with Extend (32 bit) 1180 | \details Moves each bit of a bitstring right by one bit. 1181 | The carry input is shifted in at the left end of the bitstring. 1182 | \param [in] value Value to rotate 1183 | \return Rotated value 1184 | */ 1185 | __STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) 1186 | { 1187 | uint32_t result; 1188 | 1189 | __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 1190 | return(result); 1191 | } 1192 | 1193 | 1194 | /** 1195 | \brief LDRT Unprivileged (8 bit) 1196 | \details Executes a Unprivileged LDRT instruction for 8 bit value. 1197 | \param [in] ptr Pointer to data 1198 | \return value of type uint8_t at (*ptr) 1199 | */ 1200 | __STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) 1201 | { 1202 | uint32_t result; 1203 | 1204 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1205 | __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); 1206 | #else 1207 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1208 | accepted by assembler. So has to use following less efficient pattern. 1209 | */ 1210 | __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); 1211 | #endif 1212 | return ((uint8_t) result); /* Add explicit type cast here */ 1213 | } 1214 | 1215 | 1216 | /** 1217 | \brief LDRT Unprivileged (16 bit) 1218 | \details Executes a Unprivileged LDRT instruction for 16 bit values. 1219 | \param [in] ptr Pointer to data 1220 | \return value of type uint16_t at (*ptr) 1221 | */ 1222 | __STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) 1223 | { 1224 | uint32_t result; 1225 | 1226 | #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 1227 | __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); 1228 | #else 1229 | /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 1230 | accepted by assembler. So has to use following less efficient pattern. 1231 | */ 1232 | __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); 1233 | #endif 1234 | return ((uint16_t) result); /* Add explicit type cast here */ 1235 | } 1236 | 1237 | 1238 | /** 1239 | \brief LDRT Unprivileged (32 bit) 1240 | \details Executes a Unprivileged LDRT instruction for 32 bit values. 1241 | \param [in] ptr Pointer to data 1242 | \return value of type uint32_t at (*ptr) 1243 | */ 1244 | __STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) 1245 | { 1246 | uint32_t result; 1247 | 1248 | __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); 1249 | return(result); 1250 | } 1251 | 1252 | 1253 | /** 1254 | \brief STRT Unprivileged (8 bit) 1255 | \details Executes a Unprivileged STRT instruction for 8 bit values. 1256 | \param [in] value Value to store 1257 | \param [in] ptr Pointer to location 1258 | */ 1259 | __STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) 1260 | { 1261 | __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1262 | } 1263 | 1264 | 1265 | /** 1266 | \brief STRT Unprivileged (16 bit) 1267 | \details Executes a Unprivileged STRT instruction for 16 bit values. 1268 | \param [in] value Value to store 1269 | \param [in] ptr Pointer to location 1270 | */ 1271 | __STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) 1272 | { 1273 | __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1274 | } 1275 | 1276 | 1277 | /** 1278 | \brief STRT Unprivileged (32 bit) 1279 | \details Executes a Unprivileged STRT instruction for 32 bit values. 1280 | \param [in] value Value to store 1281 | \param [in] ptr Pointer to location 1282 | */ 1283 | __STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) 1284 | { 1285 | __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); 1286 | } 1287 | 1288 | #else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1289 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1290 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 1291 | 1292 | /** 1293 | \brief Signed Saturate 1294 | \details Saturates a signed value. 1295 | \param [in] value Value to be saturated 1296 | \param [in] sat Bit position to saturate to (1..32) 1297 | \return Saturated value 1298 | */ 1299 | __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) 1300 | { 1301 | if ((sat >= 1U) && (sat <= 32U)) 1302 | { 1303 | const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); 1304 | const int32_t min = -1 - max ; 1305 | if (val > max) 1306 | { 1307 | return max; 1308 | } 1309 | else if (val < min) 1310 | { 1311 | return min; 1312 | } 1313 | } 1314 | return val; 1315 | } 1316 | 1317 | /** 1318 | \brief Unsigned Saturate 1319 | \details Saturates an unsigned value. 1320 | \param [in] value Value to be saturated 1321 | \param [in] sat Bit position to saturate to (0..31) 1322 | \return Saturated value 1323 | */ 1324 | __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) 1325 | { 1326 | if (sat <= 31U) 1327 | { 1328 | const uint32_t max = ((1U << sat) - 1U); 1329 | if (val > (int32_t)max) 1330 | { 1331 | return max; 1332 | } 1333 | else if (val < 0) 1334 | { 1335 | return 0U; 1336 | } 1337 | } 1338 | return (uint32_t)val; 1339 | } 1340 | 1341 | #endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ 1342 | (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ 1343 | (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ 1344 | 1345 | 1346 | #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1347 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) 1348 | /** 1349 | \brief Load-Acquire (8 bit) 1350 | \details Executes a LDAB instruction for 8 bit value. 1351 | \param [in] ptr Pointer to data 1352 | \return value of type uint8_t at (*ptr) 1353 | */ 1354 | __STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) 1355 | { 1356 | uint32_t result; 1357 | 1358 | __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); 1359 | return ((uint8_t) result); 1360 | } 1361 | 1362 | 1363 | /** 1364 | \brief Load-Acquire (16 bit) 1365 | \details Executes a LDAH instruction for 16 bit values. 1366 | \param [in] ptr Pointer to data 1367 | \return value of type uint16_t at (*ptr) 1368 | */ 1369 | __STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) 1370 | { 1371 | uint32_t result; 1372 | 1373 | __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); 1374 | return ((uint16_t) result); 1375 | } 1376 | 1377 | 1378 | /** 1379 | \brief Load-Acquire (32 bit) 1380 | \details Executes a LDA instruction for 32 bit values. 1381 | \param [in] ptr Pointer to data 1382 | \return value of type uint32_t at (*ptr) 1383 | */ 1384 | __STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) 1385 | { 1386 | uint32_t result; 1387 | 1388 | __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); 1389 | return(result); 1390 | } 1391 | 1392 | 1393 | /** 1394 | \brief Store-Release (8 bit) 1395 | \details Executes a STLB instruction for 8 bit values. 1396 | \param [in] value Value to store 1397 | \param [in] ptr Pointer to location 1398 | */ 1399 | __STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) 1400 | { 1401 | __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1402 | } 1403 | 1404 | 1405 | /** 1406 | \brief Store-Release (16 bit) 1407 | \details Executes a STLH instruction for 16 bit values. 1408 | \param [in] value Value to store 1409 | \param [in] ptr Pointer to location 1410 | */ 1411 | __STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) 1412 | { 1413 | __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1414 | } 1415 | 1416 | 1417 | /** 1418 | \brief Store-Release (32 bit) 1419 | \details Executes a STL instruction for 32 bit values. 1420 | \param [in] value Value to store 1421 | \param [in] ptr Pointer to location 1422 | */ 1423 | __STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) 1424 | { 1425 | __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); 1426 | } 1427 | 1428 | 1429 | /** 1430 | \brief Load-Acquire Exclusive (8 bit) 1431 | \details Executes a LDAB exclusive instruction for 8 bit value. 1432 | \param [in] ptr Pointer to data 1433 | \return value of type uint8_t at (*ptr) 1434 | */ 1435 | __STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) 1436 | { 1437 | uint32_t result; 1438 | 1439 | __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); 1440 | return ((uint8_t) result); 1441 | } 1442 | 1443 | 1444 | /** 1445 | \brief Load-Acquire Exclusive (16 bit) 1446 | \details Executes a LDAH exclusive instruction for 16 bit values. 1447 | \param [in] ptr Pointer to data 1448 | \return value of type uint16_t at (*ptr) 1449 | */ 1450 | __STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) 1451 | { 1452 | uint32_t result; 1453 | 1454 | __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); 1455 | return ((uint16_t) result); 1456 | } 1457 | 1458 | 1459 | /** 1460 | \brief Load-Acquire Exclusive (32 bit) 1461 | \details Executes a LDA exclusive instruction for 32 bit values. 1462 | \param [in] ptr Pointer to data 1463 | \return value of type uint32_t at (*ptr) 1464 | */ 1465 | __STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) 1466 | { 1467 | uint32_t result; 1468 | 1469 | __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); 1470 | return(result); 1471 | } 1472 | 1473 | 1474 | /** 1475 | \brief Store-Release Exclusive (8 bit) 1476 | \details Executes a STLB exclusive instruction for 8 bit values. 1477 | \param [in] value Value to store 1478 | \param [in] ptr Pointer to location 1479 | \return 0 Function succeeded 1480 | \return 1 Function failed 1481 | */ 1482 | __STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) 1483 | { 1484 | uint32_t result; 1485 | 1486 | __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1487 | return(result); 1488 | } 1489 | 1490 | 1491 | /** 1492 | \brief Store-Release Exclusive (16 bit) 1493 | \details Executes a STLH exclusive instruction for 16 bit values. 1494 | \param [in] value Value to store 1495 | \param [in] ptr Pointer to location 1496 | \return 0 Function succeeded 1497 | \return 1 Function failed 1498 | */ 1499 | __STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) 1500 | { 1501 | uint32_t result; 1502 | 1503 | __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1504 | return(result); 1505 | } 1506 | 1507 | 1508 | /** 1509 | \brief Store-Release Exclusive (32 bit) 1510 | \details Executes a STL exclusive instruction for 32 bit values. 1511 | \param [in] value Value to store 1512 | \param [in] ptr Pointer to location 1513 | \return 0 Function succeeded 1514 | \return 1 Function failed 1515 | */ 1516 | __STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) 1517 | { 1518 | uint32_t result; 1519 | 1520 | __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); 1521 | return(result); 1522 | } 1523 | 1524 | #endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ 1525 | (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ 1526 | 1527 | /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ 1528 | 1529 | 1530 | /* ################### Compiler specific Intrinsics ########################### */ 1531 | /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics 1532 | Access to dedicated SIMD instructions 1533 | @{ 1534 | */ 1535 | 1536 | #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) 1537 | 1538 | __STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) 1539 | { 1540 | uint32_t result; 1541 | 1542 | __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1543 | return(result); 1544 | } 1545 | 1546 | __STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) 1547 | { 1548 | uint32_t result; 1549 | 1550 | __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1551 | return(result); 1552 | } 1553 | 1554 | __STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) 1555 | { 1556 | uint32_t result; 1557 | 1558 | __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1559 | return(result); 1560 | } 1561 | 1562 | __STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) 1563 | { 1564 | uint32_t result; 1565 | 1566 | __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1567 | return(result); 1568 | } 1569 | 1570 | __STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) 1571 | { 1572 | uint32_t result; 1573 | 1574 | __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1575 | return(result); 1576 | } 1577 | 1578 | __STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) 1579 | { 1580 | uint32_t result; 1581 | 1582 | __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1583 | return(result); 1584 | } 1585 | 1586 | 1587 | __STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) 1588 | { 1589 | uint32_t result; 1590 | 1591 | __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1592 | return(result); 1593 | } 1594 | 1595 | __STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) 1596 | { 1597 | uint32_t result; 1598 | 1599 | __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1600 | return(result); 1601 | } 1602 | 1603 | __STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) 1604 | { 1605 | uint32_t result; 1606 | 1607 | __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1608 | return(result); 1609 | } 1610 | 1611 | __STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) 1612 | { 1613 | uint32_t result; 1614 | 1615 | __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1616 | return(result); 1617 | } 1618 | 1619 | __STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) 1620 | { 1621 | uint32_t result; 1622 | 1623 | __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1624 | return(result); 1625 | } 1626 | 1627 | __STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) 1628 | { 1629 | uint32_t result; 1630 | 1631 | __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1632 | return(result); 1633 | } 1634 | 1635 | 1636 | __STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) 1637 | { 1638 | uint32_t result; 1639 | 1640 | __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1641 | return(result); 1642 | } 1643 | 1644 | __STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) 1645 | { 1646 | uint32_t result; 1647 | 1648 | __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1649 | return(result); 1650 | } 1651 | 1652 | __STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) 1653 | { 1654 | uint32_t result; 1655 | 1656 | __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1657 | return(result); 1658 | } 1659 | 1660 | __STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) 1661 | { 1662 | uint32_t result; 1663 | 1664 | __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1665 | return(result); 1666 | } 1667 | 1668 | __STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) 1669 | { 1670 | uint32_t result; 1671 | 1672 | __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1673 | return(result); 1674 | } 1675 | 1676 | __STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) 1677 | { 1678 | uint32_t result; 1679 | 1680 | __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1681 | return(result); 1682 | } 1683 | 1684 | __STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) 1685 | { 1686 | uint32_t result; 1687 | 1688 | __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1689 | return(result); 1690 | } 1691 | 1692 | __STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) 1693 | { 1694 | uint32_t result; 1695 | 1696 | __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1697 | return(result); 1698 | } 1699 | 1700 | __STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) 1701 | { 1702 | uint32_t result; 1703 | 1704 | __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1705 | return(result); 1706 | } 1707 | 1708 | __STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) 1709 | { 1710 | uint32_t result; 1711 | 1712 | __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1713 | return(result); 1714 | } 1715 | 1716 | __STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) 1717 | { 1718 | uint32_t result; 1719 | 1720 | __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1721 | return(result); 1722 | } 1723 | 1724 | __STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) 1725 | { 1726 | uint32_t result; 1727 | 1728 | __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1729 | return(result); 1730 | } 1731 | 1732 | __STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) 1733 | { 1734 | uint32_t result; 1735 | 1736 | __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1737 | return(result); 1738 | } 1739 | 1740 | __STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) 1741 | { 1742 | uint32_t result; 1743 | 1744 | __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1745 | return(result); 1746 | } 1747 | 1748 | __STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) 1749 | { 1750 | uint32_t result; 1751 | 1752 | __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1753 | return(result); 1754 | } 1755 | 1756 | __STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) 1757 | { 1758 | uint32_t result; 1759 | 1760 | __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1761 | return(result); 1762 | } 1763 | 1764 | __STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) 1765 | { 1766 | uint32_t result; 1767 | 1768 | __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1769 | return(result); 1770 | } 1771 | 1772 | __STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) 1773 | { 1774 | uint32_t result; 1775 | 1776 | __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1777 | return(result); 1778 | } 1779 | 1780 | __STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) 1781 | { 1782 | uint32_t result; 1783 | 1784 | __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1785 | return(result); 1786 | } 1787 | 1788 | __STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) 1789 | { 1790 | uint32_t result; 1791 | 1792 | __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1793 | return(result); 1794 | } 1795 | 1796 | __STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) 1797 | { 1798 | uint32_t result; 1799 | 1800 | __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1801 | return(result); 1802 | } 1803 | 1804 | __STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) 1805 | { 1806 | uint32_t result; 1807 | 1808 | __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1809 | return(result); 1810 | } 1811 | 1812 | __STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) 1813 | { 1814 | uint32_t result; 1815 | 1816 | __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1817 | return(result); 1818 | } 1819 | 1820 | __STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) 1821 | { 1822 | uint32_t result; 1823 | 1824 | __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1825 | return(result); 1826 | } 1827 | 1828 | __STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) 1829 | { 1830 | uint32_t result; 1831 | 1832 | __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1833 | return(result); 1834 | } 1835 | 1836 | __STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) 1837 | { 1838 | uint32_t result; 1839 | 1840 | __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1841 | return(result); 1842 | } 1843 | 1844 | #define __SSAT16(ARG1,ARG2) \ 1845 | ({ \ 1846 | int32_t __RES, __ARG1 = (ARG1); \ 1847 | __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1848 | __RES; \ 1849 | }) 1850 | 1851 | #define __USAT16(ARG1,ARG2) \ 1852 | ({ \ 1853 | uint32_t __RES, __ARG1 = (ARG1); \ 1854 | __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1855 | __RES; \ 1856 | }) 1857 | 1858 | __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) 1859 | { 1860 | uint32_t result; 1861 | 1862 | __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1863 | return(result); 1864 | } 1865 | 1866 | __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) 1867 | { 1868 | uint32_t result; 1869 | 1870 | __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1871 | return(result); 1872 | } 1873 | 1874 | __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) 1875 | { 1876 | uint32_t result; 1877 | 1878 | __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1879 | return(result); 1880 | } 1881 | 1882 | __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) 1883 | { 1884 | uint32_t result; 1885 | 1886 | __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1887 | return(result); 1888 | } 1889 | 1890 | __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) 1891 | { 1892 | uint32_t result; 1893 | 1894 | __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1895 | return(result); 1896 | } 1897 | 1898 | __STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) 1899 | { 1900 | uint32_t result; 1901 | 1902 | __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1903 | return(result); 1904 | } 1905 | 1906 | __STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) 1907 | { 1908 | uint32_t result; 1909 | 1910 | __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1911 | return(result); 1912 | } 1913 | 1914 | __STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) 1915 | { 1916 | uint32_t result; 1917 | 1918 | __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1919 | return(result); 1920 | } 1921 | 1922 | __STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) 1923 | { 1924 | union llreg_u{ 1925 | uint32_t w32[2]; 1926 | uint64_t w64; 1927 | } llr; 1928 | llr.w64 = acc; 1929 | 1930 | #ifndef __ARMEB__ /* Little endian */ 1931 | __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 1932 | #else /* Big endian */ 1933 | __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 1934 | #endif 1935 | 1936 | return(llr.w64); 1937 | } 1938 | 1939 | __STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) 1940 | { 1941 | union llreg_u{ 1942 | uint32_t w32[2]; 1943 | uint64_t w64; 1944 | } llr; 1945 | llr.w64 = acc; 1946 | 1947 | #ifndef __ARMEB__ /* Little endian */ 1948 | __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 1949 | #else /* Big endian */ 1950 | __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 1951 | #endif 1952 | 1953 | return(llr.w64); 1954 | } 1955 | 1956 | __STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) 1957 | { 1958 | uint32_t result; 1959 | 1960 | __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1961 | return(result); 1962 | } 1963 | 1964 | __STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) 1965 | { 1966 | uint32_t result; 1967 | 1968 | __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1969 | return(result); 1970 | } 1971 | 1972 | __STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) 1973 | { 1974 | uint32_t result; 1975 | 1976 | __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1977 | return(result); 1978 | } 1979 | 1980 | __STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) 1981 | { 1982 | uint32_t result; 1983 | 1984 | __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1985 | return(result); 1986 | } 1987 | 1988 | __STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) 1989 | { 1990 | union llreg_u{ 1991 | uint32_t w32[2]; 1992 | uint64_t w64; 1993 | } llr; 1994 | llr.w64 = acc; 1995 | 1996 | #ifndef __ARMEB__ /* Little endian */ 1997 | __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 1998 | #else /* Big endian */ 1999 | __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 2000 | #endif 2001 | 2002 | return(llr.w64); 2003 | } 2004 | 2005 | __STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) 2006 | { 2007 | union llreg_u{ 2008 | uint32_t w32[2]; 2009 | uint64_t w64; 2010 | } llr; 2011 | llr.w64 = acc; 2012 | 2013 | #ifndef __ARMEB__ /* Little endian */ 2014 | __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 2015 | #else /* Big endian */ 2016 | __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 2017 | #endif 2018 | 2019 | return(llr.w64); 2020 | } 2021 | 2022 | __STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) 2023 | { 2024 | uint32_t result; 2025 | 2026 | __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2027 | return(result); 2028 | } 2029 | 2030 | __STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) 2031 | { 2032 | int32_t result; 2033 | 2034 | __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2035 | return(result); 2036 | } 2037 | 2038 | __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) 2039 | { 2040 | int32_t result; 2041 | 2042 | __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 2043 | return(result); 2044 | } 2045 | 2046 | #if 0 2047 | #define __PKHBT(ARG1,ARG2,ARG3) \ 2048 | ({ \ 2049 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 2050 | __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 2051 | __RES; \ 2052 | }) 2053 | 2054 | #define __PKHTB(ARG1,ARG2,ARG3) \ 2055 | ({ \ 2056 | uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 2057 | if (ARG3 == 0) \ 2058 | __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ 2059 | else \ 2060 | __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 2061 | __RES; \ 2062 | }) 2063 | #endif 2064 | 2065 | #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ 2066 | ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) 2067 | 2068 | #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ 2069 | ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) 2070 | 2071 | __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) 2072 | { 2073 | int32_t result; 2074 | 2075 | __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); 2076 | return(result); 2077 | } 2078 | 2079 | #endif /* (__ARM_FEATURE_DSP == 1) */ 2080 | /*@} end of group CMSIS_SIMD_intrinsics */ 2081 | 2082 | 2083 | #pragma GCC diagnostic pop 2084 | 2085 | #endif /* __CMSIS_GCC_H */ 2086 | -------------------------------------------------------------------------------- /include/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.2 5 | * @date 19. April 2017 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2017 ARM Limited. All rights reserved. 9 | * 10 | * SPDX-License-Identifier: Apache-2.0 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the License); you may 13 | * not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 20 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | 25 | #if defined ( __ICCARM__ ) 26 | #pragma system_include /* treat file as system include file for MISRA check */ 27 | #elif defined (__clang__) 28 | #pragma clang system_header /* treat file as system include file */ 29 | #endif 30 | 31 | #ifndef __CMSIS_VERSION_H 32 | #define __CMSIS_VERSION_H 33 | 34 | /* CMSIS Version definitions */ 35 | #define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ 36 | #define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ 37 | #define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ 38 | __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ 39 | #endif 40 | -------------------------------------------------------------------------------- /include/gpio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | ****************************************************************************** 5 | * @file : gpio.hpp 6 | * @author : Rohit Nimkar 7 | * @brief : GPIO library header file 8 | * This source file contains definitions of inline function and all declarations 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | * This software component is licensed by Rohit Nimkar under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | class GPIO 24 | { 25 | public: 26 | enum PIN : uint8_t; 27 | enum PIN_STATE : uint8_t; 28 | enum MODE : uint8_t; 29 | enum CNF : uint8_t; 30 | 31 | private: 32 | PIN pin; 33 | GPIO_TypeDef *PORT; 34 | 35 | public: 36 | /** 37 | * @brief GPIO port pins 38 | * 39 | */ 40 | enum PIN : uint8_t 41 | { 42 | PIN_0 = (uint8_t)0x0000, /* GPIO pin 0 */ 43 | PIN_1 = (uint8_t)0x0001, /* GPIO pin 1 */ 44 | PIN_2 = (uint8_t)0x0002, /* GPIO pin 2 */ 45 | PIN_3 = (uint8_t)0x0003, /* GPIO pin 3 */ 46 | PIN_4 = (uint8_t)0x0004, /* GPIO pin 4 */ 47 | PIN_5 = (uint8_t)0x0005, /* GPIO pin 5 */ 48 | PIN_6 = (uint8_t)0x0006, /* GPIO pin 6 */ 49 | PIN_7 = (uint8_t)0x0007, /* GPIO pin 7 */ 50 | PIN_8 = (uint8_t)0x0008, /* GPIO pin 8 */ 51 | PIN_9 = (uint8_t)0x0009, /* GPIO pin 9 */ 52 | PIN_10 = (uint8_t)0x000A, /* GPIO pin 10 */ 53 | PIN_11 = (uint8_t)0x000B, /* GPIO pin 11 */ 54 | PIN_12 = (uint8_t)0x000C, /* GPIO pin 12 */ 55 | PIN_13 = (uint8_t)0x000D, /* GPIO pin 13 */ 56 | PIN_14 = (uint8_t)0x000E, /* GPIO pin 14 */ 57 | PIN_15 = (uint8_t)0x000F, /* GPIO pin 15 */ 58 | PIN_ALL = (uint8_t)0xffff /* Select all gpio pins */ 59 | }; 60 | 61 | /** 62 | * @brief GPIO logical pin state 63 | * 64 | */ 65 | enum PIN_STATE : uint8_t 66 | { 67 | LOW = (uint8_t)0x00, /* Pin state logical LOW */ 68 | HIGH = (uint8_t)0x01 /* Pin state logical HIGH */ 69 | }; 70 | 71 | enum MODE : uint8_t 72 | { 73 | INPUT = (uint8_t)0b00, 74 | OUTPUT_10MHZ, 75 | OUTPUT_2MHZ, 76 | OUTPUT_50MHZ 77 | }; 78 | 79 | enum CNF : uint8_t 80 | { 81 | INPUT_ANALOG = (uint8_t)0b00, 82 | INPUT_FLOATING, 83 | INPUT_PULLUP_DOWN, 84 | INPUT_RESERVED, 85 | OUTPUT_PUSH_PULL = (uint8_t)0b00, 86 | OUTPUT_OPEN_DRAIN, 87 | OUTPUT_ALT_PUSH_PULL, 88 | OUTPUT_ALT_OPEN_DRAIN 89 | }; 90 | 91 | GPIO() : pin{PIN_0}, PORT{nullptr} 92 | { 93 | } 94 | 95 | GPIO(GPIO_TypeDef *port) : pin{PIN_0}, PORT{port} 96 | { 97 | } 98 | 99 | GPIO(const GPIO &gpio) : pin{gpio.pin}, PORT{gpio.PORT} 100 | { 101 | } 102 | 103 | GPIO &operator=(const GPIO &gpio); 104 | 105 | /** 106 | * @brief Construct a new GPIO object 107 | * 108 | * @param port POinter to port base address 109 | * @param newPin pin number 110 | */ 111 | GPIO(GPIO_TypeDef *port, PIN newPin) : pin{newPin}, PORT{port} {} 112 | 113 | /** 114 | * @brief Enable clock source for Port A 115 | */ 116 | static void enable_PortA(); 117 | 118 | /** 119 | * @brief Enable clock source for Port B 120 | */ 121 | static void enable_PortB(); 122 | 123 | /** 124 | * @brief Enable clock source for Port C 125 | */ 126 | static void enable_PortC(); 127 | 128 | /** 129 | * @brief Destroy the GPIO object 130 | */ 131 | ~GPIO(); 132 | 133 | /** 134 | * @brief Write HIGH logic to GPIO 135 | */ 136 | void high(); 137 | static void high(GPIO_TypeDef *port, PIN newPin); 138 | 139 | /** 140 | * @brief Write LOW logic to GPIO 141 | */ 142 | void low(); 143 | static void low(GPIO_TypeDef *port, PIN newPin); 144 | 145 | /** 146 | * @brief Toggle GPIO 147 | */ 148 | void toggle(); 149 | static void toggle(GPIO_TypeDef *port, PIN newPin); 150 | 151 | /** 152 | * @brief Set the state of GPIO pin 153 | * @param state new state to be set 154 | */ 155 | void write(PIN_STATE state); 156 | static void write(GPIO_TypeDef *port, PIN newPin, PIN_STATE state); 157 | 158 | void setMode(MODE mode); 159 | static void setMode(GPIO_TypeDef *port, PIN newPin, MODE mode); 160 | 161 | void setConfig(CNF cnf); 162 | static void setConfig(GPIO_TypeDef *port, PIN newPin, CNF cnf); 163 | }; 164 | 165 | inline GPIO &GPIO::operator=(const GPIO &gpio) 166 | { 167 | this->pin = gpio.pin; 168 | this->PORT = gpio.PORT; 169 | return *this; 170 | } 171 | 172 | inline void GPIO::enable_PortA() { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; } 173 | inline void GPIO::enable_PortB() { RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; } 174 | void GPIO::enable_PortC() 175 | { 176 | RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; 177 | } 178 | 179 | inline void GPIO::setMode(MODE mode) 180 | { 181 | setMode(PORT, pin, mode); 182 | }; 183 | inline void GPIO::setMode(GPIO_TypeDef *port, PIN newPin, MODE mode) 184 | { 185 | if (newPin < PIN_8) 186 | { 187 | port->CRL &= ~(0b11 << (newPin << 2)); 188 | port->CRL |= mode << (newPin << 2); 189 | } 190 | else 191 | { 192 | port->CRH &= ~(0b11 << ((newPin - 8) << 2)); 193 | port->CRH |= mode << ((newPin - 8) << 2); 194 | } 195 | } 196 | inline void GPIO::setConfig(CNF config) 197 | { 198 | setConfig(PORT, pin, config); 199 | } 200 | inline void GPIO::setConfig(GPIO_TypeDef *port, PIN newPin, CNF config) 201 | { 202 | if (newPin < PIN_8) 203 | { 204 | port->CRL &= ~(0b11 << ((newPin << 2) + 2)); 205 | port->CRL |= config << ((newPin << 2) + 2); 206 | } 207 | else 208 | { 209 | port->CRH &= ~(0b11 << (((newPin - 8) << 2) + 2)); 210 | port->CRH |= config << (((newPin - 8) << 2) + 2); 211 | } 212 | } 213 | 214 | inline void GPIO::toggle() { this->PORT->ODR ^= 1 << this->pin; }; 215 | inline void GPIO::toggle(GPIO_TypeDef *port, PIN newPin) { port->ODR ^= 1 << newPin; }; 216 | 217 | inline void GPIO::write(PIN_STATE state) 218 | { 219 | if (state == HIGH) 220 | { 221 | high(); 222 | } 223 | else 224 | { 225 | low(); 226 | } 227 | }; 228 | inline void GPIO::write(GPIO_TypeDef *port, PIN newPin, PIN_STATE state) 229 | { 230 | if (state == HIGH) 231 | { 232 | high(port, newPin); 233 | } 234 | else 235 | { 236 | low(port, newPin); 237 | } 238 | }; 239 | 240 | inline void GPIO::high() { this->PORT->BSRR = 1 << this->pin; }; 241 | inline void GPIO::high(GPIO_TypeDef *port, PIN newPin) { port->BSRR = 1 << newPin; }; 242 | 243 | inline void GPIO::low() { this->PORT->BRR = 1 << this->pin; }; 244 | inline void GPIO::low(GPIO_TypeDef *port, PIN newPin) { port->BRR = 1 << newPin; }; 245 | -------------------------------------------------------------------------------- /include/stm32f1xx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f1xx.h 4 | * @author MCD Application Team 5 | * @brief CMSIS STM32F1xx Device Peripheral Access Layer Header File. 6 | * 7 | * The file is the unique include file that the application programmer 8 | * is using in the C source code, usually in main.c. This file contains: 9 | * - Configuration section that allows to select: 10 | * - The STM32F1xx device used in the target application 11 | * - To use or not the peripheral�s drivers in application code(i.e. 12 | * code will be based on direct access to peripheral�s registers 13 | * rather than drivers API), this option is controlled by 14 | * "#define USE_HAL_DRIVER" 15 | * 16 | ****************************************************************************** 17 | * @attention 18 | * 19 | *

© Copyright (c) 2017 STMicroelectronics. 20 | * All rights reserved.

21 | * 22 | * This software component is licensed by ST under BSD 3-Clause license, 23 | * the "License"; You may not use this file except in compliance with the 24 | * License. You may obtain a copy of the License at: 25 | * opensource.org/licenses/BSD-3-Clause 26 | * 27 | ****************************************************************************** 28 | */ 29 | 30 | /** @addtogroup CMSIS 31 | * @{ 32 | */ 33 | 34 | /** @addtogroup stm32f1xx 35 | * @{ 36 | */ 37 | 38 | #ifndef __STM32F1XX_H 39 | #define __STM32F1XX_H 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif /* __cplusplus */ 44 | 45 | /** @addtogroup Library_configuration_section 46 | * @{ 47 | */ 48 | 49 | /** 50 | * @brief STM32 Family 51 | */ 52 | #if !defined (STM32F1) 53 | #define STM32F1 54 | #endif /* STM32F1 */ 55 | 56 | /* Uncomment the line below according to the target STM32L device used in your 57 | application 58 | */ 59 | 60 | #if !defined (STM32F100xB) && !defined (STM32F100xE) && !defined (STM32F101x6) && \ 61 | !defined (STM32F101xB) && !defined (STM32F101xE) && !defined (STM32F101xG) && !defined (STM32F102x6) && !defined (STM32F102xB) && !defined (STM32F103x6) && \ 62 | !defined (STM32F103xB) && !defined (STM32F103xE) && !defined (STM32F103xG) && !defined (STM32F105xC) && !defined (STM32F107xC) 63 | /* #define STM32F100xB */ /*!< STM32F100C4, STM32F100R4, STM32F100C6, STM32F100R6, STM32F100C8, STM32F100R8, STM32F100V8, STM32F100CB, STM32F100RB and STM32F100VB */ 64 | /* #define STM32F100xE */ /*!< STM32F100RC, STM32F100VC, STM32F100ZC, STM32F100RD, STM32F100VD, STM32F100ZD, STM32F100RE, STM32F100VE and STM32F100ZE */ 65 | /* #define STM32F101x6 */ /*!< STM32F101C4, STM32F101R4, STM32F101T4, STM32F101C6, STM32F101R6 and STM32F101T6 Devices */ 66 | /* #define STM32F101xB */ /*!< STM32F101C8, STM32F101R8, STM32F101T8, STM32F101V8, STM32F101CB, STM32F101RB, STM32F101TB and STM32F101VB */ 67 | /* #define STM32F101xE */ /*!< STM32F101RC, STM32F101VC, STM32F101ZC, STM32F101RD, STM32F101VD, STM32F101ZD, STM32F101RE, STM32F101VE and STM32F101ZE */ 68 | /* #define STM32F101xG */ /*!< STM32F101RF, STM32F101VF, STM32F101ZF, STM32F101RG, STM32F101VG and STM32F101ZG */ 69 | /* #define STM32F102x6 */ /*!< STM32F102C4, STM32F102R4, STM32F102C6 and STM32F102R6 */ 70 | /* #define STM32F102xB */ /*!< STM32F102C8, STM32F102R8, STM32F102CB and STM32F102RB */ 71 | /* #define STM32F103x6 */ /*!< STM32F103C4, STM32F103R4, STM32F103T4, STM32F103C6, STM32F103R6 and STM32F103T6 */ 72 | /* #define STM32F103xB */ /*!< STM32F103C8, STM32F103R8, STM32F103T8, STM32F103V8, STM32F103CB, STM32F103RB, STM32F103TB and STM32F103VB */ 73 | /* #define STM32F103xE */ /*!< STM32F103RC, STM32F103VC, STM32F103ZC, STM32F103RD, STM32F103VD, STM32F103ZD, STM32F103RE, STM32F103VE and STM32F103ZE */ 74 | /* #define STM32F103xG */ /*!< STM32F103RF, STM32F103VF, STM32F103ZF, STM32F103RG, STM32F103VG and STM32F103ZG */ 75 | /* #define STM32F105xC */ /*!< STM32F105R8, STM32F105V8, STM32F105RB, STM32F105VB, STM32F105RC and STM32F105VC */ 76 | /* #define STM32F107xC */ /*!< STM32F107RB, STM32F107VB, STM32F107RC and STM32F107VC */ 77 | #endif 78 | 79 | /* Tip: To avoid modifying this file each time you need to switch between these 80 | devices, you can define the device in your toolchain compiler preprocessor. 81 | */ 82 | 83 | #if !defined (USE_HAL_DRIVER) 84 | /** 85 | * @brief Comment the line below if you will not use the peripherals drivers. 86 | In this case, these drivers will not be included and the application code will 87 | be based on direct access to peripherals registers 88 | */ 89 | /*#define USE_HAL_DRIVER */ 90 | #endif /* USE_HAL_DRIVER */ 91 | 92 | /** 93 | * @brief CMSIS Device version number V4.3.3 94 | */ 95 | #define __STM32F1_CMSIS_VERSION_MAIN (0x04) /*!< [31:24] main version */ 96 | #define __STM32F1_CMSIS_VERSION_SUB1 (0x03) /*!< [23:16] sub1 version */ 97 | #define __STM32F1_CMSIS_VERSION_SUB2 (0x03) /*!< [15:8] sub2 version */ 98 | #define __STM32F1_CMSIS_VERSION_RC (0x00) /*!< [7:0] release candidate */ 99 | #define __STM32F1_CMSIS_VERSION ((__STM32F1_CMSIS_VERSION_MAIN << 24)\ 100 | |(__STM32F1_CMSIS_VERSION_SUB1 << 16)\ 101 | |(__STM32F1_CMSIS_VERSION_SUB2 << 8 )\ 102 | |(__STM32F1_CMSIS_VERSION_RC)) 103 | 104 | /** 105 | * @} 106 | */ 107 | 108 | /** @addtogroup Device_Included 109 | * @{ 110 | */ 111 | 112 | #if defined(STM32F100xB) 113 | #include "stm32f100xb.h" 114 | #elif defined(STM32F100xE) 115 | #include "stm32f100xe.h" 116 | #elif defined(STM32F101x6) 117 | #include "stm32f101x6.h" 118 | #elif defined(STM32F101xB) 119 | #include "stm32f101xb.h" 120 | #elif defined(STM32F101xE) 121 | #include "stm32f101xe.h" 122 | #elif defined(STM32F101xG) 123 | #include "stm32f101xg.h" 124 | #elif defined(STM32F102x6) 125 | #include "stm32f102x6.h" 126 | #elif defined(STM32F102xB) 127 | #include "stm32f102xb.h" 128 | #elif defined(STM32F103x6) 129 | #include "stm32f103x6.h" 130 | #elif defined(STM32F103xB) 131 | #include "stm32f103xb.h" 132 | #elif defined(STM32F103xE) 133 | #include "stm32f103xe.h" 134 | #elif defined(STM32F103xG) 135 | #include "stm32f103xg.h" 136 | #elif defined(STM32F105xC) 137 | #include "stm32f105xc.h" 138 | #elif defined(STM32F107xC) 139 | #include "stm32f107xc.h" 140 | #else 141 | #error "Please select first the target STM32F1xx device used in your application (in stm32f1xx.h file)" 142 | #endif 143 | 144 | /** 145 | * @} 146 | */ 147 | 148 | /** @addtogroup Exported_types 149 | * @{ 150 | */ 151 | typedef enum 152 | { 153 | RESET = 0, 154 | SET = !RESET 155 | } FlagStatus, ITStatus; 156 | 157 | typedef enum 158 | { 159 | DISABLE = 0, 160 | ENABLE = !DISABLE 161 | } FunctionalState; 162 | #define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) 163 | 164 | typedef enum 165 | { 166 | SUCCESS = 0U, 167 | ERROR = !SUCCESS 168 | } ErrorStatus; 169 | 170 | /** 171 | * @} 172 | */ 173 | 174 | 175 | /** @addtogroup Exported_macros 176 | * @{ 177 | */ 178 | #define SET_BIT(REG, BIT) ((REG) |= (BIT)) 179 | 180 | #define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) 181 | 182 | #define READ_BIT(REG, BIT) ((REG) & (BIT)) 183 | 184 | #define CLEAR_REG(REG) ((REG) = (0x0)) 185 | 186 | #define WRITE_REG(REG, VAL) ((REG) = (VAL)) 187 | 188 | #define READ_REG(REG) ((REG)) 189 | 190 | #define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) 191 | 192 | #define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) 193 | 194 | /* Use of CMSIS compiler intrinsics for register exclusive access */ 195 | /* Atomic 32-bit register access macro to set one or several bits */ 196 | #define ATOMIC_SET_BIT(REG, BIT) \ 197 | do { \ 198 | uint32_t val; \ 199 | do { \ 200 | val = __LDREXW((__IO uint32_t *)&(REG)) | (BIT); \ 201 | } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \ 202 | } while(0) 203 | 204 | /* Atomic 32-bit register access macro to clear one or several bits */ 205 | #define ATOMIC_CLEAR_BIT(REG, BIT) \ 206 | do { \ 207 | uint32_t val; \ 208 | do { \ 209 | val = __LDREXW((__IO uint32_t *)&(REG)) & ~(BIT); \ 210 | } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \ 211 | } while(0) 212 | 213 | /* Atomic 32-bit register access macro to clear and set one or several bits */ 214 | #define ATOMIC_MODIFY_REG(REG, CLEARMSK, SETMASK) \ 215 | do { \ 216 | uint32_t val; \ 217 | do { \ 218 | val = (__LDREXW((__IO uint32_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \ 219 | } while ((__STREXW(val,(__IO uint32_t *)&(REG))) != 0U); \ 220 | } while(0) 221 | 222 | /* Atomic 16-bit register access macro to set one or several bits */ 223 | #define ATOMIC_SETH_BIT(REG, BIT) \ 224 | do { \ 225 | uint16_t val; \ 226 | do { \ 227 | val = __LDREXH((__IO uint16_t *)&(REG)) | (BIT); \ 228 | } while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \ 229 | } while(0) 230 | 231 | /* Atomic 16-bit register access macro to clear one or several bits */ 232 | #define ATOMIC_CLEARH_BIT(REG, BIT) \ 233 | do { \ 234 | uint16_t val; \ 235 | do { \ 236 | val = __LDREXH((__IO uint16_t *)&(REG)) & ~(BIT); \ 237 | } while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \ 238 | } while(0) 239 | 240 | /* Atomic 16-bit register access macro to clear and set one or several bits */ 241 | #define ATOMIC_MODIFYH_REG(REG, CLEARMSK, SETMASK) \ 242 | do { \ 243 | uint16_t val; \ 244 | do { \ 245 | val = (__LDREXH((__IO uint16_t *)&(REG)) & ~(CLEARMSK)) | (SETMASK); \ 246 | } while ((__STREXH(val,(__IO uint16_t *)&(REG))) != 0U); \ 247 | } while(0) 248 | 249 | 250 | /** 251 | * @} 252 | */ 253 | 254 | #if defined (USE_HAL_DRIVER) 255 | #include "stm32f1xx_hal.h" 256 | #endif /* USE_HAL_DRIVER */ 257 | 258 | 259 | #ifdef __cplusplus 260 | } 261 | #endif /* __cplusplus */ 262 | 263 | #endif /* __STM32F1xx_H */ 264 | /** 265 | * @} 266 | */ 267 | 268 | /** 269 | * @} 270 | */ 271 | 272 | 273 | 274 | 275 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 276 | 277 | -------------------------------------------------------------------------------- /include/system_stm32f1xx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f10x.h 4 | * @author MCD Application Team 5 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2017 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | 20 | /** @addtogroup CMSIS 21 | * @{ 22 | */ 23 | 24 | /** @addtogroup stm32f10x_system 25 | * @{ 26 | */ 27 | 28 | /** 29 | * @brief Define to prevent recursive inclusion 30 | */ 31 | #ifndef __SYSTEM_STM32F10X_H 32 | #define __SYSTEM_STM32F10X_H 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** @addtogroup STM32F10x_System_Includes 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @} 44 | */ 45 | 46 | 47 | /** @addtogroup STM32F10x_System_Exported_types 48 | * @{ 49 | */ 50 | 51 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 52 | extern const uint8_t AHBPrescTable[16U]; /*!< AHB prescalers table values */ 53 | extern const uint8_t APBPrescTable[8U]; /*!< APB prescalers table values */ 54 | 55 | /** 56 | * @} 57 | */ 58 | 59 | /** @addtogroup STM32F10x_System_Exported_Constants 60 | * @{ 61 | */ 62 | 63 | /** 64 | * @} 65 | */ 66 | 67 | /** @addtogroup STM32F10x_System_Exported_Macros 68 | * @{ 69 | */ 70 | 71 | /** 72 | * @} 73 | */ 74 | 75 | /** @addtogroup STM32F10x_System_Exported_Functions 76 | * @{ 77 | */ 78 | 79 | extern void SystemInit(void); 80 | extern void SystemCoreClockUpdate(void); 81 | /** 82 | * @} 83 | */ 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif /*__SYSTEM_STM32F10X_H */ 90 | 91 | /** 92 | * @} 93 | */ 94 | 95 | /** 96 | * @} 97 | */ 98 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 99 | -------------------------------------------------------------------------------- /src/gpio.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csrohit/stm32-startup-cpp/968ebc82374523b8fc83b9f79b4b9978d372bd2b/src/gpio.cpp -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | void ms_delay(int ms) 7 | { 8 | while (ms-- > 0) 9 | { 10 | volatile int x = 500; 11 | while (x-- > 0) 12 | __asm("nop"); 13 | } 14 | } 15 | 16 | int main(void) 17 | { 18 | GPIO::enable_PortC(); 19 | GPIO::setMode(GPIOC, GPIO::PIN_13,GPIO::OUTPUT_2MHZ); 20 | GPIO::setConfig(GPIOC, GPIO::PIN_13,GPIO::OUTPUT_PUSH_PULL); 21 | while (1) 22 | { 23 | GPIO::toggle(GPIOC, GPIO::PIN_13); 24 | ms_delay(1000U); 25 | } 26 | } -------------------------------------------------------------------------------- /src/startup_stm32f103.cpp: -------------------------------------------------------------------------------- 1 | // startup declarations and function for the STM32F103C8T6 2 | // See: RM0008 10.1.2 Interrupt and exception vectors, Table 63. Vector table for other STM32F10xxx devices 3 | 4 | #include 5 | #include 6 | 7 | #define SRAM_START 0x20000000U 8 | #define SRAM_SIZE (20U * 1024U) // 20KB 9 | #define SRAM_END ((SRAM_START) + (SRAM_SIZE)) 10 | #define STACK_START SRAM_END 11 | 12 | extern uint32_t _etext; 13 | extern uint32_t _sdata; 14 | extern uint32_t _edata; 15 | extern uint32_t _la_data; 16 | 17 | extern uint32_t _sbss; 18 | extern uint32_t _ebss; 19 | 20 | int main(void); 21 | 22 | extern "C" 23 | { 24 | [[noreturn]] void Reset_Handler(void); 25 | void Default_Handler(void); 26 | void *memcpy(void *dest, const void *src, size_t n); 27 | } 28 | 29 | // Weak function prototypes for the vector table so that they can easily be redefined 30 | void NMI_Handler(void) __attribute__((weak, alias("Default_Handler"))); 31 | void HardFault_Handler(void) __attribute__((weak, alias("Default_Handler"))); 32 | void MemManage_Handler(void) __attribute__((weak, alias("Default_Handler"))); 33 | void BusFault_Handler(void) __attribute__((weak, alias("Default_Handler"))); 34 | void UsageFault_Handler(void) __attribute__((weak, alias("Default_Handler"))); 35 | void SVC_Handler(void) __attribute__((weak, alias("Default_Handler"))); 36 | void DebugMon_Handler(void) __attribute__((weak, alias("Default_Handler"))); 37 | void PendSV_Handler(void) __attribute__((weak, alias("Default_Handler"))); 38 | void SysTick_Handler(void) __attribute__((weak, alias("Default_Handler"))); 39 | void WWDG_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 40 | void PVD_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 41 | void TAMP_STAMP_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 42 | void RTC_WKUP_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 43 | void RCC_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 44 | void EXTI0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 45 | void EXTI1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 46 | void EXTI2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 47 | void EXTI3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 48 | void EXTI4_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 49 | void DMA1_Channel1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 50 | void DMA1_Channel2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 51 | void DMA1_Channel3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 52 | void DMA1_Channel4_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 53 | void DMA1_Channel5_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 54 | void DMA1_Channel6_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 55 | void DMA1_Channel7_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 56 | void ADC_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 57 | void USB_HP_CAN_TX_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 58 | void USB_LP_CAN_RX0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 59 | void CAN_RX1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 60 | void CAN_SCE_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 61 | void EXTI9_5_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 62 | void TIM1_BRK_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 63 | void TIM1_UP_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 64 | void TIM1_TRG_COM_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 65 | void TIM1_CC_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 66 | void TIM2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 67 | void TIM3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 68 | void TIM4_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 69 | void I2C1_EV_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 70 | void I2C1_ER_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 71 | void I2C2_EV_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 72 | void I2C2_ER_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 73 | void SPI1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 74 | void SPI2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 75 | void USART1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 76 | void USART2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 77 | void USART3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 78 | void EXTI15_10_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 79 | void RTC_Alarm_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 80 | void USB_Wakeup_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 81 | void TIM8_BRK_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 82 | void TIM8_UP_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 83 | void TIM8_TRG_COM_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 84 | void TIM8_CC_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 85 | void ADC3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 86 | void FSMC_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 87 | void SDIO_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 88 | void TIM5_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 89 | void SPI3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 90 | void UART4_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 91 | void UART5_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 92 | void TIM6_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 93 | void TIM7_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 94 | void DMA2_Channel1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 95 | void DMA2_Channel2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 96 | void DMA2_Channel3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 97 | void DMA2_Channel4_5_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 98 | 99 | // Define the veector table 100 | uint32_t vectors[] __attribute__((section(".isr_vector"))) = { 101 | STACK_START, 102 | (uint32_t)Reset_Handler, 103 | (uint32_t)NMI_Handler, 104 | (uint32_t)HardFault_Handler, 105 | (uint32_t)MemManage_Handler, 106 | (uint32_t)BusFault_Handler, 107 | (uint32_t)UsageFault_Handler, 108 | 0, // reserved 109 | 0, // reserved 110 | 0, // reserved 111 | 0, // reserved 112 | (uint32_t)SVC_Handler, 113 | (uint32_t)DebugMon_Handler, 114 | 0, // reserved 115 | (uint32_t)PendSV_Handler, 116 | (uint32_t)SysTick_Handler, 117 | (uint32_t)WWDG_IRQHandler, 118 | (uint32_t)PVD_IRQHandler, 119 | (uint32_t)TAMP_STAMP_IRQHandler, 120 | (uint32_t)RTC_WKUP_IRQHandler, 121 | 0, // Flash global interrupt 122 | (uint32_t)RCC_IRQHandler, 123 | (uint32_t)EXTI0_IRQHandler, 124 | (uint32_t)EXTI1_IRQHandler, 125 | (uint32_t)EXTI2_IRQHandler, 126 | (uint32_t)EXTI3_IRQHandler, 127 | (uint32_t)EXTI4_IRQHandler, 128 | (uint32_t)DMA1_Channel1_IRQHandler, 129 | (uint32_t)DMA1_Channel2_IRQHandler, 130 | (uint32_t)DMA1_Channel3_IRQHandler, 131 | (uint32_t)DMA1_Channel4_IRQHandler, 132 | (uint32_t)DMA1_Channel5_IRQHandler, 133 | (uint32_t)DMA1_Channel6_IRQHandler, 134 | (uint32_t)DMA1_Channel7_IRQHandler, 135 | (uint32_t)ADC_IRQHandler, 136 | (uint32_t)USB_HP_CAN_TX_IRQHandler, 137 | (uint32_t)USB_LP_CAN_RX0_IRQHandler, 138 | (uint32_t)CAN_RX1_IRQHandler, 139 | (uint32_t)CAN_SCE_IRQHandler, 140 | (uint32_t)EXTI9_5_IRQHandler, 141 | (uint32_t)TIM1_BRK_IRQHandler, 142 | (uint32_t)TIM1_UP_IRQHandler, 143 | (uint32_t)TIM1_TRG_COM_IRQHandler, 144 | (uint32_t)TIM1_CC_IRQHandler, 145 | (uint32_t)TIM2_IRQHandler, 146 | (uint32_t)TIM3_IRQHandler, 147 | (uint32_t)TIM4_IRQHandler, 148 | (uint32_t)I2C1_EV_IRQHandler, 149 | (uint32_t)I2C1_ER_IRQHandler, 150 | (uint32_t)I2C2_EV_IRQHandler, 151 | (uint32_t)I2C2_ER_IRQHandler, 152 | (uint32_t)SPI1_IRQHandler, 153 | (uint32_t)SPI2_IRQHandler, 154 | (uint32_t)USART1_IRQHandler, 155 | (uint32_t)USART2_IRQHandler, 156 | (uint32_t)USART3_IRQHandler, 157 | (uint32_t)EXTI15_10_IRQHandler, 158 | (uint32_t)RTC_Alarm_IRQHandler, 159 | (uint32_t)USB_Wakeup_IRQHandler, 160 | (uint32_t)TIM8_BRK_IRQHandler, 161 | (uint32_t)TIM8_UP_IRQHandler, 162 | (uint32_t)TIM8_TRG_COM_IRQHandler, 163 | (uint32_t)TIM8_CC_IRQHandler, 164 | (uint32_t)ADC3_IRQHandler, 165 | (uint32_t)FSMC_IRQHandler, 166 | (uint32_t)SDIO_IRQHandler, 167 | (uint32_t)TIM5_IRQHandler, 168 | (uint32_t)SPI3_IRQHandler, 169 | (uint32_t)UART4_IRQHandler, 170 | (uint32_t)UART5_IRQHandler, 171 | (uint32_t)TIM6_IRQHandler, 172 | (uint32_t)TIM7_IRQHandler, 173 | (uint32_t)DMA2_Channel1_IRQHandler, 174 | (uint32_t)DMA2_Channel2_IRQHandler, 175 | (uint32_t)DMA2_Channel3_IRQHandler, 176 | (uint32_t)DMA2_Channel4_5_IRQHandler, 177 | }; 178 | 179 | // Command: a default "do nothing" handler 180 | void Default_Handler(void) 181 | { 182 | while (1) 183 | ; 184 | } 185 | 186 | // Command: reset memory and restart user program 187 | [[noreturn]] void Reset_Handler(void) 188 | { 189 | // copy .data section to SRAM 190 | uint32_t data_size = (uint32_t)&_edata - (uint32_t)&_sdata; 191 | 192 | std::copy(&_la_data, &_la_data + data_size, &_sdata); 193 | 194 | // init. the .bss section to zero in SRAM 195 | std::fill(&_sbss, &_ebss, 0); 196 | // now invoke main 197 | main(); 198 | while (1) 199 | { 200 | __asm("nop"); 201 | } 202 | 203 | } 204 | 205 | void *memcpy(void *dest, const void *src, size_t n) 206 | { 207 | for (size_t i = 0; i < n; i++) 208 | { 209 | ((char*)dest)[i] = ((char*)src)[i]; 210 | } 211 | return dest; 212 | } -------------------------------------------------------------------------------- /stm32f1.ld: -------------------------------------------------------------------------------- 1 | ENTRY(Reset_Handler) 2 | 3 | MEMORY 4 | { 5 | FLASH(rx):ORIGIN =0x08000000,LENGTH =64K 6 | SRAM(rwx):ORIGIN =0x20000000,LENGTH =20K 7 | } 8 | 9 | SECTIONS 10 | { 11 | 12 | .isr_vector : 13 | { 14 | *(.isr_vector) 15 | . = ALIGN(4); 16 | }> FLASH 17 | 18 | .text : 19 | { 20 | *(.text) 21 | *(.text.*) 22 | *(.init) 23 | *(.fini) 24 | *(.rodata) 25 | *(.rodata.*) 26 | . = ALIGN(4); 27 | _etext = .; 28 | }> FLASH 29 | 30 | _la_data = LOADADDR(.data); 31 | 32 | .data : 33 | { 34 | _sdata = .; 35 | *(.data) 36 | *(.data.*) 37 | . = ALIGN(4); 38 | _edata = .; 39 | }> SRAM AT> FLASH 40 | 41 | .bss : 42 | { 43 | _sbss = .; 44 | __bss_start__ = _sbss; 45 | *(.bss) 46 | *(.bss.*) 47 | *(COMMON) 48 | . = ALIGN(4); 49 | _ebss = .; 50 | __bss_end__ = _ebss; 51 | . = ALIGN(4); 52 | end = .; 53 | __end__ = .; 54 | }> SRAM 55 | } 56 | --------------------------------------------------------------------------------