├── .gitattributes ├── .gitignore ├── .vscode ├── c_cpp_properties.json └── launch.json ├── LICENSE ├── Makefile ├── docs └── perfect-wave.png ├── linker └── AT32F421_FLASH.ld ├── readme.md ├── script └── jlink-download.sh ├── src ├── app │ ├── main.cpp │ ├── printf.cpp │ ├── sound.cpp │ └── sound.h ├── board │ ├── board.h │ ├── board_at32f421_v1_0.h │ └── board_at32f421_v1_1.h ├── config │ ├── config.cpp │ └── config.h ├── motor │ ├── motor.h │ └── src │ │ ├── bldc.cpp │ │ ├── bldc.h │ │ └── motor.cpp ├── msp │ ├── msp.h │ └── src │ │ ├── AT32F421 │ │ ├── adc.cpp │ │ ├── adc.h │ │ ├── cmp.cpp │ │ ├── cmp.h │ │ ├── crc.cpp │ │ ├── crc.h │ │ ├── flash.cpp │ │ ├── flash.h │ │ ├── gpio.cpp │ │ ├── gpio.h │ │ ├── motor-gpio.cpp │ │ ├── motor-gpio.h │ │ ├── motor-pwm.cpp │ │ ├── motor-pwm.h │ │ ├── msp.cpp │ │ ├── signal-pwm.cpp │ │ ├── signal-pwm.h │ │ ├── stdlib │ │ │ ├── at32f421.h │ │ │ ├── at32f421_adc.c │ │ │ ├── at32f421_adc.h │ │ │ ├── at32f421_cmp.c │ │ │ ├── at32f421_cmp.h │ │ │ ├── at32f421_conf.h │ │ │ ├── at32f421_crc.c │ │ │ ├── at32f421_crc.h │ │ │ ├── at32f421_crm.c │ │ │ ├── at32f421_crm.h │ │ │ ├── at32f421_debug.c │ │ │ ├── at32f421_debug.h │ │ │ ├── at32f421_def.h │ │ │ ├── at32f421_dma.c │ │ │ ├── at32f421_dma.h │ │ │ ├── at32f421_ertc.c │ │ │ ├── at32f421_ertc.h │ │ │ ├── at32f421_exint.c │ │ │ ├── at32f421_exint.h │ │ │ ├── at32f421_flash.c │ │ │ ├── at32f421_flash.h │ │ │ ├── at32f421_gpio.c │ │ │ ├── at32f421_gpio.h │ │ │ ├── at32f421_i2c.c │ │ │ ├── at32f421_i2c.h │ │ │ ├── at32f421_misc.c │ │ │ ├── at32f421_misc.h │ │ │ ├── at32f421_pwc.c │ │ │ ├── at32f421_pwc.h │ │ │ ├── at32f421_scfg.c │ │ │ ├── at32f421_scfg.h │ │ │ ├── at32f421_spi.c │ │ │ ├── at32f421_spi.h │ │ │ ├── at32f421_tmr.c │ │ │ ├── at32f421_tmr.h │ │ │ ├── at32f421_usart.c │ │ │ ├── at32f421_usart.h │ │ │ ├── at32f421_wdt.c │ │ │ ├── at32f421_wdt.h │ │ │ ├── at32f421_wwdt.c │ │ │ ├── at32f421_wwdt.h │ │ │ ├── system_at32f421.c │ │ │ └── system_at32f421.h │ │ ├── tim.cpp │ │ ├── tim.h │ │ ├── usart.cpp │ │ └── usart.h │ │ └── cm4 │ │ ├── arm_common_tables.h │ │ ├── arm_const_structs.h │ │ ├── arm_helium_utils.h │ │ ├── arm_math.h │ │ ├── arm_mve_tables.h │ │ ├── arm_vec_math.h │ │ ├── cmsis_armcc.h │ │ ├── cmsis_armclang.h │ │ ├── cmsis_armclang_ltm.h │ │ ├── cmsis_compiler.h │ │ ├── cmsis_gcc.h │ │ ├── cmsis_iccarm.h │ │ ├── cmsis_version.h │ │ ├── core_cm4.h │ │ ├── mpu_armv7.h │ │ ├── mpu_armv8.h │ │ └── pmu_armv8.h ├── protocol │ ├── protocol.h │ └── src │ │ ├── dshot.cpp │ │ ├── dshot.h │ │ ├── oneshot.cpp │ │ ├── oneshot.h │ │ ├── protocol.cpp │ │ ├── serial.cpp │ │ └── serial.h └── startup │ └── at32f421 │ └── startup_at32f421.s └── svd └── AT32F421xx_v2.svd /.gitattributes: -------------------------------------------------------------------------------- 1 | LICENSE text eol=lf 2 | *.md text eol=lf 3 | *.c text eol=lf 4 | *.cpp text eol=lf 5 | *.h text eol=lf 6 | *.S text eol=lf 7 | *.s text eol=lf 8 | *.hex -crlf -diff 9 | *.elf -crlf -diff 10 | *.ld text eol=lf 11 | Makefile text eol=lf 12 | *.mk text eol=lf 13 | *.nomk text eol=lf 14 | *.pl text eol=lf 15 | *.js text eol=lf 16 | *.json text eol=lf 17 | *.html text eol=lf 18 | *.css text eol=lf 19 | *.svg text eol=lf 20 | *.png -crlf -diff 21 | *.yml text eol=lf 22 | *.xml text eol=lf 23 | *.mcm text eol=lf 24 | *.nsi text eol=lf 25 | *.nsh text eol=lf 26 | *.lua text eol=lf 27 | *.txt text eol=lf 28 | *.sh text eol=lf 29 | *.config text eol=lf 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | build 4 | 5 | # only allowed new linker file 6 | linker 7 | 8 | # artefacts for VS Code 9 | .vscode/ 10 | 11 | 12 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ // just used for code viewing, have no effect on compiling 3 | { 4 | "name": "lax-vtx", 5 | "includePath": [ 6 | "${workspaceFolder}/src/**" 7 | ], 8 | "defines": [ 9 | "AT32F421G8U7", 10 | "at32f421_v1_0", 11 | "USE_STDPERIPH_DRIVER" 12 | ], 13 | "compilerPath": "D:/develop/gcc-arm/bin/arm-none-eabi-g++.exe", 14 | "cStandard": "c17", 15 | "cppStandard": "gnu++17", 16 | "intelliSenseMode": "linux-gcc-arm", 17 | "forcedInclude": [ 18 | 19 | ] 20 | } 21 | ], 22 | "version": 4 23 | } -------------------------------------------------------------------------------- /.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": "${workspaceFolder}/build/at32f421_v1_1.elf", 11 | "request": "launch", 12 | "type": "cortex-debug", 13 | "runToEntryPoint": "main", 14 | "device": "-at32f421g8u7", 15 | "interface": "swd", 16 | "servertype": "jlink", 17 | "serverpath": "C:/Program Files/SEGGER/JLink/JLinkGDBServerCL.exe", 18 | "svdFile": "${workspaceFolder}/svd/at32f421xx_v2.svd", 19 | //"armToolchainPath": "/root/betaflight/tools/gcc-arm-none-eabi-10.3-2021.10/bin", 20 | "showDevDebugOutput": "raw" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ########################################################################################################################## 2 | # File automatically-generated by tool: [projectgenerator] version: [3.19.2] date: [Sat Sep 02 18:56:37 CST 2023] 3 | ########################################################################################################################## 4 | 5 | # ------------------------------------------------ 6 | # Generic Makefile (based on gcc) 7 | # 8 | # ChangeLog : 9 | # 2017-02-10 - Several enhancements + project update mode 10 | # 2015-07-22 - first version 11 | # ------------------------------------------------ 12 | 13 | ###################################### 14 | # target 15 | ###################################### 16 | BOARD ?= at32f421_v1_1 17 | TARGET = $(BOARD) 18 | MCU_FAMILY = at32f421 19 | DEVICE = at32f421x8 20 | FLASH_SIZE = 64k 21 | RAM_SIZE = 16k 22 | HEAP_SIZE = 0XC00 23 | STACK_SIZE = 0X400 24 | 25 | ####################################### 26 | # download script 27 | ####################################### 28 | DOWNLOAD_SCRIP = "script/jlink-download.sh" 29 | 30 | ####################################### 31 | # link script 32 | ####################################### 33 | 34 | LDSCRIPT := linker/$(MCU_FAMILY)_flash.ld 35 | 36 | ###################################### 37 | # building variables 38 | ###################################### 39 | # debug build? 40 | DEBUG ?= 0 41 | 42 | ####################################### 43 | # paths 44 | ####################################### 45 | # Build output directory 46 | BUILD_DIR = build 47 | 48 | ###################################### 49 | # source 50 | ###################################### 51 | APP_LAYER_DIR = src/app 52 | MTR_LAYER_DIR = src/motor 53 | PRO_LAYER_DIR = src/protocol 54 | MSP_LAYER_DIR = src/msp 55 | START_UP_DIR = src/startup/$(MCU_FAMILY) 56 | CONFIG_DIR = src/config 57 | BOARD_DEF_DIR = src/board 58 | 59 | APP_LAYER_INCLUDE = $(BOARD_DEF_DIR) $(APP_LAYER_DIR) $(MTR_LAYER_DIR) $(MSP_LAYER_DIR) $(PRO_LAYER_DIR) $(CONFIG_DIR) 60 | PRO_LAYER_INCLUDE = $(BOARD_DEF_DIR) $(PRO_LAYER_DIR) $(PRO_LAYER_DIR)/src $(MSP_LAYER_DIR) $(MTR_LAYER_DIR) $(CONFIG_DIR) 61 | MTR_LAYER_INCLUDE = $(BOARD_DEF_DIR) $(MTR_LAYER_DIR) $(MTR_LAYER_DIR)/src $(MSP_LAYER_DIR) $(CONFIG_DIR) 62 | MSP_LAYER_INCLUDE = $(MSP_LAYER_DIR) $(MSP_LAYER_DIR)/src/$(MCU_FAMILY) $(MSP_LAYER_DIR)/src/$(MCU_FAMILY)/stdlib src/msp/src/cm4 63 | 64 | SOURCES_DIR = $(START_UP_DIR) $(CONFIG_DIR) $(APP_LAYER_DIR) $(MTR_LAYER_DIR)/src $(PRO_LAYER_DIR)/src $(MSP_LAYER_DIR)/src $(MSP_LAYER_DIR)/src/$(MCU_FAMILY) $(MSP_LAYER_DIR)/src/$(MCU_FAMILY)/stdlib 65 | 66 | SOURCES = $(wildcard $(foreach i,$(SOURCES_DIR),$(i)/*.c $(i)/*.cpp $(i)/*.s)) 67 | 68 | OBJECTS = $(addsuffix .o,$(basename $(SOURCES:src/%=%))) 69 | 70 | ####################################### 71 | # binaries 72 | ####################################### 73 | PREFIX = arm-none-eabi- 74 | # The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx) 75 | # either it can be added to the PATH environment variable. 76 | ifdef GCC_PATH 77 | CC = $(GCC_PATH)/$(PREFIX)gcc 78 | CXX = $(GCC_PATH)/$(PREFIX)g++ 79 | AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp 80 | CP = $(GCC_PATH)/$(PREFIX)objcopy 81 | SZ = $(GCC_PATH)/$(PREFIX)size 82 | else 83 | CC = $(PREFIX)gcc 84 | CXX = $(PREFIX)g++ 85 | AS = $(PREFIX)gcc -x assembler-with-cpp 86 | CP = $(PREFIX)objcopy 87 | SZ = $(PREFIX)size 88 | endif 89 | HEX = $(CP) -O ihex 90 | BIN = $(CP) -O binary -S 91 | 92 | ####################################### 93 | # CFLAGS 94 | ####################################### 95 | # cpu 96 | CPU = -mcpu=cortex-m4 97 | 98 | # fpu 99 | FPU = 100 | 101 | # float-abi 102 | FLOAT-ABI = 103 | 104 | # mcu 105 | MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI) 106 | 107 | # macros for gcc 108 | # AS defines 109 | AS_DEFS = 110 | 111 | # C defines 112 | C_DEFS = \ 113 | -DAT32F421G8U7 \ 114 | -DUSE_STDPERIPH_DRIVER \ 115 | -DAT_START_F421_V1 \ 116 | -DUSE_PA_RFPA5542 \ 117 | -DUSE_RTC6705 118 | 119 | # AS includes 120 | AS_INCLUDES = 121 | 122 | 123 | # compile gcc flags 124 | ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections 125 | CFLAGS += $(MCU) $(C_DEFS) $(OPT) -Wall -fdata-sections -ffunction-sections -D$(BOARD) 126 | 127 | ifeq ($(DEBUG), 1) 128 | CFLAGS += -Og -g -gdwarf-2 129 | else 130 | CFLAGS += -O3 -g -DNDEBUG 131 | endif 132 | 133 | # Generate dependency information 134 | CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" 135 | 136 | ####################################### 137 | # LDFLAGS 138 | ####################################### 139 | 140 | # libraries 141 | LIBS = -lc -lm -lnosys 142 | LIBDIR = 143 | LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections #-u _printf_float 144 | # default action: build all 145 | all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin 146 | 147 | define make_build_dir 148 | @if [ ! -d `dirname $(1)` ]; then mkdir -p `dirname $(1)`; fi 149 | endef 150 | 151 | define get_include_dir 152 | @case $(1) in \ 153 | *app/*) INCLUDE_DIR="$(foreach i,$(APP_LAYER_INCLUDE),-I$(i))";; \ 154 | *motor/*) INCLUDE_DIR="$(foreach i,$(MTR_LAYER_INCLUDE),-I$(i))";; \ 155 | *msp/*) INCLUDE_DIR="$(foreach i,$(MSP_LAYER_INCLUDE),-I$(i))";; \ 156 | *protocol/*) INCLUDE_DIR="$(foreach i,$(PRO_LAYER_INCLUDE),-I$(i))";; \ 157 | *config/*) INCLUDE_DIR="$(foreach i,$(MSP_LAYER_INCLUDE),-I$(i))";; \ 158 | *) echo "####### error object: $(1) ########" ;; \ 159 | esac; echo -n $${INCLUDE_DIR} > $(BUILD_DIR)/$(dir $(1))/$(notdir $(1)).inc 160 | endef 161 | 162 | $(BUILD_DIR)/%.o: src/%.c Makefile 163 | $(call make_build_dir,$@) 164 | $(call get_include_dir,$*) 165 | $(CC) $(CFLAGS) `cat $(dir $@)/$(notdir $*).inc` -c $< -o $@ 166 | 167 | $(BUILD_DIR)/%.o: src/%.cpp Makefile 168 | $(call make_build_dir,$@) 169 | $(call get_include_dir,$*) 170 | $(CXX) $(CFLAGS) `cat $(dir $@)/$(notdir $*).inc` -c $< -o $@ 171 | 172 | $(BUILD_DIR)/%.o: src/%.s Makefile 173 | $(call make_build_dir,$@) 174 | $(AS) -c $(CFLAGS) $< -o $@ 175 | 176 | ####################################### 177 | # build the application 178 | ####################################### 179 | # list of objects 180 | $(LDSCRIPT): Makefile 181 | @sed -i "s/^FLASH_SIZE = .*/FLASH_SIZE = $(FLASH_SIZE);/" $(LDSCRIPT) 182 | @sed -i "s/^RAM_SIZE = .*/RAM_SIZE = $(RAM_SIZE);/" $(LDSCRIPT) 183 | @sed -i "s/^_Min_Heap_Size = .*/_Min_Heap_Size = $(HEAP_SIZE);/" $(LDSCRIPT) 184 | @sed -i "s/^_Min_Stack_Size = .*/_Min_Stack_Size = $(STACK_SIZE);/" $(LDSCRIPT) 185 | 186 | $(BUILD_DIR)/$(TARGET).elf: $(addprefix $(BUILD_DIR)/,$(OBJECTS)) $(LDSCRIPT) 187 | $(CXX) $(addprefix $(BUILD_DIR)/,$(OBJECTS)) $(LDFLAGS) -o $@ 188 | $(SZ) $@ 189 | 190 | $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf 191 | $(HEX) $< $@ 192 | 193 | $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf 194 | $(BIN) $< $@ 195 | 196 | 197 | ####################################### 198 | # clean up 199 | ####################################### 200 | clean: 201 | -rm -rf $(BUILD_DIR) 202 | 203 | ####################################### 204 | # download to mcu 205 | ####################################### 206 | download: $(BUILD_DIR)/$(TARGET).hex 207 | @echo start flashing...... 208 | @bash $(DOWNLOAD_SCRIP) $(DEVICE) $(BUILD_DIR)/$(TARGET).hex 209 | 210 | ####################################### 211 | # list all the target board suppported 212 | ####################################### 213 | list: 214 | @echo support target board list: 215 | @for i in `ls src/board`; do tmp=$${i#board}; tmp=$${tmp#_}; echo " $${tmp%.h}"; done 216 | 217 | 218 | ####################################### 219 | # dependencies 220 | ####################################### 221 | -include $(shell [ -d $(BUILD_DIR) ] && find $(BUILD_DIR) -name *.d) -------------------------------------------------------------------------------- /docs/perfect-wave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lax-fly/lax-esc/07811909a11757494ec3af564c478ab060603457/docs/perfect-wave.png -------------------------------------------------------------------------------- /linker/AT32F421_FLASH.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | ** 4 | ** File : AT32F421x8_FLASH.ld 5 | ** 6 | ** Abstract : Linker script for AT32F421x8 Device with 7 | ** 64KByte FLASH, 16KByte RAM 8 | ** 9 | ** Set heap size, stack size and stack location according 10 | ** to application requirements. 11 | ** 12 | ** Set memory bank area and size if external memory is used. 13 | ** 14 | ** 15 | ** Environment : Arm gcc toolchain 16 | ** 17 | ***************************************************************************** 18 | */ 19 | 20 | /* Entry Point */ 21 | ENTRY(Reset_Handler) 22 | 23 | /* Highest address of the user mode stack */ 24 | _estack = 0x20004000; /* end of RAM */ 25 | 26 | /* Generate a link error if heap and stack don't fit into RAM */ 27 | _Min_Heap_Size = 0XC00; 28 | _Min_Stack_Size = 0X400; 29 | 30 | FLASH_SIZE = 64k; 31 | RAM_SIZE = 16k; 32 | 33 | /* Specify the memory areas */ 34 | MEMORY 35 | { 36 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = FLASH_SIZE 37 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = RAM_SIZE 38 | } 39 | 40 | /* Define output sections */ 41 | SECTIONS 42 | { 43 | /* The startup code goes first into FLASH */ 44 | .isr_vector : 45 | { 46 | . = ALIGN(4); 47 | KEEP(*(.isr_vector)) /* Startup code */ 48 | . = ALIGN(4); 49 | } >FLASH 50 | 51 | /* The program code and other data goes into FLASH */ 52 | .text : 53 | { 54 | . = ALIGN(4); 55 | *(.text) /* .text sections (code) */ 56 | *(.text*) /* .text* sections (code) */ 57 | *(.glue_7) /* glue arm to thumb code */ 58 | *(.glue_7t) /* glue thumb to arm code */ 59 | *(.eh_frame) 60 | 61 | KEEP (*(.init)) 62 | KEEP (*(.fini)) 63 | 64 | . = ALIGN(4); 65 | _etext = .; /* define a global symbols at end of code */ 66 | } >FLASH 67 | 68 | /* Constant data goes into FLASH */ 69 | .rodata : 70 | { 71 | . = ALIGN(4); 72 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 73 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 74 | . = ALIGN(4); 75 | } >FLASH 76 | 77 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 78 | .ARM : { 79 | __exidx_start = .; 80 | *(.ARM.exidx*) 81 | __exidx_end = .; 82 | } >FLASH 83 | 84 | .preinit_array : 85 | { 86 | PROVIDE_HIDDEN (__preinit_array_start = .); 87 | KEEP (*(.preinit_array*)) 88 | PROVIDE_HIDDEN (__preinit_array_end = .); 89 | } >FLASH 90 | .init_array : 91 | { 92 | PROVIDE_HIDDEN (__init_array_start = .); 93 | KEEP (*(SORT(.init_array.*))) 94 | KEEP (*(.init_array*)) 95 | PROVIDE_HIDDEN (__init_array_end = .); 96 | } >FLASH 97 | .fini_array : 98 | { 99 | PROVIDE_HIDDEN (__fini_array_start = .); 100 | KEEP (*(SORT(.fini_array.*))) 101 | KEEP (*(.fini_array*)) 102 | PROVIDE_HIDDEN (__fini_array_end = .); 103 | } >FLASH 104 | 105 | /* used by the startup to initialize data */ 106 | _sidata = LOADADDR(.data); 107 | 108 | /* Initialized data sections goes into RAM, load LMA copy after code */ 109 | .data : 110 | { 111 | . = ALIGN(4); 112 | _sdata = .; /* create a global symbol at data start */ 113 | *(.data) /* .data sections */ 114 | *(.data*) /* .data* sections */ 115 | 116 | . = ALIGN(4); 117 | _edata = .; /* define a global symbol at data end */ 118 | } >RAM AT> FLASH 119 | 120 | /* Uninitialized data section */ 121 | . = ALIGN(4); 122 | .bss : 123 | { 124 | /* This is used by the startup in order to initialize the .bss secion */ 125 | _sbss = .; /* define a global symbol at bss start */ 126 | __bss_start__ = _sbss; 127 | *(.bss) 128 | *(.bss*) 129 | *(COMMON) 130 | 131 | . = ALIGN(4); 132 | _ebss = .; /* define a global symbol at bss end */ 133 | __bss_end__ = _ebss; 134 | } >RAM 135 | 136 | /* User_heap_stack section, used to check that there is enough RAM left */ 137 | ._user_heap_stack : 138 | { 139 | . = ALIGN(8); 140 | PROVIDE ( end = . ); 141 | PROVIDE ( _end = . ); 142 | . = . + _Min_Heap_Size; 143 | . = . + _Min_Stack_Size; 144 | . = ALIGN(8); 145 | } >RAM 146 | 147 | /* Remove information from the standard libraries */ 148 | /DISCARD/ : 149 | { 150 | libc.a ( * ) 151 | libm.a ( * ) 152 | libgcc.a ( * ) 153 | } 154 | 155 | .ARM.attributes 0 : { *(.ARM.attributes) } 156 | } 157 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # features 2 | 3 | 1. support DSHOT ONESHOT MULTISHOT PWM and BRUSH protocols, and 3D mode. 4 | 2. support protocol switching automatically at runtime 5 | 3. support PWM frequency up to 50kHz 6 | 4. support dynamic PWM frequence 7 | 5. support debug mode by serial port 8 | 6. support motor stalling prevention 9 | 7. throttle response rate up to 50/ms, which means 40ms for full throttle(2000) 10 | 11 | # requirements 12 | 13 | 1. Linux shell or Cygwin for windows. 14 | 2. arm-none-eabi-gcc 10.3. 15 | 3. J-Link adapter. 16 | 17 | # how to compile 18 | 19 | compiling steps like this: 20 | 21 | ```bash 22 | make -j # if gcc is not in your environment, use GCC_PATH=xxxxxx to specify it 23 | make download 24 | 25 | # or 26 | make BOARD=at32f421_v1_1 -j # the target board can be listed by 'make list', the board name should be the same as the suffix of file in the 'board' directory with prefix name 'board_' 27 | ``` 28 | 29 | watch this [video](https://www.bilibili.com/video/BV12x4y1W7Q2/?vd_source=43d9ea2f55b405b989b877e469b9fc2e) for more details. 30 | 31 | # debug mode 32 | 33 | ```bash 34 | make clean 35 | make -j DEBUG=1 36 | make download 37 | ``` 38 | 39 | the serial print is only available in debug mode, the baudrate is fixed to 256000. 40 | to shake hands with esc using SERIAL protocol, the host must use baudrate 256000 to send at least 48 continuous 0xff to the esc. 41 | once using SERIAL protocol, the esc will never switch to other protocol automatically except reset. 42 | 43 | Warning: debug mode is costly, which increase the risk of stalling at fast rpm. 44 | 45 | # SERIAL protocol 46 | 47 | 1. shake hands 48 | 49 | send more than 48 hex values of 0xff `0xff 0xff ...` to the esc. 50 | 51 | 2. arm the esc 52 | 53 | send string `arm` to the esc 54 | 55 | 3. spin the motor 56 | 57 | send string `throttle -2000~2000` to esc, e.g. `throttle -500` 58 | 59 | # hardware designation 60 | 61 | [click here](https://oshwhub.com/lax-fly/lax-esc-dev) 62 | 63 | # to be done -------------------------------------------------------------------------------- /script/jlink-download.sh: -------------------------------------------------------------------------------- 1 | 2 | ################################# 3 | # param 1: Device name 4 | # param 2: HEX file path 5 | ################################ 6 | 7 | JLINK_PATH="C:/Program Files/SEGGER/JLink/JLink.exe" 8 | 9 | MCU_FLY=$1 10 | HEX_FILE=$2 11 | 12 | case $MCU_FLY in 13 | at32f421?8*) 14 | DEVICE=-AT32F421G8U7 15 | ;; 16 | *) 17 | echo "error: unkown MCU family: $MCU_FLY" 18 | exit -1 19 | ;; 20 | esac 21 | 22 | ########## J-Link command line script ########### 23 | # select interface sw 24 | # set interface rate to 4000kHz 25 | # set mcu version 26 | # reset mcu 27 | # pause mcu 28 | # erase flash 29 | # download 30 | # run 31 | # exit jlink cmd line 32 | ################################################# 33 | echo " 34 | si 1 35 | speed 4000 36 | device $DEVICE 37 | r 38 | h 39 | erase 40 | loadfile \"$HEX_FILE\" 41 | r 42 | go 43 | q 44 | " > ./jlink-script.txt 45 | 46 | "${JLINK_PATH}" ./jlink-script.txt 47 | rm -f ./jlink-script.txt -------------------------------------------------------------------------------- /src/app/main.cpp: -------------------------------------------------------------------------------- 1 | #include "motor.h" 2 | #include "msp.h" 3 | #include "stdio.h" 4 | #include "protocol.h" 5 | #include "sound.h" 6 | #include "board.h" 7 | #include 8 | 9 | TimerIf *timer = nullptr; 10 | Protocol *proto = nullptr; 11 | MotorIf *motor = nullptr; 12 | Sound *sound = nullptr; 13 | 14 | #if !defined(NDEBUG) 15 | UsartIf *debug_usart = nullptr; 16 | Protocol *debug_proto = nullptr; 17 | GpioIf *debug_pin = nullptr; 18 | #endif 19 | 20 | uint8_t escInfoBuffer[64]; 21 | 22 | uint32_t dshot_bits; 23 | Protocol::Type proto_type; 24 | int throttle; 25 | 26 | #ifndef NDEBUG 27 | void print_routine() 28 | { 29 | static AdcIf *adc_bat = nullptr; 30 | if (adc_bat == nullptr) 31 | adc_bat = AdcIf::new_instance(ADC_BAT_PIN); 32 | 33 | const char* proto; 34 | static uint32_t run_time = 0; 35 | if (run_time < timer->now_ms()) 36 | { 37 | run_time = timer->now_ms() + 500; 38 | 39 | switch (proto_type) 40 | { 41 | case Protocol::SERIAL: 42 | proto = "SERIAL"; 43 | break; 44 | case Protocol::DSHOT: 45 | proto = "DSHOT"; 46 | break; 47 | case Protocol::BRUSHED: 48 | proto = "BRUSHED"; 49 | break; 50 | case Protocol::STD_PWM: 51 | proto = "STD_PWM"; 52 | break; 53 | case Protocol::ONESHOT: 54 | proto = "ONESHOT"; 55 | break; 56 | case Protocol::PROSHOT: 57 | proto = "PROSHOT"; 58 | break; 59 | 60 | default: // AUTO_DETECT 61 | proto = "NONE"; 62 | break; 63 | } 64 | printf("prot: %s throt: %d pwm: %d rpm: %d cur: %u valt: %lu\n", 65 | proto, 66 | motor->get_throttle(), 67 | motor->get_real_throttle(), 68 | motor->get_rpm(), 69 | motor->get_current(), 70 | adc_bat->sample_voltage() * config.voltage_gain); 71 | } 72 | } 73 | #endif 74 | 75 | #define PWM_TEST 0 76 | uint32_t pulse; 77 | void pwm_test(void) 78 | { 79 | #if PWM_TEST == 1 80 | MotorPwmIf *pwm = MotorPwmIf::new_instance(MOS_A_HIGH_PIN, MOS_B_HIGH_PIN, MOS_C_HIGH_PIN); 81 | pwm->set_freq(1000); 82 | pwm->set_dutycycle(DUTY_CYCLE(0.5f)); 83 | while (1) 84 | { 85 | } 86 | #elif PWM_TEST == 2 87 | SignalPwmIf *pwm = SignalPwmIf::new_instance(SIGNAL_IN_PIN); 88 | pwm->set_mode(SignalPwmIf::PULSE_OUTPUT_CAPTURE); 89 | uint32_t pulses[] = {400000, 300000, 10000, 1000}; 90 | while (1) 91 | { 92 | timer->delay_ms(10); 93 | pwm->send_pulses(pulses, 4, 500000); 94 | } 95 | #elif PWM_TEST == 3 96 | SignalPwmIf *pwm = SignalPwmIf::new_instance(SIGNAL_IN_PIN); 97 | pwm->set_mode(SignalPwmIf::PULSE_OUTPUT_CAPTURE); 98 | uint32_t pulses[32]; 99 | while (1) 100 | { 101 | pwm->recv_pulses(pulses, 31); 102 | timer->delay_ms(100); 103 | if (pwm->recv_pulses() == 31) 104 | { 105 | static char buf[256] = {0}; 106 | int len = 0; 107 | for (uint32_t i = 0; i < 31; i++) 108 | { 109 | len += sprintf(buf + len, "%4lu ", pulses[i]); 110 | } 111 | buf[len] = '\n'; 112 | buf[len + 1] = 0; 113 | printf("%s", buf); 114 | } 115 | } 116 | #elif PWM_TEST == 4 117 | SignalPwmIf *pwm = SignalPwmIf::new_instance(SIGNAL_IN_PIN); 118 | pwm->set_mode(SignalPwmIf::UP_PULSE_CAPTURE); 119 | pwm->set_up_pulse_callback([](uint32_t p) 120 | { pulse = p; }); 121 | while (1) 122 | { 123 | timer->delay_ms(500); 124 | printf("%lu\n", pulse); 125 | } 126 | #endif 127 | } 128 | 129 | int main(void) 130 | { 131 | system_init(); 132 | timer = TimerIf::singleton(); 133 | 134 | #if !defined(NDEBUG) 135 | #if DEBUG_PIN != PIN_NONE 136 | debug_pin = GpioIf::new_instance(DEBUG_PIN); 137 | debug_pin->set_mode(GpioIf::OUTPUT); 138 | #endif 139 | debug_usart = UsartIf::new_instance(PB6, PB7, 256000, 1); 140 | debug_proto = Protocol::singleton(Protocol::SERIAL, PIN_NONE); 141 | #endif 142 | 143 | config.load(); 144 | motor = MotorIf::singleton(MotorIf::BLDC); 145 | sound = new Sound(motor); 146 | sound->power_on_tone(); 147 | #if PWM_TEST > 0 148 | pwm_test(); 149 | #endif 150 | proto_type = Protocol::auto_detect(SIGNAL_IN_PIN); 151 | proto = Protocol::singleton(proto_type, SIGNAL_IN_PIN); 152 | sound->throttle_signal_detected_tone(); 153 | while (1) // don't make one loop take more than 10us, motor->poll must be called once per <10us 154 | { 155 | if (__builtin_expect(proto->signal_lost(), false)) 156 | { 157 | proto_type = Protocol::auto_detect(SIGNAL_IN_PIN); 158 | proto = Protocol::singleton(proto_type, SIGNAL_IN_PIN); 159 | sound->throttle_signal_detected_tone(); 160 | } 161 | motor->poll(); 162 | proto->poll(); 163 | motor->poll(); 164 | #if !defined(NDEBUG) 165 | debug_proto->poll(); 166 | print_routine(); 167 | #endif 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/app/printf.cpp: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | #include "assert.h" 3 | #include "msp.h" 4 | #include "motor.h" 5 | 6 | extern UsartIf *debug_usart; 7 | extern MotorIf *motor; 8 | extern TimerIf *timer; 9 | 10 | extern "C" 11 | { 12 | #include "stdio.h" 13 | #include "unistd.h" 14 | #include 15 | #include 16 | 17 | // refer to https://blog.csdn.net/CooCox_UP_Team/article/details/8465143 18 | 19 | extern int _end; // the heap region, defined in ld script 20 | extern int _Min_Heap_Size; 21 | 22 | caddr_t _sbrk(int incr) 23 | { 24 | static unsigned char *heap = NULL; 25 | unsigned char *prev_heap; 26 | if (heap == NULL) 27 | { 28 | heap = (unsigned char *)&_end; 29 | } 30 | prev_heap = heap; 31 | heap += incr; 32 | if ((uint32_t)heap > (uint32_t)((char *)&_end + _Min_Heap_Size)) 33 | return nullptr; 34 | 35 | return (caddr_t)prev_heap; 36 | } 37 | 38 | int _close(int file) 39 | { 40 | return 0; 41 | } 42 | int _fstat(int file, struct stat *st) 43 | { 44 | st->st_mode = S_IFCHR; // char device 45 | return 0; 46 | } 47 | int _isatty(int file) 48 | { 49 | return 1; // terminal device 50 | } 51 | int _lseek(int file, int ptr, int dir) 52 | { 53 | return 0; 54 | } 55 | int _read(int file, char *ptr, int len) 56 | { 57 | #ifndef NDEBUG 58 | if (debug_usart) 59 | return debug_usart->async_recv((uint8_t *)ptr, len); 60 | else 61 | #endif 62 | return 0; 63 | } 64 | int _write(int file, char *ptr, int len) 65 | { 66 | #ifndef NDEBUG 67 | if (debug_usart) 68 | { 69 | if (ptr[0] == '\r') 70 | debug_usart->sync_send((uint8_t *)ptr + 1, len - 1); 71 | else 72 | debug_usart->async_send((uint8_t *)ptr, len); 73 | } 74 | #endif 75 | return len; 76 | } 77 | void abort(void) 78 | { 79 | if (motor) 80 | motor->set_throttle(0); // avoid motor burning in case motor is running at high dutycycle when dead exception happens 81 | /* Abort called */ 82 | while (1) 83 | { 84 | #ifndef NDEBUG 85 | if (timer) 86 | timer->delay_ms(1000); 87 | if (debug_usart) 88 | debug_usart->sync_send((const uint8_t *)"exception happened\n", 19); 89 | #endif 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/app/sound.cpp: -------------------------------------------------------------------------------- 1 | #include "sound.h" 2 | 3 | void Sound::power_on_tone(void) 4 | { 5 | motor->beep(TONE2, MotorIf::VOLUME_LOW); 6 | timer->delay_ms(200); 7 | 8 | motor->beep(TONE3, MotorIf::VOLUME_LOW); 9 | timer->delay_ms(200); 10 | 11 | motor->beep(TONE4, MotorIf::VOLUME_LOW); 12 | timer->delay_ms(200); 13 | motor->beep(TONE4, MotorIf::VOLUME_OFF); 14 | } 15 | 16 | void Sound::throttle_signal_detected_tone(void) 17 | { 18 | timer->delay_ms(200); 19 | motor->beep(TONE2, MotorIf::VOLUME_LOW); 20 | timer->delay_ms(500); 21 | motor->beep(TONE2, MotorIf::VOLUME_OFF); 22 | } 23 | 24 | void Sound::armed_tone(void) 25 | { 26 | motor->beep(TONE5, MotorIf::VOLUME_LOW); 27 | timer->delay_ms(500); 28 | motor->beep(TONE5, MotorIf::VOLUME_OFF); 29 | } 30 | -------------------------------------------------------------------------------- /src/app/sound.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "motor.h" 4 | #include "msp.h" 5 | 6 | extern TimerIf *timer; 7 | extern MotorIf *motor; 8 | 9 | class Sound 10 | { 11 | private: 12 | TimerIf *timer; 13 | MotorIf *motor; 14 | 15 | public: 16 | Sound(MotorIf *motor) : motor(motor) { timer = TimerIf::singleton(); } 17 | void power_on_tone(void); 18 | void armed_tone(void); 19 | void throttle_signal_detected_tone(void); 20 | }; -------------------------------------------------------------------------------- /src/board/board.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef at32f421_v1_0 4 | #include "board_at32f421_v1_0.h" 5 | #endif 6 | 7 | #ifdef at32f421_v1_1 8 | #include "board_at32f421_v1_1.h" 9 | #endif 10 | 11 | -------------------------------------------------------------------------------- /src/board/board_at32f421_v1_0.h: -------------------------------------------------------------------------------- 1 | 2 | #define MOS_A_HIGH_PIN PA10 3 | #define MOS_B_HIGH_PIN PA9 4 | #define MOS_C_HIGH_PIN PA8 5 | 6 | #define MOS_A_LOW_PIN PB1 7 | #define MOS_B_LOW_PIN PB0 8 | #define MOS_C_LOW_PIN PA7 9 | 10 | #define CMP_A_POS_PIN PA5 11 | #define CMP_B_POS_PIN PA1 12 | #define CMP_C_POS_PIN PA0 13 | 14 | #define CMP_A_NEG_PIN PA2 15 | #define CMP_B_NEG_PIN PA2 16 | #define CMP_C_NEG_PIN PA2 17 | 18 | #define CMP_OUT_PIN PIN_NONE 19 | 20 | #define ADC_A_PIN CMP_A_POS_PIN 21 | #define ADC_B_PIN CMP_B_POS_PIN 22 | #define ADC_C_PIN CMP_C_POS_PIN 23 | 24 | #define ADC_BAT_PIN PA6 // if defined NONE, default 12v is used, you need to change it by configurator 25 | #define ADC_CUR_PIN PA4 26 | 27 | #define DEBUG_PIN PIN_NONE 28 | 29 | #define SIGNAL_IN_PIN PB4 30 | -------------------------------------------------------------------------------- /src/board/board_at32f421_v1_1.h: -------------------------------------------------------------------------------- 1 | 2 | #define MOS_A_HIGH_PIN PA10 3 | #define MOS_B_HIGH_PIN PA9 4 | #define MOS_C_HIGH_PIN PA8 5 | 6 | #define MOS_A_LOW_PIN PB1 7 | #define MOS_B_LOW_PIN PB0 8 | #define MOS_C_LOW_PIN PA7 9 | 10 | #define CMP_A_POS_PIN PA5 11 | #define CMP_B_POS_PIN PA1 12 | #define CMP_C_POS_PIN PA0 13 | 14 | #define CMP_A_NEG_PIN PA2 15 | #define CMP_B_NEG_PIN PA2 16 | #define CMP_C_NEG_PIN PA2 17 | 18 | #ifndef NDEBUG 19 | #define CMP_OUT_PIN PA6 20 | #else 21 | #define CMP_OUT_PIN PIN_NONE 22 | #endif 23 | 24 | #define ADC_A_PIN CMP_A_POS_PIN 25 | #define ADC_B_PIN CMP_B_POS_PIN 26 | #define ADC_C_PIN CMP_C_POS_PIN 27 | 28 | #define ADC_BAT_PIN PA3 29 | #define ADC_CUR_PIN PA4 30 | 31 | #define SIGNAL_IN_PIN PB4 32 | -------------------------------------------------------------------------------- /src/config/config.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "msp.h" 3 | #include "stdio.h" 4 | 5 | Config config; 6 | #define CONFIG_VERSION 0xaa550001 7 | 8 | void Config::save() 9 | { 10 | FlashIf *flash = FlashIf::singleton(); 11 | flash->write((uint8_t *)&config, sizeof(config)); 12 | } 13 | 14 | void print_config(void) 15 | { 16 | const char *degree = ""; 17 | switch (config.commutate_angle) 18 | { 19 | case ANGLE_30: 20 | degree = "30"; 21 | break; 22 | case ANGLE_15: 23 | degree = "15"; 24 | break; 25 | case ANGLE_7_5: 26 | degree = "7.5"; 27 | break; 28 | case ANGLE_3_75: 29 | degree = "3.75"; 30 | break; 31 | case ANGLE_1_875: 32 | degree = "1.875"; 33 | break; 34 | 35 | default: 36 | break; 37 | } 38 | // \r means using sync print, without \r starting, async print is used 39 | printf("\r################### configuration start ####################\n"); 40 | printf("\r version: %7lu\n", config.version); 41 | printf("\r serial telemetry: %7s\n", config.serial_telemetry ? "on" : "off"); 42 | printf("\r 3d mode: %7s\n", config.mode_3d ? "on" : "off"); 43 | printf("\r EDT mode: %7s\n", config.edt_mode ? "on" : "off"); 44 | printf("\r spin reversed: %7s\n", config.spin_dir_reverse ? "on" : "off"); 45 | printf("\r polar count: %7lu\n", config.polar_cnt); 46 | printf("\r motor kv: %7lu\n", config.kv); 47 | printf("\r blind comutate interval: %7lu us\n", config.blind_interval); 48 | printf("\r startup frequence: %7lu\n", config.startup_freq); 49 | printf("\r commutate angle: %7s'\n", degree); 50 | printf("\r bemf threshold: %7lu mV\n", config.bemf_threshold); 51 | printf("\r max pwm frequence: %7lu\n", config.max_pwm_freq); 52 | printf("\r current gain: %7lu\n", config.current_gain); 53 | printf("\r voltage gain: %7lu\n", config.voltage_gain); 54 | printf("\r multishot min: %7lu ns\n", config.multishot_min); 55 | printf("\r multishot max: %7lu ns\n", config.multishot_max); 56 | printf("\r oneshot42 min: %7lu ns\n", config.oneshot42_min); 57 | printf("\r oneshot84 max: %7lu ns\n", config.oneshot42_max); 58 | printf("\r oneshot125 min: %7lu ns\n", config.oneshot125_min); 59 | printf("\r oneshot250 max: %7lu ns\n", config.oneshot125_max); 60 | printf("\r pwm max: %7lu ns\n", config.pwm_min); 61 | printf("\r pwm min: %7lu ns\n", config.pwm_max); 62 | printf("\r################### configuration end ####################\n"); 63 | } 64 | 65 | void Config::load() 66 | { 67 | FlashIf *flash = FlashIf::singleton(); 68 | flash->read((uint8_t *)&config, sizeof(config)); 69 | if (config.version == CONFIG_VERSION) 70 | { 71 | print_config(); 72 | return; 73 | } 74 | 75 | config.version = CONFIG_VERSION; 76 | config.serial_telemetry = false; 77 | config.mode_3d = false; 78 | config.edt_mode = false; 79 | config.spin_dir_reverse = false; 80 | 81 | config.polar_cnt = 14; // the polar count of the target motor 82 | config.kv = 1400; // rpm/v while empty load, used to judge current load 83 | config.blind_interval = 20000; // us 84 | config.startup_freq = 5000; // Hz 85 | config.commutate_angle = ANGLE_30; 86 | config.bemf_threshold = 50; // mV 87 | config.max_pwm_freq = 50000; // Hz 88 | config.current_gain = 5; // the real current(mA) value divided by voltage(mV) from adc 89 | config.voltage_gain = 11; // the read voltage value divided by voltage(mV) from adc 90 | 91 | config.multishot_min = 5000; 92 | config.multishot_max = 25000; 93 | config.oneshot42_min = 42000; 94 | config.oneshot42_max = 84000; 95 | config.oneshot125_min = 125000; 96 | config.oneshot125_max = 250000; 97 | config.pwm_min = 1000000; 98 | config.pwm_max = 2000000; 99 | print_config(); 100 | } -------------------------------------------------------------------------------- /src/config/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stdint.h" 4 | 5 | enum Angle 6 | { // for bldc 7 | ANGLE_1_875 = 5, // degree 1.875 8 | ANGLE_3_75 = 4, // degree 3.75 9 | ANGLE_7_5 = 3, // degree 7.5 10 | ANGLE_15 = 2, // degree 15 11 | ANGLE_30 = 1, // degree 30 12 | }; 13 | 14 | struct Config 15 | { 16 | uint32_t version; 17 | 18 | bool edt_mode = false; // Extended DShot Telemetry (EDT) 19 | bool serial_telemetry = false; // use serial telemetry?, on the bf configurator, you should enable esc sensor 20 | bool mode_3d; 21 | bool spin_dir_reverse; 22 | 23 | uint32_t polar_cnt; // the polar count of the target motor 24 | uint32_t kv; // rpm/v while empty load, used to judge current load 25 | uint32_t blind_interval; // us 26 | uint32_t startup_freq; // Hz 27 | Angle commutate_angle; 28 | uint32_t bemf_threshold; // mV 29 | uint32_t max_pwm_freq; // Hz 30 | uint32_t current_gain; // the real current(mA) value divided by voltage(mV) from adc 31 | uint32_t voltage_gain; // the read voltage value divided by voltage(mV) from adc 32 | 33 | // calibration value for shot type protocol 34 | uint32_t multishot_min; 35 | uint32_t multishot_max; 36 | uint32_t oneshot42_min; 37 | uint32_t oneshot42_max; 38 | uint32_t oneshot125_min; 39 | uint32_t oneshot125_max; 40 | uint32_t pwm_min; 41 | uint32_t pwm_max; 42 | 43 | void save(); 44 | void load(); 45 | } __attribute__((aligned(4))); 46 | 47 | extern Config config; -------------------------------------------------------------------------------- /src/motor/motor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "config.h" 5 | 6 | #define TONE1 1600 7 | #define TONE2 1800 8 | #define TONE3 2000 9 | #define TONE4 2200 10 | #define TONE5 2400 11 | #define TONE6 2600 12 | 13 | class MotorIf 14 | { 15 | public: 16 | enum Type 17 | { 18 | BDCM, // brushed DC motor 19 | BLDC, // brushless DC motor 20 | PMSM, // Permanent magnet synchronous motor(in future) 21 | }; 22 | enum VolumeLevel 23 | { 24 | VOLUME_OFF, // OFF 25 | VOLUME_LOW, 26 | VOLUME_MID, 27 | VOLUME_HIGH, 28 | }; 29 | virtual int get_rpm() const = 0; // the sign of return value represents the dir, negative means backward 30 | virtual int get_erpm() const = 0; 31 | virtual int get_e_period() const = 0; 32 | virtual int get_current() const = 0; // return current consumption in mA, return -1 if function isn't supported 33 | #ifndef NDEBUG 34 | virtual int get_throttle() const = 0; // get the throttle set by user 35 | virtual int get_real_throttle() const = 0; // get the real throttle currently running at(for debug) 36 | #endif 37 | virtual void set_throttle(int v) = 0; // suport negative throttle as backward spin direction, or just treat negative throttle as 0 if not supported 38 | virtual void stop() = 0; 39 | virtual void beep(uint32_t freq, VolumeLevel volume) = 0; // setting freq to 0 means beep off 40 | virtual void arm(bool state) = 0; 41 | virtual bool is_armed() = 0; 42 | virtual void poll() = 0; 43 | static MotorIf *singleton(Type type); 44 | }; 45 | -------------------------------------------------------------------------------- /src/motor/src/bldc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "msp.h" 3 | 4 | class Bldc : public MotorIf 5 | { 6 | private: 7 | public: 8 | Bldc(); 9 | ~Bldc(); 10 | virtual int get_rpm() const; 11 | virtual int get_erpm() const; 12 | virtual int get_e_period() const; 13 | virtual int get_current() const; 14 | #ifndef NDEBUG 15 | virtual int get_throttle() const; 16 | virtual int get_real_throttle() const; 17 | #endif 18 | virtual void set_throttle(int v); 19 | virtual void stop(); 20 | virtual void beep(uint32_t freq, VolumeLevel volume); 21 | virtual void arm(bool state); 22 | virtual bool is_armed(); 23 | virtual void poll(); 24 | }; -------------------------------------------------------------------------------- /src/motor/src/motor.cpp: -------------------------------------------------------------------------------- 1 | #include "motor.h" 2 | #include "bldc.h" 3 | #include "assert.h" 4 | 5 | static Bldc* bldc; 6 | 7 | MotorIf *MotorIf::singleton(Type type) 8 | { 9 | switch (type) 10 | { 11 | case BLDC: 12 | if (bldc) 13 | return bldc; 14 | return bldc = new Bldc(); 15 | break; 16 | case PMSM: // not yet 17 | case BDCM: // not yet 18 | default: 19 | assert(false); 20 | break; 21 | } 22 | return nullptr; 23 | } -------------------------------------------------------------------------------- /src/msp/src/AT32F421/adc.cpp: -------------------------------------------------------------------------------- 1 | #include "adc.h" 2 | #include "gpio.h" 3 | #include "msp.h" 4 | #include 5 | 6 | static bool g_adc_inited = false; 7 | static uint32_t &adc_osq = *(uint32_t *)&ADC1->osq3; 8 | static uint32_t &adc_ctrl2 = *(uint32_t *)&ADC1->ctrl2; 9 | static volatile uint32_t &adc_sts = ADC1->sts; 10 | static uint32_t &adc_odt = *(uint32_t *)&ADC1->odt; 11 | 12 | static inline adc_channel_select_type pin2channel(Pin pin) 13 | { 14 | return (adc_channel_select_type)GPIO2IDX(pin); 15 | } 16 | 17 | void Adc::prepare(void) 18 | { 19 | } 20 | 21 | uint32_t Adc::sample_value(void) const 22 | { 23 | adc_osq = ch; // change channel to this adc object 24 | adc_ctrl2 |= 1 << 22; 25 | while (!(adc_sts & ADC_CCE_FLAG)) 26 | { 27 | } 28 | return adc_odt; 29 | } 30 | 31 | uint32_t Adc::sample_voltage(void) const 32 | { 33 | return sample_value() * 3280 / 4096; 34 | } 35 | 36 | uint32_t Adc::sample_temperature(void) const 37 | { 38 | return ((int)sample_voltage() - 1280) * 10 / 43 + 25; 39 | } 40 | 41 | AdcIf *AdcIf::new_instance(Pin pin) 42 | { 43 | assert(pin < PA8 || pin == PIN_MAX); // other pins are not supported yet 44 | 45 | adc_channel_select_type ch; 46 | if (pin == PIN_MAX) 47 | ch = ADC_CHANNEL_16; 48 | else 49 | { 50 | ch = pin2channel(pin); 51 | Gpio::setup_af(pin, Gpio::AF_ANALOG); 52 | } 53 | 54 | Adc *adc = new Adc(ch); 55 | if (g_adc_inited) 56 | return adc; 57 | 58 | g_adc_inited = true; 59 | adc_base_config_type adc_base_struct; 60 | crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE); 61 | crm_adc_clock_div_set(CRM_ADC_DIV_6); 62 | 63 | /* adc_settings----------------------------------------------------------- */ 64 | adc_base_default_para_init(&adc_base_struct); 65 | adc_base_struct.sequence_mode = FALSE; 66 | adc_base_struct.repeat_mode = FALSE; 67 | adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT; 68 | adc_base_struct.ordinary_channel_length = 1; 69 | adc_base_config(ADC1, &adc_base_struct); 70 | 71 | /* adc_ordinary_conversionmode-------------------------------------------- */ 72 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_1_5); 73 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_1, 1, ADC_SAMPLETIME_1_5); 74 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_2, 1, ADC_SAMPLETIME_1_5); 75 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_3, 1, ADC_SAMPLETIME_1_5); 76 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_4, 1, ADC_SAMPLETIME_1_5); 77 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_5, 1, ADC_SAMPLETIME_1_5); 78 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_6, 1, ADC_SAMPLETIME_1_5); 79 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_7, 1, ADC_SAMPLETIME_1_5); 80 | adc_ordinary_channel_set(ADC1, ADC_CHANNEL_16, 1, ADC_SAMPLETIME_1_5); 81 | 82 | adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE); 83 | 84 | adc_ordinary_part_mode_enable(ADC1, FALSE); 85 | 86 | adc_enable(ADC1, TRUE); 87 | 88 | /* adc calibration-------------------------------------------------------- */ 89 | adc_calibration_init(ADC1); 90 | while (adc_calibration_init_status_get(ADC1)) 91 | { 92 | } 93 | adc_calibration_start(ADC1); 94 | while (adc_calibration_status_get(ADC1)) 95 | { 96 | } 97 | 98 | /* add user code begin adc1_init 2 */ 99 | adc_flag_clear(ADC1, ADC_CCE_FLAG); 100 | /* add user code end adc1_init 2 */ 101 | return adc; 102 | } 103 | 104 | uint16_t calc_avg(uint16_t *data, uint32_t sz) 105 | { 106 | uint16_t max = 0; 107 | uint16_t min = 65535; 108 | uint16_t max_i = 0; 109 | uint16_t min_i = 0; 110 | for (uint32_t i = 0; i < sz; ++i) 111 | { 112 | if (max < data[i]) 113 | { 114 | max = data[i]; 115 | max_i = i; 116 | } 117 | if (min < data[i]) 118 | { 119 | min = data[i]; 120 | min_i = i; 121 | } 122 | } 123 | uint32_t avg = 0; 124 | for (uint32_t i = 0; i < sz; ++i) 125 | { 126 | if (i == min_i || i == max_i) 127 | continue; 128 | 129 | avg += data[i]; 130 | } 131 | avg /= sz - 2; 132 | return (uint16_t)avg; 133 | } 134 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/adc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "at32f421_adc.h" 4 | #include "msp.h" 5 | 6 | class Adc : public AdcIf 7 | { 8 | private: 9 | adc_channel_select_type ch; 10 | uint32_t sample_value(void) const; 11 | 12 | public: 13 | Adc(adc_channel_select_type ch) : ch(ch) {} 14 | virtual void prepare(); 15 | virtual uint32_t sample_voltage(void) const; 16 | virtual uint32_t sample_temperature(void) const; 17 | }; 18 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/cmp.cpp: -------------------------------------------------------------------------------- 1 | #include "CMP.h" 2 | #include "gpio.h" 3 | #include "assert.h" 4 | 5 | static bool cmp1_inited = false; 6 | 7 | ComparatorIf *ComparatorIf::new_instance(Pin pos_pin, Pin neg_pin, Pin out_pin) 8 | { 9 | assert(pos_pin == PA0 || pos_pin == PA1 || pos_pin == PA5); 10 | assert(neg_pin == PA0 || neg_pin == PA2 || neg_pin == PA4 || neg_pin == PA5); 11 | Gpio::setup_af(pos_pin, Gpio::AF_ANALOG); 12 | Gpio::setup_af(neg_pin, Gpio::AF_ANALOG); 13 | Comparator *cmp = new Comparator(pos_pin, neg_pin, out_pin); 14 | if (cmp1_inited) 15 | return cmp; 16 | cmp1_inited = true; 17 | cmp_init_type cmp_init_struct; 18 | crm_periph_clock_enable(CRM_CMP_PERIPH_CLOCK, TRUE); 19 | cmp_default_para_init(&cmp_init_struct); 20 | cmp_init_struct.cmp_non_inverting = CMP_NON_INVERTING_PA5; 21 | cmp_init_struct.cmp_inverting = CMP_INVERTING_PA2; 22 | cmp_init_struct.cmp_output = CMP_OUTPUT_NONE; 23 | cmp_init_struct.cmp_polarity = CMP_POL_NON_INVERTING; 24 | cmp_init_struct.cmp_speed = CMP_SPEED_FAST; 25 | cmp_init_struct.cmp_hysteresis = CMP_HYSTERESIS_NONE; 26 | cmp_init(CMP1_SELECTION, &cmp_init_struct); 27 | cmp_enable(CMP1_SELECTION, TRUE); 28 | cmp_scal_brg_config(CMP_SCAL_BRG_11); 29 | cmp_filter_config(0x3f, 0x3f, TRUE); 30 | return cmp; 31 | } 32 | 33 | Comparator::Comparator(Pin pos_pin, Pin neg_pin, Pin out_pin) 34 | { 35 | cmp_non_inverting_type non_invert_in = CMP_NON_INVERTING_PA5; 36 | cmp_inverting_type invert_in = CMP_INVERTING_PA4; 37 | switch (pos_pin) 38 | { 39 | case PA5: 40 | non_invert_in = CMP_NON_INVERTING_PA5; 41 | break; 42 | case PA1: 43 | non_invert_in = CMP_NON_INVERTING_PA1; 44 | break; 45 | case PA0: 46 | non_invert_in = CMP_NON_INVERTING_PA0; 47 | break; 48 | default: 49 | assert(false); 50 | break; 51 | } 52 | switch (neg_pin) 53 | { 54 | case PA4: 55 | invert_in = CMP_INVERTING_PA4; 56 | break; 57 | case PA5: 58 | invert_in = CMP_INVERTING_PA5; 59 | break; 60 | case PA0: 61 | invert_in = CMP_INVERTING_PA0; 62 | break; 63 | case PA2: 64 | invert_in = CMP_INVERTING_PA2; 65 | break; 66 | default: 67 | assert(false); 68 | break; 69 | } 70 | input_pins = (non_invert_in << 7) | (invert_in << 4); 71 | switch (out_pin) 72 | { 73 | case PA0: 74 | Gpio::setup_af(out_pin, Gpio::AF_OUTPUT_PP, GPIO_MUX_7); 75 | break; 76 | case PA6: 77 | Gpio::setup_af(out_pin, Gpio::AF_OUTPUT_PP, GPIO_MUX_7); 78 | break; 79 | case PIN_NONE: 80 | break; 81 | default: 82 | assert(false); 83 | break; 84 | } 85 | } 86 | 87 | volatile uint32_t &cmp_ctrl = CMP->ctrlsts; 88 | 89 | void Comparator::prepare() 90 | { 91 | cmp_ctrl &= ~(0b11111 << 4); 92 | cmp_ctrl |= input_pins; 93 | } 94 | 95 | uint8_t Comparator::cmp_result() const 96 | { 97 | return !!(cmp_ctrl & (1 << 30)); 98 | } 99 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/cmp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "at32f421_cmp.h" 3 | #include "msp.h" 4 | #include "gpio.h" 5 | 6 | #define CMP_PIN_A CMP_NON_INVERTING_PA5 7 | #define CMP_PIN_B CMP_NON_INVERTING_PA1 8 | #define CMP_PIN_C CMP_NON_INVERTING_PA0 9 | #define CMP_PIN_O CMP_INVERTING_PA2 10 | 11 | class Comparator : public ComparatorIf 12 | { 13 | private: 14 | int input_pins; 15 | 16 | public: 17 | Comparator(Pin pos_pin, Pin neg_pin, Pin out_pin); 18 | virtual void prepare(); 19 | virtual uint8_t cmp_result() const; 20 | }; -------------------------------------------------------------------------------- /src/msp/src/AT32F421/crc.cpp: -------------------------------------------------------------------------------- 1 | #include "crc.h" 2 | #include "at32f421_crc.h" 3 | 4 | static Crc crc; 5 | static bool crc_inited = false; 6 | 7 | void Crc::set_start(uint8_t val) 8 | { 9 | CRC->idt = val; 10 | CRC->ctrl_bit.rst = 1; 11 | } 12 | 13 | void Crc::set_poly(uint8_t poly) 14 | { 15 | CRC->poly = poly; 16 | } 17 | 18 | uint8_t Crc::calc(uint8_t *data, uint32_t sz) 19 | { 20 | CRC->ctrl_bit.rst = 1; 21 | for (uint32_t i = 0; i < sz; i++) 22 | { // careful, the AT's crc length is determined by the length you write, so there must be a (uint8_t *) cast to have crc8 23 | (*(uint8_t *)&CRC->dt) = data[i]; 24 | } 25 | 26 | return (CRC->dt); 27 | } 28 | 29 | uint32_t Crc::calc(uint8_t data) 30 | { 31 | // careful, the AT's crc length is determined by the length you write, so there must be a (uint8_t *) cast to have crc8 32 | (*(uint8_t *)&CRC->dt) = data; 33 | return (CRC->dt); 34 | } 35 | 36 | CrcIf *CrcIf::singleton() 37 | { 38 | if (crc_inited) 39 | return &crc; 40 | crc_inited = true; 41 | crm_periph_clock_enable(CRM_CRC_PERIPH_CLOCK, TRUE); 42 | crc_init_data_set(0x00000000); 43 | crc_poly_size_set(CRC_POLY_SIZE_8B); 44 | crc_poly_value_set(0xB7); 45 | crc_reverse_input_data_set(CRC_REVERSE_INPUT_NO_AFFECTE); 46 | crc_reverse_output_data_set(CRC_REVERSE_OUTPUT_NO_AFFECTE); 47 | crc_data_reset(); 48 | return &crc; 49 | } 50 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/crc.h: -------------------------------------------------------------------------------- 1 | #include "msp.h" 2 | 3 | class Crc : public CrcIf 4 | { 5 | private: 6 | uint8_t poly; 7 | uint8_t start; 8 | 9 | public: 10 | virtual void set_start(uint8_t val); 11 | virtual void set_poly(uint8_t poly); 12 | virtual uint8_t calc(uint8_t *data, uint32_t sz); 13 | virtual uint32_t calc(uint8_t data); 14 | static CrcIf *singleton(); // do not try to delete the returned object 15 | }; -------------------------------------------------------------------------------- /src/msp/src/AT32F421/flash.cpp: -------------------------------------------------------------------------------- 1 | #include "flash.h" 2 | #include "at32f421_conf.h" 3 | #include 4 | 5 | #ifndef FLASH_BASE 6 | #define FLASH_BASE 0x08000000U 7 | #endif 8 | #define FLASH_SIZE 0x10000U // 64kB 9 | #define FLASH_END (FLASH_BASE + FLASH_SIZE) 10 | #define PAGE_SIZE 0x400U 11 | 12 | #define EEPROM_SIZE (PAGE_SIZE) 13 | #define EEPROM_ADDR (FLASH_END - EEPROM_SIZE) 14 | 15 | static int flash_storage_erase(uint32_t address) 16 | { 17 | /* wait for last operation */ 18 | while (flash_flag_get(FLASH_OBF_FLAG)) 19 | { 20 | } 21 | 22 | /* clear all pending flags */ 23 | flash_flag_clear(FLASH_ODF_FLAG | FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG); 24 | 25 | /* erase the flash pages */ 26 | for (; address < FLASH_END; address += PAGE_SIZE) 27 | { 28 | if (flash_sector_erase(address) != FLASH_OPERATE_DONE) 29 | { 30 | break; 31 | } 32 | } 33 | 34 | return (address >= FLASH_END) ? 0 : -1; 35 | } 36 | 37 | static int flash_storage_write(uint32_t const *data, uint32_t size) 38 | { 39 | uint32_t address = EEPROM_ADDR; 40 | 41 | if (!data || !size || EEPROM_SIZE < size) 42 | return -1; 43 | 44 | /* 45 | Returns false results when changing only currPowerdB. 46 | Commenting out for now to force writing. 47 | */ 48 | 49 | /* unlock the flash program/erase controller */ 50 | flash_unlock(); 51 | 52 | if (flash_storage_erase(address) < 0) 53 | { 54 | // Erase failed 55 | flash_lock(); 56 | return -1; 57 | } 58 | 59 | /* program flash */ 60 | while (size-- && address < FLASH_END) 61 | { 62 | if (flash_word_program(address, *data++) != FLASH_OPERATE_DONE) 63 | { 64 | break; 65 | } 66 | address += 4U; 67 | } 68 | 69 | /* lock the main FMC after the program operation */ 70 | flash_lock(); 71 | 72 | if (size) 73 | return -1; 74 | 75 | return 0; 76 | } 77 | 78 | void Flash::write(uint8_t *data, uint32_t sz) 79 | { 80 | flash_storage_write((uint32_t *)data, ((sz + 3) / 4)); 81 | } 82 | 83 | void Flash::read(uint8_t *data, uint32_t sz) 84 | { 85 | memcpy(data, (uint8_t *)EEPROM_ADDR, sz); 86 | } 87 | 88 | static Flash flash; 89 | 90 | FlashIf *FlashIf::singleton() 91 | { 92 | return &flash; 93 | } -------------------------------------------------------------------------------- /src/msp/src/AT32F421/flash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "msp.h" 4 | 5 | class Flash : public FlashIf 6 | { 7 | virtual void write(uint8_t *data, uint32_t sz); 8 | virtual void read(uint8_t *data, uint32_t sz); 9 | }; 10 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/gpio.cpp: -------------------------------------------------------------------------------- 1 | #include "at32f421_conf.h" 2 | #include "gpio.h" 3 | #include 4 | 5 | GpioIf *GpioIf::new_instance(Pin pin) 6 | { 7 | gpio_init_type gpio_init_struct; 8 | 9 | uint32_t pin_bit = GPIO2BIT(pin); 10 | gpio_type *regs = (gpio_type *)(GPIOA_BASE + 0x400 * GPIO2PORT(pin)); 11 | Gpio::clock_enable(regs); 12 | gpio_default_para_init(&gpio_init_struct); 13 | gpio_init_struct.gpio_pins = pin_bit; 14 | 15 | gpio_init(regs, &gpio_init_struct); 16 | Gpio *gpio = new Gpio(regs, pin); 17 | return gpio; 18 | } 19 | 20 | void Gpio::clock_enable(gpio_type *regs) 21 | { 22 | switch ((uint32_t)regs) 23 | { 24 | case GPIOA_BASE: 25 | crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); 26 | break; 27 | case GPIOB_BASE: 28 | crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); 29 | break; 30 | case GPIOC_BASE: 31 | crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); 32 | break; 33 | case GPIOF_BASE: 34 | crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE); 35 | break; 36 | 37 | default: 38 | assert(false); 39 | break; 40 | } 41 | } 42 | 43 | void Gpio::setup_af(Pin pin, AfMode mode, gpio_mux_sel_type function) 44 | { 45 | uint32_t pin_idx = GPIO2IDX(pin); 46 | gpio_type *regs = (gpio_type *)(GPIOA_BASE + 0x400 * GPIO2PORT(pin)); 47 | gpio_mode_type gpio_mode = GPIO_MODE_MUX; 48 | gpio_output_type gpio_out_type = GPIO_OUTPUT_PUSH_PULL; 49 | gpio_pull_type gpio_pull = GPIO_PULL_UP; 50 | gpio_drive_type gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; 51 | Gpio::clock_enable(regs); 52 | switch (mode) 53 | { 54 | case AF_ANALOG: 55 | gpio_mode = GPIO_MODE_ANALOG; 56 | break; 57 | case AF_INPUT_FT: 58 | gpio_pull = GPIO_PULL_NONE; 59 | case AF_INPUT_PU: 60 | gpio_pull = GPIO_PULL_UP; 61 | break; 62 | case AF_INPUT_PD: 63 | gpio_pull = GPIO_PULL_DOWN; 64 | break; 65 | case AF_OUTPUT_PP: 66 | gpio_out_type = GPIO_OUTPUT_PUSH_PULL; 67 | break; 68 | case AF_OUTPUT_OD: 69 | gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN; 70 | break; 71 | default: 72 | assert(false); 73 | break; 74 | } 75 | 76 | regs->cfgr &= (uint32_t) ~(0x03 << (pin_idx * 2)); 77 | regs->cfgr |= (uint32_t)(gpio_mode << (pin_idx * 2)); 78 | regs->omode &= (uint32_t) ~(0x01 << (pin_idx)); 79 | regs->omode |= (uint32_t)(gpio_out_type << (pin_idx)); 80 | regs->odrvr &= (uint32_t) ~(0x03 << (pin_idx * 2)); 81 | regs->odrvr |= (uint32_t)(gpio_drive_strength << (pin_idx * 2)); 82 | regs->pull &= (uint32_t) ~(0x03 << (pin_idx * 2)); 83 | regs->pull |= (uint32_t)(gpio_pull << (pin_idx * 2)); 84 | 85 | gpio_pin_mux_config(regs, (gpio_pins_source_type)pin_idx, function); 86 | } 87 | 88 | void Gpio::write(uint8_t bit) 89 | { 90 | if (bit) 91 | set(); 92 | else 93 | unset(); 94 | } 95 | 96 | uint8_t Gpio::read() 97 | { 98 | return (!!(regs->idt & pin_bit)); 99 | } 100 | 101 | void Gpio::set() 102 | { 103 | regs->scr = pin_bit; 104 | } 105 | 106 | void Gpio::unset() 107 | { 108 | regs->clr = pin_bit; 109 | } 110 | 111 | void Gpio::toggle() 112 | { 113 | if (read()) 114 | unset(); 115 | else 116 | set(); 117 | } 118 | 119 | int Gpio::set_mode(IoMode mode) 120 | { 121 | gpio_mode_type gpio_mode = GPIO_MODE_INPUT; 122 | gpio_output_type gpio_out_type = GPIO_OUTPUT_PUSH_PULL; 123 | gpio_pull_type gpio_pull = GPIO_PULL_NONE; 124 | switch (mode) 125 | { 126 | case INPUT_FLOAT: 127 | gpio_pull = GPIO_PULL_NONE; 128 | break; 129 | case INPUT_PULLUP: 130 | gpio_pull = GPIO_PULL_UP; 131 | break; 132 | case INPUT_PULLDOWN: 133 | gpio_pull = GPIO_PULL_DOWN; 134 | break; 135 | case OUTPUT: 136 | gpio_mode = GPIO_MODE_OUTPUT; 137 | gpio_out_type = GPIO_OUTPUT_PUSH_PULL; 138 | break; 139 | case INPUT_OUTPUT: 140 | gpio_mode = GPIO_MODE_OUTPUT; 141 | gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN; 142 | break; 143 | default: 144 | return false; 145 | } 146 | 147 | regs->cfgr &= (uint32_t) ~(0x03 << (pin_idx * 2)); 148 | regs->cfgr |= (uint32_t)(gpio_mode << (pin_idx * 2)); 149 | regs->omode &= (uint32_t) ~(0x01 << (pin_idx)); 150 | regs->omode |= (uint32_t)(gpio_out_type << (pin_idx)); 151 | regs->pull &= (uint32_t) ~(0x03 << (pin_idx * 2)); 152 | regs->pull |= (uint32_t)(gpio_pull << (pin_idx * 2)); 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/gpio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "msp.h" 5 | #include "at32f421_gpio.h" 6 | 7 | class Gpio : public GpioIf 8 | { 9 | private: 10 | gpio_type * regs; 11 | uint16_t pin_idx; 12 | uint16_t pin_bit; 13 | 14 | public: 15 | enum AfMode 16 | { 17 | AF_ANALOG, 18 | AF_INPUT_FT, 19 | AF_INPUT_PU, 20 | AF_INPUT_PD, 21 | AF_OUTPUT_PP, 22 | AF_OUTPUT_OD 23 | }; 24 | static void clock_enable(gpio_type* regs); 25 | virtual void write(uint8_t bit); 26 | virtual uint8_t read(); 27 | virtual void set(); 28 | virtual void unset(); 29 | virtual void toggle(); 30 | virtual int set_mode(IoMode mode); 31 | Gpio(gpio_type * regs, Pin pin) : regs(regs), pin_idx(GPIO2IDX(pin)), pin_bit(GPIO2BIT(pin)) 32 | { 33 | } 34 | ~Gpio(){} 35 | static void setup_af(Pin pin, AfMode mode, gpio_mux_sel_type function = GPIO_MUX_0); 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/motor-gpio.cpp: -------------------------------------------------------------------------------- 1 | #include "at32f421_conf.h" 2 | #include "gpio.h" 3 | #include "motor-gpio.h" 4 | #include 5 | 6 | MotorIoIf *MotorIoIf::new_instance(Pin a, Pin b, Pin c) 7 | { 8 | MotorIo *gpio = new MotorIo(a, b, c); 9 | return gpio; 10 | } 11 | 12 | MotorIo::MotorIo(Pin a, Pin b, Pin c) 13 | { 14 | gpio_init_type gpio_init_struct; 15 | gpio_default_para_init(&gpio_init_struct); 16 | gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT; 17 | gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; 18 | 19 | pin_a_bit = GPIO2BIT(a); 20 | pin_b_bit = GPIO2BIT(b); 21 | pin_c_bit = GPIO2BIT(c); 22 | 23 | gpio_type *regsa = (gpio_type *)(GPIOA_BASE + 0x400 * GPIO2PORT(a)); 24 | gpio_type *regsb = (gpio_type *)(GPIOA_BASE + 0x400 * GPIO2PORT(b)); 25 | gpio_type *regsc = (gpio_type *)(GPIOA_BASE + 0x400 * GPIO2PORT(c)); 26 | Gpio::clock_enable(regsa); 27 | Gpio::clock_enable(regsb); 28 | Gpio::clock_enable(regsc); 29 | 30 | gpio_init_struct.gpio_pins = pin_a_bit; 31 | gpio_init(regsa, &gpio_init_struct); 32 | gpio_init_struct.gpio_pins = pin_b_bit; 33 | gpio_init(regsb, &gpio_init_struct); 34 | gpio_init_struct.gpio_pins = pin_c_bit; 35 | gpio_init(regsc, &gpio_init_struct); 36 | 37 | set_a = ®sa->scr; 38 | set_b = ®sb->scr; 39 | set_c = ®sc->scr; 40 | 41 | clr_a = ®sa->clr; 42 | clr_b = ®sb->clr; 43 | clr_c = ®sc->clr; 44 | 45 | pin_a = a; 46 | pin_b = b; 47 | pin_c = c; 48 | } 49 | 50 | void MotorIo::select(Pin pin) 51 | { 52 | if (pin == pin_a) 53 | { 54 | *set_a = pin_a_bit; 55 | *clr_b = pin_b_bit; 56 | *clr_c = pin_c_bit; 57 | }else if (pin == pin_b) 58 | { 59 | *clr_a = pin_a_bit; 60 | *set_b = pin_b_bit; 61 | *clr_c = pin_c_bit; 62 | }else if (pin == pin_c) 63 | { 64 | *clr_a = pin_a_bit; 65 | *clr_b = pin_b_bit; 66 | *set_c = pin_c_bit; 67 | } 68 | else if (pin == PIN_MAX) 69 | { 70 | *set_a = pin_a_bit; 71 | *set_b = pin_b_bit; 72 | *set_c = pin_c_bit; 73 | } 74 | else 75 | { 76 | *clr_a = pin_a_bit; 77 | *clr_b = pin_b_bit; 78 | *clr_c = pin_c_bit; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/motor-gpio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "msp.h" 5 | #include "at32f421_gpio.h" 6 | 7 | class MotorIo : public MotorIoIf 8 | { 9 | private: 10 | uint16_t pin_a; 11 | uint16_t pin_b; 12 | uint16_t pin_c; 13 | 14 | uint16_t pin_a_bit; 15 | uint16_t pin_b_bit; 16 | uint16_t pin_c_bit; 17 | 18 | volatile uint32_t* set_a; 19 | volatile uint32_t* set_b; 20 | volatile uint32_t* set_c; 21 | volatile uint32_t* clr_a; 22 | volatile uint32_t* clr_b; 23 | volatile uint32_t* clr_c; 24 | 25 | public: 26 | virtual void select(Pin pin); 27 | MotorIo(Pin a, Pin b, Pin c); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/motor-pwm.cpp: -------------------------------------------------------------------------------- 1 | #include "motor-pwm.h" 2 | #include "gpio.h" 3 | #include "assert.h" 4 | 5 | #define ARRAY_CNT(x) (sizeof(x) / sizeof(x[0])) 6 | #define BUF_SIZE 64 7 | #define SYS_CLOCK_FREQ 120000000 8 | 9 | #define DEFAULT_PWM_PERIOD 65536 10 | 11 | struct PwmMap 12 | { 13 | tmr_type *periph; 14 | uint16_t pin; 15 | tmr_channel_select_type ch; 16 | gpio_mux_sel_type af; 17 | }; 18 | 19 | static PwmMap pwm_maps[] = { 20 | // each pin must be different from each other. 21 | {TMR1, PA8, TMR_SELECT_CHANNEL_1, GPIO_MUX_2}, 22 | {TMR1, PA9, TMR_SELECT_CHANNEL_2, GPIO_MUX_2}, 23 | {TMR1, PA10, TMR_SELECT_CHANNEL_3, GPIO_MUX_2}, 24 | 25 | {TMR3, PB4, TMR_SELECT_CHANNEL_1, GPIO_MUX_0}, 26 | {TMR3, PB5, TMR_SELECT_CHANNEL_2, GPIO_MUX_0}, 27 | {TMR3, PB0, TMR_SELECT_CHANNEL_3, GPIO_MUX_1}, 28 | {TMR3, PB1, TMR_SELECT_CHANNEL_4, GPIO_MUX_1}, 29 | {TMR3, PA6, TMR_SELECT_CHANNEL_1, GPIO_MUX_1}, 30 | {TMR3, PA7, TMR_SELECT_CHANNEL_2, GPIO_MUX_1}, 31 | 32 | {TMR15, PA2, TMR_SELECT_CHANNEL_1, GPIO_MUX_0}, 33 | {TMR15, PA3, TMR_SELECT_CHANNEL_2, GPIO_MUX_0}, 34 | }; 35 | 36 | MotorPwmIf *MotorPwmIf::new_instance(Pin a, Pin b, Pin c) 37 | { 38 | MotorPwm *new_pwm = new MotorPwm(a, b, c); 39 | return new_pwm; 40 | } 41 | 42 | MotorPwm::MotorPwm(Pin a, Pin b, Pin c) 43 | { 44 | uint32_t index[3] = {0}; 45 | Pin pins[3] = {a, b, c}; 46 | for (uint32_t i = 0; i < 3; i++) 47 | { 48 | uint32_t &j = index[i]; 49 | for (j = 0; j < ARRAY_CNT(pwm_maps); j++) 50 | { 51 | if (pins[i] == pwm_maps[j].pin) 52 | break; 53 | } 54 | assert(j < ARRAY_CNT(pwm_maps)); 55 | } 56 | 57 | assert(pwm_maps[index[0]].periph == pwm_maps[index[1]].periph && pwm_maps[index[1]].periph == pwm_maps[index[2]].periph); // all motor pwm pins should share the same timer for running speed 58 | 59 | Gpio::setup_af(a, Gpio::AF_OUTPUT_PP, pwm_maps[index[0]].af); 60 | Gpio::setup_af(b, Gpio::AF_OUTPUT_PP, pwm_maps[index[1]].af); 61 | Gpio::setup_af(c, Gpio::AF_OUTPUT_PP, pwm_maps[index[2]].af); 62 | 63 | tmr_channel_select_type ch1, ch2, ch3; 64 | ch1 = pwm_maps[index[0]].ch; 65 | ch2 = pwm_maps[index[1]].ch; 66 | ch3 = pwm_maps[index[2]].ch; 67 | 68 | pina = a; 69 | pinb = b; 70 | pinc = c; 71 | 72 | freq = 0; 73 | tim_config(pwm_maps[index[0]].periph, ch1, ch2, ch3); 74 | 75 | set_freq(1000); 76 | set_dutycycle(0); 77 | } 78 | 79 | MotorPwm::~MotorPwm() 80 | { 81 | // release tim 82 | *tim_div = 0; 83 | } 84 | 85 | inline void MotorPwm::tim_config(tmr_type *tim, tmr_channel_select_type ch1, tmr_channel_select_type ch2, tmr_channel_select_type ch3) 86 | { 87 | uint32_t ch_idx1 = ch1 >> 1; 88 | uint32_t ch_idx2 = ch2 >> 1; 89 | uint32_t ch_idx3 = ch3 >> 1; 90 | // map the timer registers 91 | tim_cdt1 = &(&tim->c1dt)[ch_idx1]; 92 | tim_cdt2 = &(&tim->c1dt)[ch_idx2]; 93 | tim_cdt3 = &(&tim->c1dt)[ch_idx3]; 94 | tim_pr = &tim->pr; 95 | tim_div = &tim->div; 96 | tim_cval = &tim->cval; 97 | 98 | tim_cm1 = &tim->cm1; 99 | tim_cm2 = &tim->cm2; 100 | 101 | switch ((uint32_t)tim) 102 | { 103 | case TMR1_BASE: 104 | crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE); 105 | break; 106 | case TMR3_BASE: 107 | crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE); 108 | break; 109 | case TMR15_BASE: 110 | crm_periph_clock_enable(CRM_TMR15_PERIPH_CLOCK, TRUE); 111 | break; 112 | default: 113 | assert(false); 114 | break; 115 | } 116 | 117 | tmr_base_init(tim, DEFAULT_PWM_PERIOD - 1, 0); 118 | tmr_cnt_dir_set(tim, TMR_COUNT_UP); 119 | tmr_clock_source_div_set(tim, TMR_CLOCK_DIV1); 120 | tmr_period_buffer_enable(tim, FALSE); 121 | 122 | tmr_sub_sync_mode_set(tim, FALSE); 123 | tmr_primary_mode_select(tim, TMR_PRIMARY_SEL_RESET); 124 | tmr_overflow_request_source_set(tim, FALSE); 125 | 126 | tmr_output_config_type tmr_output_struct; 127 | tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_FORCE_LOW; 128 | tmr_output_struct.oc_output_state = TRUE; 129 | tmr_output_struct.occ_output_state = FALSE; 130 | tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH; 131 | tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH; 132 | tmr_output_struct.oc_idle_state = FALSE; 133 | tmr_output_struct.occ_idle_state = FALSE; 134 | tmr_output_channel_config(tim, ch1, &tmr_output_struct); 135 | tmr_output_channel_config(tim, ch2, &tmr_output_struct); 136 | tmr_output_channel_config(tim, ch3, &tmr_output_struct); 137 | 138 | if (ch_idx1 < 2) 139 | { 140 | ch1_cm1 = *tim_cm1 | TMR_OUTPUT_CONTROL_PWM_MODE_A << (4 + 8 * ch_idx1); 141 | ch1_cm2 = *tim_cm2; 142 | } 143 | else 144 | { 145 | ch1_cm1 = *tim_cm1; 146 | ch1_cm2 = *tim_cm2 | TMR_OUTPUT_CONTROL_PWM_MODE_A << (4 + 8 * (ch_idx1 - 2)); 147 | } 148 | 149 | if (ch_idx2 < 2) 150 | { 151 | ch2_cm1 = *tim_cm1 | TMR_OUTPUT_CONTROL_PWM_MODE_A << (4 + 8 * ch_idx2); 152 | ch2_cm2 = *tim_cm2; 153 | } 154 | else 155 | { 156 | ch2_cm1 = *tim_cm1; 157 | ch2_cm2 = *tim_cm2 | TMR_OUTPUT_CONTROL_PWM_MODE_A << (4 + 8 * (ch_idx2 - 2)); 158 | } 159 | 160 | if (ch_idx3 < 2) 161 | { 162 | ch3_cm1 = *tim_cm1 | TMR_OUTPUT_CONTROL_PWM_MODE_A << (4 + 8 * ch_idx3); 163 | ch3_cm2 = *tim_cm2; 164 | } 165 | else 166 | { 167 | ch3_cm1 = *tim_cm1; 168 | ch3_cm2 = *tim_cm2 | TMR_OUTPUT_CONTROL_PWM_MODE_A << (4 + 8 * (ch_idx3 - 2)); 169 | } 170 | 171 | tmr_output_enable(tim, TRUE); 172 | tmr_counter_enable(tim, TRUE); 173 | nvic_irq_enable(TMR3_GLOBAL_IRQn, 0, 0); 174 | } 175 | 176 | // dutycycle 0.0000 ~ 1.0 177 | void MotorPwm::set_dutycycle(uint32_t dutycycle) 178 | { 179 | if (__builtin_expect(this->dutycycle == dutycycle, false)) 180 | return; 181 | this->dutycycle = dutycycle; 182 | uint32_t cdt = dutycycle * cycle / 2000; 183 | *tim_cdt1 = cdt; 184 | *tim_cdt2 = cdt; 185 | *tim_cdt3 = cdt; 186 | } 187 | 188 | void MotorPwm::set_freq(uint32_t freq) 189 | { 190 | if (__builtin_expect(this->freq == freq, false)) // the current min and max freq are 1000 and 12MHz, value outside that is illegal 191 | return; 192 | this->freq = freq; 193 | uint32_t div = 1; 194 | cycle = SYS_CLOCK_FREQ / freq; 195 | while (__builtin_expect(cycle > DEFAULT_PWM_PERIOD - 1, false)) 196 | { // at most loop 3 times while freq = 1 197 | div <<= 4; // *16 198 | cycle >>= 4; // /16 199 | } 200 | *tim_div = div - 1; // attention: the div value will only take effect in the next cycle, so there is some delay according to the cycle length 201 | *tim_pr = cycle - 1; 202 | uint32_t cdt = dutycycle * cycle / 2000; 203 | *tim_cdt1 = cdt; 204 | *tim_cdt2 = cdt; 205 | *tim_cdt3 = cdt; 206 | } 207 | 208 | uint32_t MotorPwm::get_duty() const 209 | { 210 | return *tim_cdt; 211 | } 212 | 213 | uint32_t MotorPwm::get_cycle() const 214 | { 215 | return cycle; 216 | } 217 | 218 | uint32_t MotorPwm::get_pos() const 219 | { 220 | return *tim_cval; 221 | } 222 | 223 | void MotorPwm::select(Pin pin) 224 | { 225 | if (pin == pina) 226 | { 227 | *tim_cm1 = ch1_cm1; 228 | *tim_cm2 = ch1_cm2; 229 | tim_cdt = tim_cdt1; 230 | } 231 | else if (pin == pinb) 232 | { 233 | *tim_cm1 = ch2_cm1; 234 | *tim_cm2 = ch2_cm2; 235 | tim_cdt = tim_cdt2; 236 | } 237 | else if (pin == pinc) 238 | { 239 | *tim_cm1 = ch3_cm1; 240 | *tim_cm2 = ch3_cm2; 241 | tim_cdt = tim_cdt3; 242 | }else 243 | { 244 | *tim_cm1 = 0; 245 | *tim_cm2 = 0; 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/motor-pwm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "msp.h" 5 | #include "at32f421_tmr.h" 6 | 7 | class MotorPwm : public MotorPwmIf 8 | { 9 | private: 10 | uint32_t dutycycle; // 0-2000 map to 0.0-1.0 11 | uint32_t freq; 12 | uint16_t duty; 13 | uint32_t cycle; 14 | 15 | Pin pina, pinb, pinc; 16 | 17 | uint32_t ch1_cm1; 18 | uint32_t ch1_cm2; 19 | uint32_t ch2_cm1; 20 | uint32_t ch2_cm2; 21 | uint32_t ch3_cm1; 22 | uint32_t ch3_cm2; 23 | 24 | volatile uint32_t *tim_cdt1; 25 | volatile uint32_t *tim_cdt2; 26 | volatile uint32_t *tim_cdt3; 27 | volatile uint32_t *tim_cdt; 28 | volatile uint32_t *tim_pr; 29 | volatile uint32_t *tim_div; 30 | volatile uint32_t *tim_cm1; 31 | volatile uint32_t *tim_cm2; 32 | volatile uint32_t *tim_cval; 33 | 34 | inline void tim_config(tmr_type *tim, tmr_channel_select_type ch1, tmr_channel_select_type ch2, tmr_channel_select_type ch3); 35 | 36 | public: 37 | MotorPwm(Pin a, Pin b, Pin c); 38 | ~MotorPwm(); 39 | virtual void set_dutycycle(uint32_t dutycycle); 40 | virtual void set_freq(uint32_t freq); 41 | virtual void select(Pin pin); 42 | virtual uint32_t get_duty() const; // return the pwm duty length 43 | virtual uint32_t get_cycle() const; // return the pwm cycle length 44 | virtual uint32_t get_pos() const; // return the current pwm output position in the cycle 45 | }; 46 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/msp.cpp: -------------------------------------------------------------------------------- 1 | #include "at32f421_misc.h" 2 | 3 | void core_clock_config(void) 4 | { 5 | /* reset crm */ 6 | crm_reset(); 7 | 8 | /* config flash psr register */ 9 | flash_psr_set(FLASH_WAIT_CYCLE_3); 10 | 11 | /* enable lick */ 12 | crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE); 13 | 14 | /* wait till lick is ready */ 15 | while (crm_flag_get(CRM_LICK_STABLE_FLAG) != SET) 16 | { 17 | } 18 | 19 | /* enable hick */ 20 | crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE); 21 | 22 | /* wait till hick is ready */ 23 | while (crm_flag_get(CRM_HICK_STABLE_FLAG) != SET) 24 | { 25 | } 26 | 27 | /* config pll clock resource */ 28 | crm_pll_config(CRM_PLL_SOURCE_HICK, CRM_PLL_MULT_30); 29 | 30 | /* enable pll */ 31 | crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); 32 | 33 | /* wait till pll is ready */ 34 | while (crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) 35 | { 36 | } 37 | 38 | /* config ahbclk */ 39 | crm_ahb_div_set(CRM_AHB_DIV_1); 40 | 41 | /* config apb2clk */ 42 | crm_apb2_div_set(CRM_APB2_DIV_1); 43 | 44 | /* config apb1clk */ 45 | crm_apb1_div_set(CRM_APB1_DIV_2); 46 | 47 | /* enable auto step mode */ 48 | crm_auto_step_mode_enable(TRUE); 49 | 50 | /* select pll as system clock source */ 51 | crm_sysclk_switch(CRM_SCLK_PLL); 52 | 53 | /* wait till pll is used as system clock source */ 54 | while (crm_sysclk_switch_status_get() != CRM_SCLK_PLL) 55 | { 56 | } 57 | 58 | /* disable auto step mode */ 59 | crm_auto_step_mode_enable(FALSE); 60 | 61 | /* update system_core_clock global variable */ 62 | system_core_clock_update(); 63 | } 64 | 65 | void system_init(void) 66 | { 67 | core_clock_config(); 68 | nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); 69 | } -------------------------------------------------------------------------------- /src/msp/src/AT32F421/signal-pwm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "msp.h" 5 | #include "at32f421_tmr.h" 6 | 7 | extern "C" void TMR3_GLOBAL_IRQHandler(void); 8 | extern "C" void TMR1_GLOBAL_IRQHandler(void); 9 | extern "C" void TMR15_GLOBAL_IRQHandler(void); 10 | 11 | class SignalPwm : public SignalPwmIf 12 | { 13 | private: 14 | enum 15 | { 16 | INPUT = 0, // to recieve pwm input 17 | OUTPUT = 1, // to output pwm, polarity is low(idle high) 18 | }io_dir; 19 | 20 | uint16_t buf[64]; 21 | 22 | uint32_t dma_m2p; 23 | uint32_t dma_p2m; 24 | volatile uint32_t *dma_ctrl; 25 | volatile uint32_t *dma_paddr; 26 | volatile uint32_t *dma_maddr; 27 | volatile uint32_t *dma_dtcnt; 28 | 29 | uint32_t pwm_enable; 30 | uint32_t pwm_disable; 31 | uint32_t pwm_input; 32 | uint32_t pwm_output; 33 | uint32_t io_dir_mask; 34 | uint32_t cctrl_mask; 35 | uint32_t coctrl_mask; 36 | uint32_t enable_dma_request; 37 | uint32_t cctrl_out_high_value; 38 | uint32_t cctrl_out_low_value; 39 | uint32_t cctrl_out_value; 40 | uint32_t cctrl_in_value; 41 | uint32_t it_enable; 42 | uint32_t cctrl_in_high_value; 43 | uint32_t cctrl_in_low_value; 44 | uint32_t cctrl_in_both_value; 45 | volatile uint32_t *tim_cdt; 46 | volatile uint32_t *tim_cctrl; 47 | volatile uint32_t *tim_cm; 48 | volatile uint32_t *tim_pr; 49 | volatile uint32_t *tim_div; 50 | volatile uint32_t *tim_iden; 51 | 52 | Callback callback; 53 | 54 | void switch2output(); 55 | void switch2input(); 56 | inline void tim_config(tmr_type *tim, tmr_channel_select_type ch); 57 | inline void restart_dma(uint16_t* buf, uint32_t sz); 58 | inline void dma_config(dma_channel_type *dma); 59 | inline void dma_release(); 60 | 61 | friend void TMR3_GLOBAL_IRQHandler(void); 62 | friend void TMR1_GLOBAL_IRQHandler(void); 63 | friend void TMR15_GLOBAL_IRQHandler(void); 64 | 65 | public: 66 | SignalPwm(Pin pin); 67 | ~SignalPwm(); 68 | virtual void set_mode(Mode mode); 69 | virtual int send_pulses(const uint16_t *pulses, uint32_t sz, uint32_t period); // async 70 | virtual int recv_pulses(uint16_t *pulses, uint32_t sz); 71 | virtual void set_up_pulse_callback(Callback cb); 72 | }; 73 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_cmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_cmp.c 4 | * @brief contains all the functions for the gpio firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup CMP 32 | * @brief CMP driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef CMP_MODULE_ENABLED 37 | 38 | /** @defgroup CMP_private_functions 39 | * @{ 40 | */ 41 | 42 | #define CMP_CTRLSTS1_CLEAR_MASK ((uint32_t)0x00039C7C) 43 | #define CMP_INPINPUT_CLEAR_MASK ((uint32_t)0x00000180) 44 | #define CMP_HIGH_PULSE_CLEAR_MASK ((uint16_t)0x003F) 45 | #define CMP_LOW_PULSE_CLEAR_MASK ((uint16_t)0x003F) 46 | 47 | /** 48 | * @brief reset the cmp register 49 | * @param none 50 | * @retval none 51 | */ 52 | void cmp_reset(void) 53 | { 54 | crm_periph_reset(CRM_CMP_PERIPH_RESET, TRUE); 55 | crm_periph_reset(CRM_CMP_PERIPH_RESET, FALSE); 56 | } 57 | 58 | /** 59 | * @brief initialize the cmp peripheral 60 | * @param cmp_sel: to select the cmp peripheral 61 | * this parameter only can be CMP1_SELECTION 62 | * @param cmp_init_struct: pointer to cmp init structure 63 | * @retval none 64 | */ 65 | void cmp_init(cmp_sel_type cmp_sel, cmp_init_type* cmp_init_struct) 66 | { 67 | if(cmp_sel == CMP1_SELECTION) 68 | { 69 | CMP->ctrlsts_bit.cmpninvsel = cmp_init_struct->cmp_non_inverting; 70 | CMP->ctrlsts_bit.cmpinvsel = cmp_init_struct->cmp_inverting; 71 | CMP->ctrlsts_bit.cmpssel = cmp_init_struct->cmp_speed; 72 | CMP->ctrlsts_bit.cmptag = cmp_init_struct->cmp_output; 73 | CMP->ctrlsts_bit.cmpp = cmp_init_struct->cmp_polarity; 74 | CMP->ctrlsts_bit.cmphyst = cmp_init_struct->cmp_hysteresis; 75 | } 76 | } 77 | 78 | /** 79 | * @brief fill each cmp_init_type member with its default value. 80 | * @param cmp_init_type : pointer to a cmp_init_type structure 81 | * which will be initialized. 82 | * @retval none 83 | */ 84 | void cmp_default_para_init(cmp_init_type *cmp_init_struct) 85 | { 86 | /* reset cmp init structure parameters values */ 87 | cmp_init_struct->cmp_non_inverting = CMP_NON_INVERTING_PA1; 88 | cmp_init_struct->cmp_inverting = CMP_INVERTING_1_4VREFINT; 89 | cmp_init_struct->cmp_speed = CMP_SPEED_FAST; 90 | cmp_init_struct->cmp_output = CMP_OUTPUT_NONE; 91 | cmp_init_struct->cmp_polarity = CMP_POL_NON_INVERTING; 92 | cmp_init_struct->cmp_hysteresis = CMP_HYSTERESIS_NONE; 93 | } 94 | 95 | /** 96 | * @brief enable or disable cmp 97 | * @param cmp_sel: to select the cmp peripheral 98 | * this parameter only can be CMP1_SELECTION. 99 | * @param new_state (TRUE or FALSE) 100 | * @retval none 101 | */ 102 | void cmp_enable(cmp_sel_type cmp_sel, confirm_state new_state) 103 | { 104 | /* cmp enable */ 105 | if(cmp_sel == CMP1_SELECTION) 106 | { 107 | CMP->ctrlsts_bit.cmpen = new_state; 108 | } 109 | } 110 | 111 | /** 112 | * @brief enable or disable cmp input shift 113 | * @param new_state (TRUE or FALSE) 114 | * @retval none 115 | */ 116 | void cmp_input_shift_enable(confirm_state new_state) 117 | { 118 | CMP->ctrlsts_bit.cmpis = new_state; 119 | } 120 | 121 | /** 122 | * @brief get cmp output value 123 | * @param cmp_sel: to select the cmp peripheral 124 | * this parameter only can be CMP1_SELECTION. 125 | * @retval cmp output value 126 | */ 127 | uint32_t cmp_output_value_get(cmp_sel_type cmp_sel) 128 | { 129 | uint32_t cmpout = 0x0; 130 | if(cmp_sel == CMP1_SELECTION) 131 | { 132 | cmpout = CMP->ctrlsts_bit.cmpvalue; 133 | } 134 | 135 | /* return the comparator output level */ 136 | return (uint32_t)(cmpout); 137 | } 138 | 139 | /** 140 | * @brief enable cmp write protect 141 | * @param cmp_sel: to select the cmp peripheral 142 | * this parameter only can be CMP1_SELECTION. 143 | * @retval none 144 | */ 145 | void cmp_write_protect_enable(cmp_sel_type cmp_sel) 146 | { 147 | if(cmp_sel == CMP1_SELECTION) 148 | { 149 | CMP->ctrlsts_bit.cmpwp = TRUE; 150 | } 151 | } 152 | 153 | /** 154 | * @brief configure cmp glitch filter 155 | * @param high_pulse_cnt: cmp high pulse count. 156 | * this parameter must be a value between 0x00 and 0x3f 157 | * @param low_pulse_cnt: cmp low pulse count. 158 | * this parameter must be a value between 0x00 and 0x3f 159 | * @param new_state (TRUE or FALSE) 160 | * @retval none 161 | */ 162 | void cmp_filter_config(uint16_t high_pulse_cnt, uint16_t low_pulse_cnt, confirm_state new_state) 163 | { 164 | if (new_state != FALSE) 165 | { 166 | /* enable the glitch filter */ 167 | CMP->g_filter_en_bit.gfe = TRUE; 168 | 169 | /* write to cmp high_pulse and low_pulse */ 170 | CMP->low_pulse_bit.l_pulse_cnt = low_pulse_cnt; 171 | CMP->high_pulse_bit.h_pulse_cnt = high_pulse_cnt; 172 | } 173 | else 174 | { 175 | /* disable the glitch filter */ 176 | CMP->g_filter_en_bit.gfe = FALSE; 177 | 178 | /* reset the h_pulse_cnt and l_pulse_cnt bits */ 179 | CMP->low_pulse_bit.l_pulse_cnt = low_pulse_cnt; 180 | CMP->high_pulse_bit.h_pulse_cnt = high_pulse_cnt; 181 | } 182 | } 183 | 184 | /** 185 | * @brief configure cmp blanking source. 186 | * @param blank_sel: cmp blanking source 187 | * this parameter can be one of the following values: 188 | * - CMP_BLANKING_NONE 189 | * - CMP_BLANKING_TMR1_CH4 190 | * - CMP_BLANKING_TMR3_CH3 191 | * - CMP_BLANKING_TMR15_CH2 192 | * - CMP_BLANKING_TMR15_CH1 193 | * @retval none 194 | */ 195 | void cmp_blanking_config(cmp_blanking_type blank_sel) 196 | { 197 | CMP->ctrlsts_bit.cmpblanking = blank_sel; 198 | } 199 | 200 | /** 201 | * @brief configure cmp scale voltage and voltage bridge 202 | * @param scal_brg: cmp scal&brg configure 203 | * this parameter can be one of the following values: 204 | * - CMP_SCAL_BRG_00: vrefint = 3/4 vrefint = 1/2 vrefint = 1/4 vrefint = 0v 205 | * - CMP_SCAL_BRG_10: vrefint = 3/4 vrefint = 1/2 vrefint = 1/4 vrefint = 1.2v 206 | * - CMP_SCAL_BRG_11: vrefint = 1.2v, 3/4 vrefint = 0.9v, 1/2 vrefint = 0.6v, 1/4 vrefint = 0.3v 207 | * @retval none 208 | */ 209 | void cmp_scal_brg_config(cmp_scal_brg_type scal_brg) 210 | { 211 | uint32_t tmp_scal = 0, tmp_brg = 0; 212 | tmp_scal = scal_brg >> 1; 213 | tmp_brg = scal_brg & 0x01; 214 | 215 | CMP->ctrlsts_bit.scalen = tmp_scal; 216 | CMP->ctrlsts_bit.brgen = tmp_brg; 217 | } 218 | 219 | /** 220 | * @} 221 | */ 222 | 223 | #endif 224 | 225 | /** 226 | * @} 227 | */ 228 | 229 | /** 230 | * @} 231 | */ 232 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_conf.h: -------------------------------------------------------------------------------- 1 | /* add user code begin Header */ 2 | /** 3 | ************************************************************************** 4 | * @file at32f421_conf.h 5 | * @brief at32f421 config header file 6 | ************************************************************************** 7 | * Copyright notice & Disclaimer 8 | * 9 | * The software Board Support Package (BSP) that is made available to 10 | * download from Artery official website is the copyrighted work of Artery. 11 | * Artery authorizes customers to use, copy, and distribute the BSP 12 | * software and its related documentation for the purpose of design and 13 | * development in conjunction with Artery microcontrollers. Use of the 14 | * software is governed by this copyright notice and the following disclaimer. 15 | * 16 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 17 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 18 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 19 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 20 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 22 | * 23 | ************************************************************************** 24 | */ 25 | /* add user code end Header */ 26 | 27 | /* define to prevent recursive inclusion -------------------------------------*/ 28 | #ifndef __AT32F421_CONF_H 29 | #define __AT32F421_CONF_H 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /** 36 | * @brief in the following line adjust the value of high speed exernal crystal (hext) 37 | * used in your application 38 | * 39 | * tip: to avoid modifying this file each time you need to use different hext, you 40 | * can define the hext value in your toolchain compiler preprocessor. 41 | * 42 | */ 43 | #if !defined HEXT_VALUE 44 | #define HEXT_VALUE ((uint32_t)8000000) /*!< value of the high speed exernal crystal in hz */ 45 | #endif 46 | 47 | /** 48 | * @brief in the following line adjust the high speed exernal crystal (hext) startup 49 | * timeout value 50 | */ 51 | #define HEXT_STARTUP_TIMEOUT ((uint16_t)0x3000) /*!< time out for hext start up */ 52 | #define HICK_VALUE ((uint32_t)8000000) /*!< value of the high speed internal clock in hz */ 53 | #define LEXT_VALUE ((uint32_t)32768) /*!< value of the low speed exernal clock in hz */ 54 | 55 | /* module define -------------------------------------------------------------*/ 56 | #define CRM_MODULE_ENABLED 57 | #define CMP_MODULE_ENABLED 58 | #define TMR_MODULE_ENABLED 59 | /*#define ERTC_MODULE_ENABLED---------------------*/ 60 | #define GPIO_MODULE_ENABLED 61 | /*#define I2C_MODULE_ENABLED----------------------*/ 62 | #define USART_MODULE_ENABLED 63 | #define PWC_MODULE_ENABLED 64 | #define ADC_MODULE_ENABLED 65 | /*#define SPI_MODULE_ENABLED----------------------*/ 66 | #define DMA_MODULE_ENABLED 67 | #define DEBUG_MODULE_ENABLED 68 | #define FLASH_MODULE_ENABLED 69 | #define CRC_MODULE_ENABLED 70 | /*#define WWDT_MODULE_ENABLED---------------------*/ 71 | #define WDT_MODULE_ENABLED 72 | /*#define EXINT_MODULE_ENABLED--------------------*/ 73 | #define MISC_MODULE_ENABLED 74 | #define SCFG_MODULE_ENABLED 75 | 76 | /* includes ------------------------------------------------------------------*/ 77 | #ifdef CRM_MODULE_ENABLED 78 | #include "at32f421_crm.h" 79 | #endif 80 | #ifdef CMP_MODULE_ENABLED 81 | #include "at32f421_cmp.h" 82 | #endif 83 | #ifdef TMR_MODULE_ENABLED 84 | #include "at32f421_tmr.h" 85 | #endif 86 | #ifdef ERTC_MODULE_ENABLED 87 | #include "at32f421_ertc.h" 88 | #endif 89 | #ifdef GPIO_MODULE_ENABLED 90 | #include "at32f421_gpio.h" 91 | #endif 92 | #ifdef I2C_MODULE_ENABLED 93 | #include "at32f421_i2c.h" 94 | #endif 95 | #ifdef USART_MODULE_ENABLED 96 | #include "at32f421_usart.h" 97 | #endif 98 | #ifdef PWC_MODULE_ENABLED 99 | #include "at32f421_pwc.h" 100 | #endif 101 | #ifdef ADC_MODULE_ENABLED 102 | #include "at32f421_adc.h" 103 | #endif 104 | #ifdef SPI_MODULE_ENABLED 105 | #include "at32f421_spi.h" 106 | #endif 107 | #ifdef DMA_MODULE_ENABLED 108 | #include "at32f421_dma.h" 109 | #endif 110 | #ifdef DEBUG_MODULE_ENABLED 111 | #include "at32f421_debug.h" 112 | #endif 113 | #ifdef FLASH_MODULE_ENABLED 114 | #include "at32f421_flash.h" 115 | #endif 116 | #ifdef CRC_MODULE_ENABLED 117 | #include "at32f421_crc.h" 118 | #endif 119 | #ifdef WWDT_MODULE_ENABLED 120 | #include "at32f421_wwdt.h" 121 | #endif 122 | #ifdef WDT_MODULE_ENABLED 123 | #include "at32f421_wdt.h" 124 | #endif 125 | #ifdef EXINT_MODULE_ENABLED 126 | #include "at32f421_exint.h" 127 | #endif 128 | #ifdef MISC_MODULE_ENABLED 129 | #include "at32f421_misc.h" 130 | #endif 131 | #ifdef SCFG_MODULE_ENABLED 132 | #include "at32f421_scfg.h" 133 | #endif 134 | 135 | #ifdef __cplusplus 136 | } 137 | #endif 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_crc.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_crc.c 4 | * @brief contains all the functions for the crc firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup CRC 32 | * @brief CRC driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef CRC_MODULE_ENABLED 37 | 38 | /** @defgroup CRC_private_functions 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @brief reset the crc data register. 44 | * @param none 45 | * @retval none 46 | */ 47 | void crc_data_reset(void) 48 | { 49 | /* reset crc generator */ 50 | CRC->ctrl_bit.rst = 0x1; 51 | } 52 | 53 | /** 54 | * @brief compute the 32-bit crc of a given data word(32-bit). 55 | * @param data: data word(32-bit) to compute its crc 56 | * @retval 32-bit crc 57 | */ 58 | uint32_t crc_one_word_calculate(uint32_t data) 59 | { 60 | CRC->dt = data; 61 | return (CRC->dt); 62 | } 63 | 64 | /** 65 | * @brief compute the 32-bit crc of a given buffer of data word(32-bit). 66 | * @param pbuffer: pointer to the buffer containing the data to be computed 67 | * @param length: length of the buffer to be computed 68 | * @retval 32-bit crc 69 | */ 70 | uint32_t crc_block_calculate(uint32_t *pbuffer, uint32_t length) 71 | { 72 | uint32_t index = 0; 73 | 74 | for(index = 0; index < length; index++) 75 | { 76 | CRC->dt = pbuffer[index]; 77 | } 78 | 79 | return (CRC->dt); 80 | } 81 | 82 | /** 83 | * @brief return the current crc value. 84 | * @param none 85 | * @retval 32-bit crc 86 | */ 87 | uint32_t crc_data_get(void) 88 | { 89 | return (CRC->dt); 90 | } 91 | 92 | /** 93 | * @brief store a 8-bit data in the common data register. 94 | * @param cdt_value: 8-bit value to be stored in the common data register 95 | * @retval none 96 | */ 97 | void crc_common_data_set(uint8_t cdt_value) 98 | { 99 | CRC->cdt_bit.cdt = cdt_value; 100 | } 101 | 102 | /** 103 | * @brief return the 8-bit data stored in the common data register 104 | * @param none 105 | * @retval 8-bit value of the common data register 106 | */ 107 | uint8_t crc_common_data_get(void) 108 | { 109 | return (CRC->cdt_bit.cdt); 110 | } 111 | 112 | /** 113 | * @brief set the 32-bit initial data of crc 114 | * @param value: initial data 115 | * @retval none 116 | */ 117 | void crc_init_data_set(uint32_t value) 118 | { 119 | CRC->idt = value; 120 | } 121 | 122 | /** 123 | * @brief control the reversal of the bit order in the input data 124 | * @param value 125 | * this parameter can be one of the following values: 126 | * - CRC_REVERSE_INPUT_NO_AFFECTE 127 | * - CRC_REVERSE_INPUT_BY_BYTE 128 | * - CRC_REVERSE_INPUT_BY_HALFWORD 129 | * - CRC_REVERSE_INPUT_BY_WORD 130 | * @retval none. 131 | */ 132 | void crc_reverse_input_data_set(crc_reverse_input_type value) 133 | { 134 | CRC->ctrl_bit.revid = value; 135 | } 136 | 137 | /** 138 | * @brief control the reversal of the bit order in the output data 139 | * @param value 140 | * this parameter can be one of the following values: 141 | * - CRC_REVERSE_OUTPUT_NO_AFFECTE 142 | * - CRC_REVERSE_OUTPUT_DATA 143 | * @retval none. 144 | */ 145 | void crc_reverse_output_data_set(crc_reverse_output_type value) 146 | { 147 | CRC->ctrl_bit.revod = value; 148 | } 149 | 150 | /** 151 | * @brief config crc polynomial value 152 | * @param value 153 | * 32-bit new data of crc poly value 154 | * @retval none. 155 | */ 156 | void crc_poly_value_set(uint32_t value) 157 | { 158 | CRC->poly = value; 159 | } 160 | 161 | /** 162 | * @brief return crc polynomial value 163 | * @param none 164 | * @retval 32-bit value of the polynomial value. 165 | */ 166 | uint32_t crc_poly_value_get(void) 167 | { 168 | return (CRC->poly); 169 | } 170 | 171 | /** 172 | * @brief config crc polynomial data size 173 | * @param size 174 | * this parameter can be one of the following values: 175 | * - CRC_POLY_SIZE_32B 176 | * - CRC_POLY_SIZE_16B 177 | * - CRC_POLY_SIZE_8B 178 | * - CRC_POLY_SIZE_7B 179 | * @retval none. 180 | */ 181 | void crc_poly_size_set(crc_poly_size_type size) 182 | { 183 | CRC->ctrl_bit.poly_size = size; 184 | } 185 | 186 | /** 187 | * @brief return crc polynomial data size 188 | * @param none 189 | * @retval polynomial data size. 190 | */ 191 | crc_poly_size_type crc_poly_size_get(void) 192 | { 193 | return (crc_poly_size_type)(CRC->ctrl_bit.poly_size); 194 | } 195 | 196 | /** 197 | * @} 198 | */ 199 | 200 | #endif 201 | 202 | /** 203 | * @} 204 | */ 205 | 206 | /** 207 | * @} 208 | */ 209 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_crc.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_crc.h 4 | * @brief at32f421 crc header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_CRC_H 27 | #define __AT32F421_CRC_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | /* includes ------------------------------------------------------------------*/ 35 | #include "at32f421.h" 36 | 37 | /** @addtogroup AT32F421_periph_driver 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup CRC 42 | * @{ 43 | */ 44 | 45 | /** @defgroup CRC_exported_types 46 | * @{ 47 | */ 48 | 49 | /** 50 | * @brief crc reverse input data 51 | */ 52 | typedef enum 53 | { 54 | CRC_REVERSE_INPUT_NO_AFFECTE = 0x00, /*!< input data no reverse */ 55 | CRC_REVERSE_INPUT_BY_BYTE = 0x01, /*!< input data reverse by byte */ 56 | CRC_REVERSE_INPUT_BY_HALFWORD = 0x02, /*!< input data reverse by half word */ 57 | CRC_REVERSE_INPUT_BY_WORD = 0x03 /*!< input data reverse by word */ 58 | } crc_reverse_input_type; 59 | 60 | /** 61 | * @brief crc reverse output data 62 | */ 63 | typedef enum 64 | { 65 | CRC_REVERSE_OUTPUT_NO_AFFECTE = 0x00, /*!< output data no reverse */ 66 | CRC_REVERSE_OUTPUT_DATA = 0x01 /*!< output data reverse by word */ 67 | } crc_reverse_output_type; 68 | 69 | /** 70 | * @brief crc polynomial size 71 | */ 72 | typedef enum 73 | { 74 | CRC_POLY_SIZE_32B = 0x00, /*!< polynomial size 32 bits */ 75 | CRC_POLY_SIZE_16B = 0x01, /*!< polynomial size 16 bits */ 76 | CRC_POLY_SIZE_8B = 0x02, /*!< polynomial size 8 bits */ 77 | CRC_POLY_SIZE_7B = 0x03 /*!< polynomial size 7 bits */ 78 | } crc_poly_size_type; 79 | 80 | /** 81 | * @brief type define crc register all 82 | */ 83 | typedef struct 84 | { 85 | /** 86 | * @brief crc dt register, offset:0x00 87 | */ 88 | union 89 | { 90 | __IO uint32_t dt; 91 | struct 92 | { 93 | __IO uint32_t dt : 32; /* [31:0] */ 94 | } dt_bit; 95 | }; 96 | 97 | /** 98 | * @brief crc cdt register, offset:0x04 99 | */ 100 | union 101 | { 102 | __IO uint32_t cdt; 103 | struct 104 | { 105 | __IO uint32_t cdt : 8 ; /* [7:0] */ 106 | __IO uint32_t reserved1 : 24 ;/* [31:8] */ 107 | } cdt_bit; 108 | }; 109 | 110 | /** 111 | * @brief crc ctrl register, offset:0x08 112 | */ 113 | union 114 | { 115 | __IO uint32_t ctrl; 116 | struct 117 | { 118 | __IO uint32_t rst : 1 ; /* [0] */ 119 | __IO uint32_t reserved1 : 2 ; /* [2:1] */ 120 | __IO uint32_t poly_size : 2 ; /* [4:3] */ 121 | __IO uint32_t revid : 2 ; /* [6:5] */ 122 | __IO uint32_t revod : 1 ; /* [7] */ 123 | __IO uint32_t reserved2 : 24 ;/* [31:8] */ 124 | } ctrl_bit; 125 | }; 126 | 127 | /** 128 | * @brief crm reserved1 register, offset:0x0C 129 | */ 130 | __IO uint32_t reserved1; 131 | 132 | /** 133 | * @brief crc idt register, offset:0x10 134 | */ 135 | union 136 | { 137 | __IO uint32_t idt; 138 | struct 139 | { 140 | __IO uint32_t idt : 32; /* [31:0] */ 141 | } idt_bit; 142 | }; 143 | 144 | /** 145 | * @brief crc polynomial register, offset:0x14 146 | */ 147 | union 148 | { 149 | __IO uint32_t poly; 150 | struct 151 | { 152 | __IO uint32_t poly : 32; /* [31:0] */ 153 | } poly_bit; 154 | }; 155 | 156 | } crc_type; 157 | 158 | /** 159 | * @} 160 | */ 161 | 162 | #define CRC ((crc_type *) CRC_BASE) 163 | 164 | /** @defgroup CRC_exported_functions 165 | * @{ 166 | */ 167 | 168 | void crc_data_reset(void); 169 | uint32_t crc_one_word_calculate(uint32_t data); 170 | uint32_t crc_block_calculate(uint32_t *pbuffer, uint32_t length); 171 | uint32_t crc_data_get(void); 172 | void crc_common_data_set(uint8_t cdt_value); 173 | uint8_t crc_common_data_get(void); 174 | void crc_init_data_set(uint32_t value); 175 | void crc_reverse_input_data_set(crc_reverse_input_type value); 176 | void crc_reverse_output_data_set(crc_reverse_output_type value); 177 | void crc_poly_value_set(uint32_t value); 178 | uint32_t crc_poly_value_get(void); 179 | void crc_poly_size_set(crc_poly_size_type size); 180 | crc_poly_size_type crc_poly_size_get(void); 181 | 182 | /** 183 | * @} 184 | */ 185 | 186 | /** 187 | * @} 188 | */ 189 | 190 | /** 191 | * @} 192 | */ 193 | 194 | #ifdef __cplusplus 195 | } 196 | #endif 197 | 198 | #endif 199 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_debug.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_debug.c 4 | * @brief contains all the functions for the debug firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup DEBUG 32 | * @brief DEBUG driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef DEBUG_MODULE_ENABLED 37 | 38 | /** @defgroup DEBUG_private_functions 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @brief get debug device id 44 | * @param none 45 | * @retval the debug device id 46 | */ 47 | uint16_t debug_device_id_get(void) 48 | { 49 | return (uint16_t)DEBUGMCU->pid; 50 | } 51 | /** 52 | * @brief set periph debug mode 53 | * @param periph_debug_mode 54 | * this parameter can be any combination of the following values: 55 | * - DEBUG_SLEEP 56 | * - DEBUG_DEEPSLEEP 57 | * - DEBUG_STANDBY 58 | * - DEBUG_WDT_PAUSE 59 | * - DEBUG_WWDT_PAUSE 60 | * - DEBUG_TMR1_PAUSE 61 | * - DEBUG_TMR3_PAUSE 62 | * - DEBUG_ERTC_PAUSE 63 | * - DEBUG_I2C1_SMBUS_TIMEOUT 64 | * - DEBUG_I2C2_SMBUS_TIMEOUT 65 | * - DEBUG_TMR6_PAUSE 66 | * - DEBUG_ERTC_512_PAUSE 67 | * - DEBUG_TMR15_PAUSE 68 | * - DEBUG_TMR16_PAUSE 69 | * - DEBUG_TMR17_PAUSE 70 | * - DEBUG_TMR14_PAUSE 71 | * @param new_state (TRUE or FALSE) 72 | * @retval none 73 | */ 74 | void debug_periph_mode_set(uint32_t periph_debug_mode, confirm_state new_state) 75 | { 76 | if(new_state != FALSE) 77 | { 78 | DEBUGMCU->ctrl |= periph_debug_mode; 79 | } 80 | else 81 | { 82 | DEBUGMCU->ctrl &= ~periph_debug_mode; 83 | } 84 | } 85 | 86 | /** 87 | * @} 88 | */ 89 | 90 | #endif 91 | 92 | /** 93 | * @} 94 | */ 95 | 96 | /** 97 | * @} 98 | */ 99 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_debug.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_debug.h 4 | * @brief at32f421 debug header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* Define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_DEBUG_H 27 | #define __AT32F421_DEBUG_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | /* Includes ------------------------------------------------------------------*/ 35 | #include "at32f421.h" 36 | 37 | /** @addtogroup AT32F421_periph_driver 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup DEBUG 42 | * @{ 43 | */ 44 | 45 | /** @defgroup DEBUG_mode_definition 46 | * @{ 47 | */ 48 | 49 | #define DEBUG_SLEEP 0x00000001 /*!< debug sleep mode */ 50 | #define DEBUG_DEEPSLEEP 0x00000002 /*!< debug deepsleep mode */ 51 | #define DEBUG_STANDBY 0x00000004 /*!< debug standby mode */ 52 | #define DEBUG_WDT_PAUSE 0x00000100 /*!< debug watchdog timer pause */ 53 | #define DEBUG_WWDT_PAUSE 0x00000200 /*!< debug window watchdog timer pause */ 54 | #define DEBUG_TMR1_PAUSE 0x00000400 /*!< debug timer1 pause */ 55 | #define DEBUG_TMR3_PAUSE 0x00001000 /*!< debug timer3 pause */ 56 | #define DEBUG_ERTC_PAUSE 0x00004000 /*!< debug ertc pause */ 57 | #define DEBUG_I2C1_SMBUS_TIMEOUT 0x00008000 /*!< debug i2c1 smbus timeout */ 58 | #define DEBUG_I2C2_SMBUS_TIMEOUT 0x00010000 /*!< debug i2c2 smbus timeout */ 59 | #define DEBUG_TMR6_PAUSE 0x00080000 /*!< debug timer6 pause */ 60 | #define DEBUG_ERTC_512_PAUSE 0x00200000 /*!< debug ertc 512 pause */ 61 | #define DEBUG_TMR15_PAUSE 0x00400000 /*!< debug timer15 pause */ 62 | #define DEBUG_TMR16_PAUSE 0x00800000 /*!< debug timer16 pause */ 63 | #define DEBUG_TMR17_PAUSE 0x01000000 /*!< debug timer17 pause */ 64 | #define DEBUG_TMR14_PAUSE 0x08000000 /*!< debug timer14 pause */ 65 | 66 | /** 67 | * @} 68 | */ 69 | 70 | /** @defgroup DEBUG_exported_types 71 | * @{ 72 | */ 73 | 74 | /** 75 | * @brief type define debug register all 76 | */ 77 | typedef struct 78 | { 79 | /** 80 | * @brief debug idcode register, offset:0x00 81 | */ 82 | union 83 | { 84 | __IO uint32_t pid; 85 | struct 86 | { 87 | __IO uint32_t pid : 32;/* [31:0] */ 88 | } idcode_bit; 89 | }; 90 | 91 | /** 92 | * @brief debug ctrl register, offset:0x04 93 | */ 94 | union 95 | { 96 | __IO uint32_t ctrl; 97 | struct 98 | { 99 | __IO uint32_t sleep_debug : 1;/* [0] */ 100 | __IO uint32_t deepsleep_debug : 1;/* [1] */ 101 | __IO uint32_t standby_debug : 1;/* [2] */ 102 | __IO uint32_t reserved1 : 5;/* [7:3] */ 103 | __IO uint32_t wdt_pause : 1;/* [8] */ 104 | __IO uint32_t wwdt_pause : 1;/* [9] */ 105 | __IO uint32_t tmr1_pause : 1;/* [10] */ 106 | __IO uint32_t reserved2 : 1;/* [11] */ 107 | __IO uint32_t tmr3_pause : 1;/* [12] */ 108 | __IO uint32_t reserved3 : 1;/* [13] */ 109 | __IO uint32_t ertc_pause : 1;/* [14] */ 110 | __IO uint32_t i2c1_smbus_timeout : 1;/* [15] */ 111 | __IO uint32_t i2c2_smbus_timeout : 1;/* [16] */ 112 | __IO uint32_t reserved4 : 2;/* [18:17] */ 113 | __IO uint32_t tmr6_pause : 1;/* [19] */ 114 | __IO uint32_t reserved5 : 1;/* [20] */ 115 | __IO uint32_t ertc_512_pause : 1;/* [21] */ 116 | __IO uint32_t tmr15_pause : 1;/* [22] */ 117 | __IO uint32_t tmr16_pause : 1;/* [23] */ 118 | __IO uint32_t tmr17_pause : 1;/* [24] */ 119 | __IO uint32_t reserved6 : 2;/* [26:25] */ 120 | __IO uint32_t tmr14_pause : 1;/* [27] */ 121 | __IO uint32_t reserved7 : 4;/* [31:28] */ 122 | } ctrl_bit; 123 | }; 124 | 125 | } debug_type; 126 | 127 | /** 128 | * @} 129 | */ 130 | 131 | #define DEBUGMCU ((debug_type *) DEBUG_BASE) 132 | 133 | /** @defgroup DEBUG_exported_functions 134 | * @{ 135 | */ 136 | 137 | uint16_t debug_device_id_get(void); 138 | void debug_periph_mode_set(uint32_t periph_debug_mode, confirm_state new_state); 139 | 140 | /** 141 | * @} 142 | */ 143 | 144 | /** 145 | * @} 146 | */ 147 | 148 | /** 149 | * @} 150 | */ 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_def.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_def.h 4 | * @brief at32f421 macros header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* Define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_DEF_H 27 | #define __AT32F421_DEF_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /* gnu compiler */ 34 | #if defined (__GNUC__) 35 | #ifndef ALIGNED_HEAD 36 | #define ALIGNED_HEAD 37 | #endif 38 | #ifndef ALIGNED_TAIL 39 | #define ALIGNED_TAIL __attribute__ ((aligned (4))) 40 | #endif 41 | #endif 42 | 43 | /* arm compiler */ 44 | #if defined (__CC_ARM) 45 | #ifndef ALIGNED_HEAD 46 | #define ALIGNED_HEAD __align(4) 47 | #endif 48 | #ifndef ALIGNED_TAIL 49 | #define ALIGNED_TAIL 50 | #endif 51 | #endif 52 | 53 | /* iar compiler */ 54 | #if defined (__ICCARM__) 55 | #ifndef ALIGNED_HEAD 56 | #define ALIGNED_HEAD 57 | #endif 58 | #ifndef ALIGNED_TAIL 59 | #define ALIGNED_TAIL 60 | #endif 61 | #endif 62 | 63 | #define UNUSED(x) (void)x /* to avoid gcc/g++ warnings */ 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_exint.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_exint.c 4 | * @brief contains all the functions for the exint firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup EXINT 32 | * @brief EXINT driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef EXINT_MODULE_ENABLED 37 | 38 | /** @defgroup EXINT_private_functions 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @brief exint reset 44 | * @param none 45 | * @retval none 46 | */ 47 | void exint_reset(void) 48 | { 49 | EXINT->inten = 0x00000000; 50 | EXINT->polcfg1 = 0x00000000; 51 | EXINT->polcfg2 = 0x00000000; 52 | EXINT->evten = 0x00000000; 53 | EXINT->intsts = 0x003FFFFF; 54 | } 55 | 56 | /** 57 | * @brief exint default para init 58 | * @param exint_struct 59 | * - to the structure of exint_init_type 60 | * @retval none 61 | */ 62 | void exint_default_para_init(exint_init_type *exint_struct) 63 | { 64 | exint_struct->line_enable = FALSE; 65 | exint_struct->line_select = EXINT_LINE_NONE; 66 | exint_struct->line_polarity = EXINT_TRIGGER_FALLING_EDGE; 67 | exint_struct->line_mode = EXINT_LINE_EVENT; 68 | } 69 | 70 | /** 71 | * @brief exint init 72 | * @param exint_struct 73 | * - to the structure of exint_init_type 74 | * @retval none 75 | */ 76 | void exint_init(exint_init_type *exint_struct) 77 | { 78 | uint32_t line_index = 0; 79 | line_index = exint_struct->line_select; 80 | 81 | EXINT->inten &= ~line_index; 82 | EXINT->evten &= ~line_index; 83 | 84 | if(exint_struct->line_enable != FALSE) 85 | { 86 | if(exint_struct->line_mode == EXINT_LINE_INTERRUPUT) 87 | { 88 | EXINT->inten |= line_index; 89 | } 90 | else 91 | { 92 | EXINT->evten |= line_index; 93 | } 94 | 95 | EXINT->polcfg1 &= ~line_index; 96 | EXINT->polcfg2 &= ~line_index; 97 | if(exint_struct->line_polarity == EXINT_TRIGGER_RISING_EDGE) 98 | { 99 | EXINT->polcfg1 |= line_index; 100 | } 101 | else if(exint_struct->line_polarity == EXINT_TRIGGER_FALLING_EDGE) 102 | { 103 | EXINT->polcfg2 |= line_index; 104 | } 105 | else 106 | { 107 | EXINT->polcfg1 |= line_index; 108 | EXINT->polcfg2 |= line_index; 109 | } 110 | } 111 | } 112 | 113 | /** 114 | * @brief clear exint flag 115 | * @param exint_line 116 | * this parameter can be any combination of the following values: 117 | * - EXINT_LINE_0 118 | * - EXINT_LINE_1 119 | * ... 120 | * - EXINT_LINE_21 121 | * @retval none 122 | */ 123 | void exint_flag_clear(uint32_t exint_line) 124 | { 125 | EXINT->intsts = exint_line; 126 | } 127 | 128 | /** 129 | * @brief get exint flag 130 | * @param exint_line 131 | * this parameter can be one of the following values: 132 | * - EXINT_LINE_0 133 | * - EXINT_LINE_1 134 | * ... 135 | * - EXINT_LINE_21 136 | * @retval state of exint flag 137 | */ 138 | flag_status exint_flag_get(uint32_t exint_line) 139 | { 140 | flag_status status = RESET; 141 | uint32_t exint_flag =0; 142 | exint_flag = EXINT->intsts & exint_line; 143 | if((exint_flag != (uint16_t)RESET)) 144 | { 145 | status = SET; 146 | } 147 | else 148 | { 149 | status = RESET; 150 | } 151 | return status; 152 | } 153 | 154 | /** 155 | * @brief generate exint software interrupt event 156 | * @param exint_line 157 | * this parameter can be one of the following values: 158 | * - EXINT_LINE_0 159 | * - EXINT_LINE_1 160 | * ... 161 | * - EXINT_LINE_21 162 | * @retval none 163 | */ 164 | void exint_software_interrupt_event_generate(uint32_t exint_line) 165 | { 166 | EXINT->swtrg |= exint_line; 167 | } 168 | 169 | /** 170 | * @brief enable or disable exint interrupt 171 | * @param exint_line 172 | * this parameter can be any combination of the following values: 173 | * - EXINT_LINE_0 174 | * - EXINT_LINE_1 175 | * ... 176 | * - EXINT_LINE_21 177 | * @param new_state (TRUE or FALSE) 178 | * @retval none 179 | */ 180 | void exint_interrupt_enable(uint32_t exint_line, confirm_state new_state) 181 | { 182 | if(new_state == TRUE) 183 | { 184 | EXINT->inten |= exint_line; 185 | } 186 | else 187 | { 188 | EXINT->inten &= ~exint_line; 189 | } 190 | } 191 | 192 | /** 193 | * @brief enable or disable exint event 194 | * this parameter can be any combination of the following values: 195 | * - EXINT_LINE_0 196 | * - EXINT_LINE_1 197 | * ... 198 | * - EXINT_LINE_21 199 | * @param new_state (TRUE or FALSE) 200 | * @retval none 201 | */ 202 | void exint_event_enable(uint32_t exint_line, confirm_state new_state) 203 | { 204 | if(new_state == TRUE) 205 | { 206 | EXINT->evten |= exint_line; 207 | } 208 | else 209 | { 210 | EXINT->evten &= ~exint_line; 211 | } 212 | } 213 | 214 | /** 215 | * @} 216 | */ 217 | 218 | #endif 219 | 220 | /** 221 | * @} 222 | */ 223 | 224 | /** 225 | * @} 226 | */ 227 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_exint.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_exint.h 4 | * @brief at32f421 exint header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* Define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_EXINT_H 27 | #define __AT32F421_EXINT_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | /* Includes ------------------------------------------------------------------*/ 35 | #include "at32f421.h" 36 | 37 | /** @addtogroup AT32F421_periph_driver 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup EXINT 42 | * @{ 43 | */ 44 | 45 | /** @defgroup EXINT_lines 46 | * @{ 47 | */ 48 | 49 | #define EXINT_LINE_NONE ((uint32_t)0x000000) 50 | #define EXINT_LINE_0 ((uint32_t)0x000001) /*!< external interrupt line 0 */ 51 | #define EXINT_LINE_1 ((uint32_t)0x000002) /*!< external interrupt line 1 */ 52 | #define EXINT_LINE_2 ((uint32_t)0x000004) /*!< external interrupt line 2 */ 53 | #define EXINT_LINE_3 ((uint32_t)0x000008) /*!< external interrupt line 3 */ 54 | #define EXINT_LINE_4 ((uint32_t)0x000010) /*!< external interrupt line 4 */ 55 | #define EXINT_LINE_5 ((uint32_t)0x000020) /*!< external interrupt line 5 */ 56 | #define EXINT_LINE_6 ((uint32_t)0x000040) /*!< external interrupt line 6 */ 57 | #define EXINT_LINE_7 ((uint32_t)0x000080) /*!< external interrupt line 7 */ 58 | #define EXINT_LINE_8 ((uint32_t)0x000100) /*!< external interrupt line 8 */ 59 | #define EXINT_LINE_9 ((uint32_t)0x000200) /*!< external interrupt line 9 */ 60 | #define EXINT_LINE_10 ((uint32_t)0x000400) /*!< external interrupt line 10 */ 61 | #define EXINT_LINE_11 ((uint32_t)0x000800) /*!< external interrupt line 11 */ 62 | #define EXINT_LINE_12 ((uint32_t)0x001000) /*!< external interrupt line 12 */ 63 | #define EXINT_LINE_13 ((uint32_t)0x002000) /*!< external interrupt line 13 */ 64 | #define EXINT_LINE_14 ((uint32_t)0x004000) /*!< external interrupt line 14 */ 65 | #define EXINT_LINE_15 ((uint32_t)0x008000) /*!< external interrupt line 15 */ 66 | #define EXINT_LINE_16 ((uint32_t)0x010000) /*!< external interrupt line 16 connected to the pvm output */ 67 | #define EXINT_LINE_17 ((uint32_t)0x020000) /*!< external interrupt line 17 connected to the ertc alarm event */ 68 | #define EXINT_LINE_19 ((uint32_t)0x080000) /*!< external interrupt line 19 */ 69 | #define EXINT_LINE_21 ((uint32_t)0x200000) /*!< external interrupt line 21 connected to the cmp wakeup from suspend event */ 70 | 71 | /** 72 | * @} 73 | */ 74 | 75 | /** @defgroup EXINT_exported_types 76 | * @{ 77 | */ 78 | 79 | /** 80 | * @brief exint line mode type 81 | */ 82 | typedef enum 83 | { 84 | EXINT_LINE_INTERRUPUT = 0x00, /*!< external interrupt line interrupt mode */ 85 | EXINT_LINE_EVENT = 0x01 /*!< external interrupt line event mode */ 86 | } exint_line_mode_type; 87 | 88 | /** 89 | * @brief exint polarity configuration type 90 | */ 91 | typedef enum 92 | { 93 | EXINT_TRIGGER_RISING_EDGE = 0x00, /*!< external interrupt line rising trigger mode */ 94 | EXINT_TRIGGER_FALLING_EDGE = 0x01, /*!< external interrupt line falling trigger mode */ 95 | EXINT_TRIGGER_BOTH_EDGE = 0x02 /*!< external interrupt line both rising and falling trigger mode */ 96 | } exint_polarity_config_type; 97 | 98 | /** 99 | * @brief exint init type 100 | */ 101 | typedef struct 102 | { 103 | exint_line_mode_type line_mode; /*!< choose mode event or interrupt mode */ 104 | uint32_t line_select; /*!< select the exint line, availiable for single line or multiple lines */ 105 | exint_polarity_config_type line_polarity; /*!< select the tregger polarity, with rising edge, falling edge or both edge */ 106 | confirm_state line_enable; /*!< enable or disable exint */ 107 | } exint_init_type; 108 | 109 | /** 110 | * @brief type define exint register all 111 | */ 112 | typedef struct 113 | { 114 | 115 | /** 116 | * @brief exint inten register, offset:0x00 117 | */ 118 | union 119 | { 120 | __IO uint32_t inten; 121 | struct 122 | { 123 | __IO uint32_t intenx : 22;/* [21:0] */ 124 | __IO uint32_t reserved1 : 10;/* [31:22] */ 125 | } inten_bit; 126 | }; 127 | 128 | /** 129 | * @brief exint evten register, offset:0x04 130 | */ 131 | union 132 | { 133 | __IO uint32_t evten; 134 | struct 135 | { 136 | __IO uint32_t evtenx : 22;/* [21:0] */ 137 | __IO uint32_t reserved1 : 10;/* [31:22] */ 138 | } evten_bit; 139 | }; 140 | 141 | /** 142 | * @brief exint polcfg1 register, offset:0x08 143 | */ 144 | union 145 | { 146 | __IO uint32_t polcfg1; 147 | struct 148 | { 149 | __IO uint32_t rpx : 22;/* [21:0] */ 150 | __IO uint32_t reserved1 : 10;/* [31:22] */ 151 | } polcfg1_bit; 152 | }; 153 | 154 | /** 155 | * @brief exint polcfg2 register, offset:0x0C 156 | */ 157 | union 158 | { 159 | __IO uint32_t polcfg2; 160 | struct 161 | { 162 | __IO uint32_t fpx : 22;/* [21:0] */ 163 | __IO uint32_t reserved1 : 10;/* [31:22] */ 164 | } polcfg2_bit; 165 | }; 166 | 167 | /** 168 | * @brief exint swtrg register, offset:0x10 169 | */ 170 | union 171 | { 172 | __IO uint32_t swtrg; 173 | struct 174 | { 175 | __IO uint32_t swtx : 22;/* [21:0] */ 176 | __IO uint32_t reserved1 : 10;/* [31:22] */ 177 | } swtrg_bit; 178 | }; 179 | 180 | /** 181 | * @brief exint intsts register, offset:0x14 182 | */ 183 | union 184 | { 185 | __IO uint32_t intsts; 186 | struct 187 | { 188 | __IO uint32_t linex : 20;/* [21:0] */ 189 | __IO uint32_t reserved1 : 12;/* [31:22] */ 190 | } intsts_bit; 191 | }; 192 | } exint_type; 193 | 194 | /** 195 | * @} 196 | */ 197 | 198 | #define EXINT ((exint_type *) EXINT_BASE) 199 | 200 | /** @defgroup EXINT_exported_functions 201 | * @{ 202 | */ 203 | 204 | void exint_reset(void); 205 | void exint_default_para_init(exint_init_type *exint_struct); 206 | void exint_init(exint_init_type *exint_struct); 207 | void exint_flag_clear(uint32_t exint_line); 208 | flag_status exint_flag_get(uint32_t exint_line); 209 | void exint_software_interrupt_event_generate(uint32_t exint_line); 210 | void exint_interrupt_enable(uint32_t exint_line, confirm_state new_state); 211 | void exint_event_enable(uint32_t exint_line, confirm_state new_state); 212 | 213 | /** 214 | * @} 215 | */ 216 | 217 | /** 218 | * @} 219 | */ 220 | 221 | /** 222 | * @} 223 | */ 224 | 225 | #ifdef __cplusplus 226 | } 227 | #endif 228 | 229 | #endif 230 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_misc.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_misc.c 4 | * @brief contains all the functions for the misc firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* includes ------------------------------------------------------------------*/ 26 | #include "at32f421_conf.h" 27 | 28 | /** @addtogroup AT32F421_periph_driver 29 | * @{ 30 | */ 31 | 32 | /** @defgroup MISC 33 | * @brief MISC driver modules 34 | * @{ 35 | */ 36 | 37 | #ifdef MISC_MODULE_ENABLED 38 | 39 | /** @defgroup MISC_private_functions 40 | * @{ 41 | */ 42 | 43 | #define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) 44 | 45 | /** 46 | * @brief system reset 47 | * @param none 48 | * @retval none 49 | */ 50 | void nvic_system_reset(void) 51 | { 52 | NVIC_SystemReset(); 53 | } 54 | 55 | /** 56 | * @brief enable nvic irq 57 | * @param irqn (IRQn_Type number) 58 | * @param preempt_priority: preemptive priority value (starting from 0) 59 | * @param sub_priority: subpriority value (starting from 0) 60 | * @retval none 61 | */ 62 | void nvic_irq_enable(IRQn_Type irqn, uint32_t preempt_priority, uint32_t sub_priority) 63 | { 64 | uint32_t temp_priority = 0; 65 | 66 | /* encode priority */ 67 | temp_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), preempt_priority, sub_priority); 68 | /* set priority */ 69 | NVIC_SetPriority(irqn, temp_priority); 70 | /* enable irqn */ 71 | NVIC_EnableIRQ(irqn); 72 | } 73 | 74 | /** 75 | * @brief disable nvic irq number 76 | * @param irqn (IRQn_Type number) 77 | * @retval none 78 | */ 79 | void nvic_irq_disable(IRQn_Type irqn) 80 | { 81 | NVIC_DisableIRQ(irqn); 82 | } 83 | 84 | /** 85 | * @brief config nvic priority group 86 | * @param priority_group 87 | * this parameter can be one of the following values: 88 | * - NVIC_PRIORITY_GROUP_0 89 | * - NVIC_PRIORITY_GROUP_1 90 | * - NVIC_PRIORITY_GROUP_2 91 | * - NVIC_PRIORITY_GROUP_3 92 | * - NVIC_PRIORITY_GROUP_4 93 | * @retval none 94 | */ 95 | void nvic_priority_group_config(nvic_priority_group_type priority_group) 96 | { 97 | /* set the prigroup[10:8] bits according to nvic_prioritygroup value */ 98 | NVIC_SetPriorityGrouping(priority_group); 99 | } 100 | 101 | /** 102 | * @brief set the vector table location and offset. 103 | * @param base 104 | * this parameter can be one of the following values: 105 | * - NVIC_VECTTAB_RAM 106 | * - NVIC_VECTTAB_FLASH 107 | * @param offset (vector table base offset field. this value must be a multiple of 0x200) 108 | * @retval none 109 | */ 110 | void nvic_vector_table_set(uint32_t base, uint32_t offset) 111 | { 112 | SCB->VTOR = base | (offset & (uint32_t)0x1FFFFF80); 113 | } 114 | 115 | /** 116 | * @brief config nvic lowpower mode 117 | * @param lp_mode 118 | * this parameter can be one of the following values: 119 | * - NVIC_LP_SEVONPEND 120 | * - NVIC_LP_SLEEPDEEP 121 | * - NVIC_LP_SLEEPONEXIT 122 | * @param new_state (new state of lp condition. ENABLE or DISABLE) 123 | * @retval none 124 | */ 125 | void nvic_lowpower_mode_config(nvic_lowpower_mode_type lp_mode, confirm_state new_state) 126 | { 127 | if(new_state != FALSE) 128 | { 129 | SCB->SCR |= lp_mode; 130 | } 131 | else 132 | { 133 | SCB->SCR &= (uint32_t)(~(uint32_t)lp_mode); 134 | } 135 | } 136 | 137 | /** 138 | * @brief config systick clock source 139 | * @param source 140 | * this parameter can be one of the following values: 141 | * - SYSTICK_CLOCK_SOURCE_AHBCLK_DIV8 142 | * - SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV 143 | * @retval none 144 | */ 145 | void systick_clock_source_config(systick_clock_source_type source) 146 | { 147 | if(source == SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV) 148 | { 149 | SysTick->CTRL |= SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV; 150 | } 151 | else 152 | { 153 | SysTick->CTRL &= ~(uint32_t)SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV; 154 | } 155 | } 156 | 157 | /** 158 | * @} 159 | */ 160 | 161 | #endif 162 | 163 | /** 164 | * @} 165 | */ 166 | 167 | /** 168 | * @} 169 | */ 170 | 171 | 172 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_misc.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_misc.h 4 | * @brief at32f421 misc header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_MISC_H 27 | #define __AT32F421_MISC_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | /* includes ------------------------------------------------------------------*/ 35 | #include "at32f421.h" 36 | 37 | /** @addtogroup AT32F421_periph_driver 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup MISC 42 | * @{ 43 | */ 44 | 45 | /** @defgroup MISC_vector_table_base_address 46 | * @{ 47 | */ 48 | 49 | #define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< nvic vector table based ram address */ 50 | #define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< nvic vector table based flash address */ 51 | 52 | /** 53 | * @} 54 | */ 55 | 56 | /** @defgroup MISC_exported_types 57 | * @{ 58 | */ 59 | 60 | /** 61 | * @brief nvic interrupt priority group 62 | */ 63 | typedef enum 64 | { 65 | NVIC_PRIORITY_GROUP_0 = ((uint32_t)0x7), /*!< 0 bits for preemption priority, 4 bits for subpriority */ 66 | NVIC_PRIORITY_GROUP_1 = ((uint32_t)0x6), /*!< 1 bits for preemption priority, 3 bits for subpriority */ 67 | NVIC_PRIORITY_GROUP_2 = ((uint32_t)0x5), /*!< 2 bits for preemption priority, 2 bits for subpriority */ 68 | NVIC_PRIORITY_GROUP_3 = ((uint32_t)0x4), /*!< 3 bits for preemption priority, 1 bits for subpriority */ 69 | NVIC_PRIORITY_GROUP_4 = ((uint32_t)0x3) /*!< 4 bits for preemption priority, 0 bits for subpriority */ 70 | } nvic_priority_group_type; 71 | 72 | /** 73 | * @brief nvic low power mode 74 | */ 75 | typedef enum 76 | { 77 | NVIC_LP_SLEEPONEXIT = 0x02, /*!< enable sleep-on-exit feature */ 78 | NVIC_LP_SLEEPDEEP = 0x04, /*!< enable sleep-deep output signal when entering sleep mode */ 79 | NVIC_LP_SEVONPEND = 0x10 /*!< send event on pending */ 80 | } nvic_lowpower_mode_type; 81 | 82 | /** 83 | * @brief systick clock source 84 | */ 85 | typedef enum 86 | { 87 | SYSTICK_CLOCK_SOURCE_AHBCLK_DIV8 = ((uint32_t)0x00000000), /*!< systick clock source from core clock div8 */ 88 | SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV = ((uint32_t)0x00000004) /*!< systick clock source from core clock */ 89 | } systick_clock_source_type; 90 | 91 | /** 92 | * @} 93 | */ 94 | 95 | /** @defgroup MISC_exported_functions 96 | * @{ 97 | */ 98 | 99 | void nvic_system_reset(void); 100 | void nvic_irq_enable(IRQn_Type irqn, uint32_t preempt_priority, uint32_t sub_priority); 101 | void nvic_irq_disable(IRQn_Type irqn); 102 | void nvic_priority_group_config(nvic_priority_group_type priority_group); 103 | void nvic_vector_table_set(uint32_t base, uint32_t offset); 104 | void nvic_lowpower_mode_config(nvic_lowpower_mode_type lp_mode, confirm_state new_state); 105 | void systick_clock_source_config(systick_clock_source_type source); 106 | 107 | /** 108 | * @} 109 | */ 110 | 111 | /** 112 | * @} 113 | */ 114 | 115 | /** 116 | * @} 117 | */ 118 | 119 | #ifdef __cplusplus 120 | } 121 | #endif 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_pwc.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_pwc.c 4 | * @brief contains all the functions for the pwc firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup PWC 32 | * @brief PWC driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef PWC_MODULE_ENABLED 37 | 38 | /** @defgroup PWC_private_functions 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @brief deinitialize the pwc peripheral registers to their default reset values. 44 | * @param none 45 | * @retval none 46 | */ 47 | void pwc_reset(void) 48 | { 49 | crm_periph_reset(CRM_PWC_PERIPH_RESET, TRUE); 50 | crm_periph_reset(CRM_PWC_PERIPH_RESET, FALSE); 51 | } 52 | 53 | /** 54 | * @brief enable or disable access to the battery powered domain. 55 | * @param new_state: new state of battery powered domain access. 56 | * this parameter can be: TRUE or FALSE. 57 | * @retval none 58 | */ 59 | void pwc_battery_powered_domain_access(confirm_state new_state) 60 | { 61 | PWC->ctrl_bit.bpwen = new_state; 62 | } 63 | 64 | /** 65 | * @brief select the voltage threshold detected by the power voltage detector. 66 | * @param pvm_voltage: select pwc pvm voltage 67 | * this parameter can be one of the following values: 68 | * - PWC_PVM_VOLTAGE_2V3 69 | * - PWC_PVM_VOLTAGE_2V4 70 | * - PWC_PVM_VOLTAGE_2V5 71 | * - PWC_PVM_VOLTAGE_2V6 72 | * - PWC_PVM_VOLTAGE_2V7 73 | * - PWC_PVM_VOLTAGE_2V8 74 | * - PWC_PVM_VOLTAGE_2V9 75 | * @retval none 76 | */ 77 | void pwc_pvm_level_select(pwc_pvm_voltage_type pvm_voltage) 78 | { 79 | PWC->ctrl_bit.pvmsel = pvm_voltage; 80 | } 81 | 82 | /** 83 | * @brief enable or disable pwc power voltage monitor (pvm) 84 | * @param new_state: new state of pvm. 85 | * this parameter can be: TRUE or FALSE. 86 | * @retval none 87 | */ 88 | void pwc_power_voltage_monitor_enable(confirm_state new_state) 89 | { 90 | PWC->ctrl_bit.pvmen = new_state; 91 | } 92 | 93 | /** 94 | * @brief enable or disable pwc standby wakeup pin 95 | * @param pin_num: choose the wakeup pin. 96 | * this parameter can be be any combination of the following values: 97 | * - PWC_WAKEUP_PIN_1 98 | * - PWC_WAKEUP_PIN_2 99 | * - PWC_WAKEUP_PIN_6 100 | * - PWC_WAKEUP_PIN_7 101 | * @param new_state: new state of the standby wakeup pin. 102 | * this parameter can be one of the following values: 103 | * - TRUE 104 | * - FALSE 105 | * @retval none 106 | */ 107 | void pwc_wakeup_pin_enable(uint32_t pin_num, confirm_state new_state) 108 | { 109 | if(new_state == TRUE) 110 | { 111 | PWC->ctrlsts |= pin_num; 112 | } 113 | else 114 | { 115 | PWC->ctrlsts &= ~pin_num; 116 | } 117 | } 118 | 119 | /** 120 | * @brief clear flag of pwc 121 | * @param pwc_flag: select the pwc flag. 122 | * this parameter can be any combination of the following values: 123 | * - PWC_WAKEUP_FLAG 124 | * - PWC_STANDBY_FLAG 125 | * - note:"PWC_PVM_OUTPUT_FLAG" cannot be choose!this bit is readonly bit,it means the voltage monitoring output state 126 | * @retval none 127 | */ 128 | void pwc_flag_clear(uint32_t pwc_flag) 129 | { 130 | if(pwc_flag & PWC_STANDBY_FLAG) 131 | PWC->ctrl_bit.clsef = TRUE; 132 | if(pwc_flag & PWC_WAKEUP_FLAG) 133 | PWC->ctrl_bit.clswef = TRUE; 134 | } 135 | 136 | /** 137 | * @brief get flag of pwc 138 | * @param pwc_flag: select the pwc flag. 139 | * this parameter can be one of the following values: 140 | * - PWC_WAKEUP_FLAG 141 | * - PWC_STANDBY_FLAG 142 | * - PWC_PVM_OUTPUT_FLAG 143 | * @retval state of select flag(SET or RESET). 144 | */ 145 | flag_status pwc_flag_get(uint32_t pwc_flag) 146 | { 147 | flag_status status = RESET; 148 | if ((PWC->ctrlsts & pwc_flag) == RESET) 149 | { 150 | status = RESET; 151 | } 152 | else 153 | { 154 | status = SET; 155 | } 156 | return status; 157 | } 158 | 159 | /** 160 | * @brief enter pwc sleep mode 161 | * @param sleep_mode_enter: choose the instruction to enter sleep mode. 162 | * this parameter can be one of the following values: 163 | * - PWC_SLEEP_ENTER_WFI 164 | * - PWC_SLEEP_ENTER_WFE 165 | * @retval none 166 | */ 167 | void pwc_sleep_mode_enter(pwc_sleep_enter_type pwc_sleep_enter) 168 | { 169 | SCB->SCR &= (uint32_t)~0x4; 170 | if(pwc_sleep_enter == PWC_SLEEP_ENTER_WFE) 171 | { 172 | __SEV(); 173 | __WFE(); 174 | __WFE(); 175 | } 176 | else if(pwc_sleep_enter == PWC_SLEEP_ENTER_WFI) 177 | { 178 | __WFI(); 179 | } 180 | } 181 | 182 | /** 183 | * @brief enter pwc deep-sleep mode 184 | * @param pwc_deep_sleep_enter: choose the instruction to enter deep sleep mode. 185 | * this parameter can be one of the following values: 186 | * - PWC_DEEP_SLEEP_ENTER_WFI 187 | * - PWC_DEEP_SLEEP_ENTER_WFE 188 | * @retval none 189 | */ 190 | void pwc_deep_sleep_mode_enter(pwc_deep_sleep_enter_type pwc_deep_sleep_enter) 191 | { 192 | SCB->SCR |= 0x04; 193 | if(pwc_deep_sleep_enter == PWC_DEEP_SLEEP_ENTER_WFE) 194 | { 195 | __SEV(); 196 | __WFE(); 197 | __WFE(); 198 | } 199 | else if(pwc_deep_sleep_enter == PWC_DEEP_SLEEP_ENTER_WFI) 200 | { 201 | __WFI(); 202 | } 203 | SCB->SCR &= (uint32_t)~0x4; 204 | } 205 | 206 | /** 207 | * @brief regulate low power consumption in the deep sleep mode 208 | * @param pwc_regulator: set the regulator state. 209 | * this parameter can be one of the following values: 210 | * - PWC_REGULATOR_ON 211 | * - PWC_REGULATOR_LOW_POWER 212 | * - PWC_REGULATOR_EXTRA_LOW_POWER 213 | * @retval none 214 | */ 215 | void pwc_voltage_regulate_set(pwc_regulator_type pwc_regulator) 216 | { 217 | switch(pwc_regulator) 218 | { 219 | case 0: 220 | PWC->ctrl2_bit.vrexlpen = 0; 221 | PWC->ctrl_bit.vrsel = 0; 222 | break; 223 | case 1: 224 | PWC->ctrl2_bit.vrexlpen = 0; 225 | PWC->ctrl_bit.vrsel = 1; 226 | break; 227 | case 2: 228 | PWC->ctrl2_bit.vrexlpen = 1; 229 | PWC->ctrl_bit.vrsel = 1; 230 | break; 231 | default: 232 | break; 233 | } 234 | } 235 | 236 | /** 237 | * @brief enter pwc standby mode 238 | * @param none 239 | * @retval none 240 | */ 241 | void pwc_standby_mode_enter(void) 242 | { 243 | PWC->ctrl_bit.clswef = TRUE; 244 | PWC->ctrl_bit.lpsel = TRUE; 245 | SCB->SCR |= 0x04; 246 | #if defined (__CC_ARM) 247 | __force_stores(); 248 | #endif 249 | while(1) 250 | { 251 | __WFI(); 252 | } 253 | } 254 | 255 | /** 256 | * @} 257 | */ 258 | 259 | #endif 260 | 261 | /** 262 | * @} 263 | */ 264 | 265 | /** 266 | * @} 267 | */ 268 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_pwc.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_pwc.h 4 | * @brief at32f421 pwc header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* Define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_PWC_H 27 | #define __AT32F421_PWC_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | /* Includes ------------------------------------------------------------------*/ 35 | #include "at32f421.h" 36 | 37 | /** @addtogroup AT32F421_periph_driver 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup PWC 42 | * @{ 43 | */ 44 | 45 | /** @defgroup PWC_flags_definition 46 | * @brief pwc flag 47 | * @{ 48 | */ 49 | 50 | #define PWC_WAKEUP_FLAG ((uint32_t)0x00000001) /*!< wakeup flag */ 51 | #define PWC_STANDBY_FLAG ((uint32_t)0x00000002) /*!< standby flag */ 52 | #define PWC_PVM_OUTPUT_FLAG ((uint32_t)0x00000004) /*!< pvm output flag */ 53 | 54 | /** 55 | * @} 56 | */ 57 | 58 | /** 59 | * @brief pwc wakeup pin num definition 60 | */ 61 | #define PWC_WAKEUP_PIN_1 ((uint32_t)0x00000100) /*!< standby wake-up pin1 */ 62 | #define PWC_WAKEUP_PIN_2 ((uint32_t)0x00000200) /*!< standby wake-up pin2 */ 63 | #define PWC_WAKEUP_PIN_6 ((uint32_t)0x00002000) /*!< standby wake-up pin6 */ 64 | #define PWC_WAKEUP_PIN_7 ((uint32_t)0x00004000) /*!< standby wake-up pin7 */ 65 | 66 | /** @defgroup PWC_exported_types 67 | * @{ 68 | */ 69 | 70 | /** 71 | * @brief pwc pvm voltage type 72 | */ 73 | typedef enum 74 | { 75 | PWC_PVM_VOLTAGE_2V3 = 0x01, /*!< power voltage monitoring boundary 2.3v */ 76 | PWC_PVM_VOLTAGE_2V4 = 0x02, /*!< power voltage monitoring boundary 2.4v */ 77 | PWC_PVM_VOLTAGE_2V5 = 0x03, /*!< power voltage monitoring boundary 2.5v */ 78 | PWC_PVM_VOLTAGE_2V6 = 0x04, /*!< power voltage monitoring boundary 2.6v */ 79 | PWC_PVM_VOLTAGE_2V7 = 0x05, /*!< power voltage monitoring boundary 2.7v */ 80 | PWC_PVM_VOLTAGE_2V8 = 0x06, /*!< power voltage monitoring boundary 2.8v */ 81 | PWC_PVM_VOLTAGE_2V9 = 0x07 /*!< power voltage monitoring boundary 2.9v */ 82 | } pwc_pvm_voltage_type; 83 | 84 | /** 85 | * @brief pwc sleep enter type 86 | */ 87 | typedef enum 88 | { 89 | PWC_SLEEP_ENTER_WFI = 0x00, /*!< use wfi enter sleep mode */ 90 | PWC_SLEEP_ENTER_WFE = 0x01 /*!< use wfe enter sleep mode */ 91 | } pwc_sleep_enter_type; 92 | 93 | /** 94 | * @brief pwc deep sleep enter type 95 | */ 96 | typedef enum 97 | { 98 | PWC_DEEP_SLEEP_ENTER_WFI = 0x00, /*!< use wfi enter deepsleep mode */ 99 | PWC_DEEP_SLEEP_ENTER_WFE = 0x01 /*!< use wfe enter deepsleep mode */ 100 | } pwc_deep_sleep_enter_type; 101 | 102 | /** 103 | * @brief pwc regulator type 104 | */ 105 | typedef enum 106 | { 107 | PWC_REGULATOR_ON = 0x00, /*!< voltage regulator state on when deepsleep mode */ 108 | PWC_REGULATOR_LOW_POWER = 0x01, /*!< voltage regulator state low power when deepsleep mode */ 109 | PWC_REGULATOR_EXTRA_LOW_POWER = 0x02 /*!< voltage regulator state extra low power when deepsleep mode */ 110 | } pwc_regulator_type; 111 | 112 | /** 113 | * @brief type define pwc register all 114 | */ 115 | typedef struct 116 | { 117 | /** 118 | * @brief pwc ctrl register, offset:0x00 119 | */ 120 | union 121 | { 122 | __IO uint32_t ctrl; 123 | struct 124 | { 125 | __IO uint32_t vrsel : 1; /* [0] */ 126 | __IO uint32_t lpsel : 1; /* [1] */ 127 | __IO uint32_t clswef : 1; /* [2] */ 128 | __IO uint32_t clsef : 1; /* [3] */ 129 | __IO uint32_t pvmen : 1; /* [4] */ 130 | __IO uint32_t pvmsel : 3; /* [7:5] */ 131 | __IO uint32_t bpwen : 1; /* [8] */ 132 | __IO uint32_t reserved1 : 23;/* [31:9] */ 133 | } ctrl_bit; 134 | }; 135 | 136 | /** 137 | * @brief pwc ctrlsts register, offset:0x04 138 | */ 139 | union 140 | { 141 | __IO uint32_t ctrlsts; 142 | struct 143 | { 144 | __IO uint32_t swef : 1; /* [0] */ 145 | __IO uint32_t sef : 1; /* [1] */ 146 | __IO uint32_t pvmof : 1; /* [2] */ 147 | __IO uint32_t reserved1 : 5; /* [7:3] */ 148 | __IO uint32_t swpen1 : 1; /* [8] */ 149 | __IO uint32_t swpen2 : 1; /* [9] */ 150 | __IO uint32_t reserved2 : 3; /* [12:10] */ 151 | __IO uint32_t swpen6 : 1; /* [13] */ 152 | __IO uint32_t swpen7 : 1; /* [14] */ 153 | __IO uint32_t reserved3 : 17;/* [31:15] */ 154 | } ctrlsts_bit; 155 | }; 156 | 157 | /** 158 | * @brief pwc reserved register, offset:0x08~0x1C 159 | */ 160 | __IO uint32_t reserved1[6]; 161 | 162 | /** 163 | * @brief pwc ctrl2 register, offset:0x20 164 | */ 165 | union 166 | { 167 | __IO uint32_t ctrl2; 168 | struct 169 | { 170 | __IO uint32_t reserved1 : 5;/* [4:0] */ 171 | __IO uint32_t vrexlpen : 1; /* [5] */ 172 | __IO uint32_t reserved2 : 26;/* [31:6] */ 173 | } ctrl2_bit; 174 | }; 175 | 176 | } pwc_type; 177 | 178 | /** 179 | * @} 180 | */ 181 | 182 | #define PWC ((pwc_type *) PWC_BASE) 183 | 184 | /** @defgroup PWC_exported_functions 185 | * @{ 186 | */ 187 | 188 | void pwc_reset(void); 189 | void pwc_battery_powered_domain_access(confirm_state new_state); 190 | void pwc_pvm_level_select(pwc_pvm_voltage_type pvm_voltage); 191 | void pwc_power_voltage_monitor_enable(confirm_state new_state); 192 | void pwc_wakeup_pin_enable(uint32_t pin_num, confirm_state new_state); 193 | void pwc_flag_clear(uint32_t pwc_flag); 194 | flag_status pwc_flag_get(uint32_t pwc_flag); 195 | void pwc_sleep_mode_enter(pwc_sleep_enter_type pwc_sleep_enter); 196 | void pwc_deep_sleep_mode_enter(pwc_deep_sleep_enter_type pwc_deep_sleep_enter); 197 | void pwc_voltage_regulate_set(pwc_regulator_type pwc_regulator); 198 | void pwc_standby_mode_enter(void); 199 | 200 | /** 201 | * @} 202 | */ 203 | 204 | /** 205 | * @} 206 | */ 207 | 208 | /** 209 | * @} 210 | */ 211 | 212 | #ifdef __cplusplus 213 | } 214 | #endif 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_scfg.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_scfg.c 4 | * @brief contains all the functions for the system config firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup SCFG 32 | * @brief SCFG driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef SCFG_MODULE_ENABLED 37 | 38 | /** @defgroup SCFG_private_functions 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @brief scfg reset 44 | * @param none 45 | * @retval none 46 | */ 47 | void scfg_reset(void) 48 | { 49 | crm_periph_reset(CRM_SCFG_PERIPH_RESET, TRUE); 50 | crm_periph_reset(CRM_SCFG_PERIPH_RESET, FALSE); 51 | } 52 | 53 | /** 54 | * @brief scfg infrared config 55 | * @param source 56 | * this parameter can be one of the following values: 57 | * - SCFG_IR_SOURCE_TMR16 58 | * - SCFG_IR_SOURCE_USART1 59 | * - SCFG_IR_SOURCE_USART2 60 | * @param polarity 61 | * this parameter can be one of the following values: 62 | * - SCFG_IR_POLARITY_NO_AFFECTE 63 | * - SCFG_IR_POLARITY_REVERSE 64 | * @retval none 65 | */ 66 | void scfg_infrared_config(scfg_ir_source_type source, scfg_ir_polarity_type polarity) 67 | { 68 | SCFG->cfg1_bit.ir_src_sel = source; 69 | SCFG->cfg1_bit.ir_pol = polarity; 70 | } 71 | 72 | /** 73 | * @brief scfg memory address mapping get 74 | * @param none 75 | * @retval return parameter can be one of the following values: 76 | * - SCFG_MEM_MAP_MAIN_MEMORY 77 | * - SCFG_MEM_MAP_BOOT_MEMORY 78 | * - SCFG_MEM_MAP_INTERNAL_SRAM 79 | */ 80 | uint8_t scfg_mem_map_get(void) 81 | { 82 | return (uint8_t)SCFG->cfg1_bit.mem_map_sel ; 83 | } 84 | 85 | /** 86 | * @brief scfg pa11/12 pin remap 87 | * @param pin_remap 88 | * this parameter can be one of the following values: 89 | * - SCFG_PA11PA12_NO_REMAP 90 | * - SCFG_PA11PA12_TO_PA9PA10 91 | * @retval none 92 | */ 93 | void scfg_pa11pa12_pin_remap(scfg_pa11pa12_remap_type pin_remap) 94 | { 95 | SCFG->cfg1_bit.pa11_12_rmp = pin_remap; 96 | } 97 | 98 | /** 99 | * @brief scfg adc dma channel remap 100 | * @param dma_channel 101 | * this parameter can be one of the following values: 102 | * - SCFG_ADC_TO_DMA_CHANNEL_1 103 | * - SCFG_ADC_TO_DMA_CHANNEL_2 104 | * @retval none 105 | */ 106 | void scfg_adc_dma_channel_remap(scfg_adc_dma_remap_type dma_channel) 107 | { 108 | SCFG->cfg1_bit.adc_dma_rmp = dma_channel; 109 | } 110 | 111 | /** 112 | * @brief scfg usart1 tx dma channel remap 113 | * @param dma_channel 114 | * this parameter can be one of the following values: 115 | * - SCFG_USART1_TX_TO_DMA_CHANNEL_2 116 | * - SCFG_USART1_TX_TO_DMA_CHANNEL_4 117 | * @retval none 118 | */ 119 | void scfg_usart1_tx_dma_channel_remap(scfg_usart1_tx_dma_remap_type dma_channel) 120 | { 121 | SCFG->cfg1_bit.usart1_tx_dma_rmp = dma_channel; 122 | } 123 | 124 | /** 125 | * @brief scfg usart1 rx dma channel remap 126 | * @param dma_channel 127 | * this parameter can be one of the following values: 128 | * - SCFG_USART1_RX_TO_DMA_CHANNEL_3 129 | * - SCFG_USART1_RX_TO_DMA_CHANNEL_5 130 | * @retval none 131 | */ 132 | void scfg_usart1_rx_dma_channel_remap(scfg_usart1_rx_dma_remap_type dma_channel) 133 | { 134 | SCFG->cfg1_bit.usart1_rx_dma_rmp = dma_channel; 135 | } 136 | 137 | /** 138 | * @brief scfg tmr16 dma channel remap 139 | * @param dma_channel 140 | * this parameter can be one of the following values: 141 | * - SCFG_TMR16_TO_DMA_CHANNEL_3 142 | * - SCFG_TMR16_TO_DMA_CHANNEL_4 143 | * @retval none 144 | */ 145 | void scfg_tmr16_dma_channel_remap(scfg_tmr16_dma_remap_type dma_channel) 146 | { 147 | SCFG->cfg1_bit.tmr16_dma_rmp = dma_channel; 148 | } 149 | 150 | /** 151 | * @brief scfg tmr17 dma channel remap 152 | * @param dma_channel 153 | * this parameter can be one of the following values: 154 | * - SCFG_TMR17_TO_DMA_CHANNEL_1 155 | * - SCFG_TMR17_TO_DMA_CHANNEL_2 156 | * @retval none 157 | */ 158 | void scfg_tmr17_dma_channel_remap(scfg_tmr17_dma_remap_type dma_channel) 159 | { 160 | SCFG->cfg1_bit.tmr17_dma_rmp = dma_channel; 161 | } 162 | 163 | /** 164 | * @brief select the gpio pin used as exint line. 165 | * @param port_source: 166 | * select the gpio port to be used as source for exint lines. 167 | * this parameter can be one of the following values: 168 | * - SCFG_PORT_SOURCE_GPIOA 169 | * - SCFG_PORT_SOURCE_GPIOB 170 | * - SCFG_PORT_SOURCE_GPIOC 171 | * - SCFG_PORT_SOURCE_GPIOF 172 | * @param pin_source: 173 | * specifies the exint line to be configured. 174 | * this parameter can be one of the following values: 175 | * - SCFG_PINS_SOURCE0 176 | * - SCFG_PINS_SOURCE1 177 | * - SCFG_PINS_SOURCE2 178 | * - SCFG_PINS_SOURCE3 179 | * - SCFG_PINS_SOURCE4 180 | * - SCFG_PINS_SOURCE5 181 | * - SCFG_PINS_SOURCE6 182 | * - SCFG_PINS_SOURCE7 183 | * - SCFG_PINS_SOURCE8 184 | * - SCFG_PINS_SOURCE9 185 | * - SCFG_PINS_SOURCE10 186 | * - SCFG_PINS_SOURCE11 187 | * - SCFG_PINS_SOURCE12 188 | * - SCFG_PINS_SOURCE13 189 | * - SCFG_PINS_SOURCE14 190 | * - SCFG_PINS_SOURCE15 191 | * @retval none 192 | */ 193 | void scfg_exint_line_config(scfg_port_source_type port_source, scfg_pins_source_type pin_source) 194 | { 195 | uint32_t tmp = 0x00; 196 | tmp = ((uint32_t)0x0F) << (0x04 * (pin_source & (uint8_t)0x03)); 197 | 198 | switch (pin_source >> 0x02) 199 | { 200 | case 0: 201 | SCFG->exintc1 &= ~tmp; 202 | SCFG->exintc1 |= (((uint32_t)port_source) << (0x04 * (pin_source & (uint8_t)0x03))); 203 | break; 204 | 205 | case 1: 206 | SCFG->exintc2 &= ~tmp; 207 | SCFG->exintc2 |= (((uint32_t)port_source) << (0x04 * (pin_source & (uint8_t)0x03))); 208 | break; 209 | 210 | case 2: 211 | SCFG->exintc3 &= ~tmp; 212 | SCFG->exintc3 |= (((uint32_t)port_source) << (0x04 * (pin_source & (uint8_t)0x03))); 213 | break; 214 | 215 | case 3: 216 | SCFG->exintc4 &= ~tmp; 217 | SCFG->exintc4 |= (((uint32_t)port_source) << (0x04 * (pin_source & (uint8_t)0x03))); 218 | break; 219 | 220 | default: 221 | break; 222 | } 223 | } 224 | 225 | /** 226 | * @} 227 | */ 228 | 229 | #endif 230 | 231 | /** 232 | * @} 233 | */ 234 | 235 | /** 236 | * @} 237 | */ 238 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_wdt.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_wdt.c 4 | * @brief contains all the functions for the wdt firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup WDT 32 | * @brief WDT driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef WDT_MODULE_ENABLED 37 | 38 | /** @defgroup WDT_private_functions 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @brief wdt enable ,the reload value will be sent to the counter 44 | * @param none 45 | * @retval none 46 | */ 47 | void wdt_enable(void) 48 | { 49 | WDT->cmd = WDT_CMD_ENABLE; 50 | } 51 | 52 | /** 53 | * @brief reload wdt counter 54 | * @param none 55 | * @retval none 56 | */ 57 | void wdt_counter_reload(void) 58 | { 59 | WDT->cmd = WDT_CMD_RELOAD; 60 | } 61 | 62 | /** 63 | * @brief set wdt counter reload value 64 | * @param reload_value (0x0000~0x0FFF) 65 | * @retval none 66 | */ 67 | void wdt_reload_value_set(uint16_t reload_value) 68 | { 69 | WDT->rld = reload_value; 70 | } 71 | 72 | /** 73 | * @brief set wdt division divider 74 | * @param division 75 | * this parameter can be one of the following values: 76 | * - WDT_CLK_DIV_4 77 | * - WDT_CLK_DIV_8 78 | * - WDT_CLK_DIV_16 79 | * - WDT_CLK_DIV_32 80 | * - WDT_CLK_DIV_64 81 | * - WDT_CLK_DIV_128 82 | * - WDT_CLK_DIV_256 83 | * @retval none 84 | */ 85 | void wdt_divider_set(wdt_division_type division) 86 | { 87 | WDT->div_bit.div = division; 88 | } 89 | 90 | /** 91 | * @brief enable or disable wdt cmd register write 92 | * @param new_state (TRUE or FALSE) 93 | * @retval none 94 | */ 95 | void wdt_register_write_enable( confirm_state new_state) 96 | { 97 | if(new_state == FALSE) 98 | { 99 | WDT->cmd = WDT_CMD_LOCK; 100 | } 101 | else 102 | { 103 | WDT->cmd = WDT_CMD_UNLOCK; 104 | } 105 | } 106 | 107 | /** 108 | * @brief get wdt flag 109 | * @param wdt_flag 110 | * this parameter can be one of the following values: 111 | * - WDT_DIVF_UPDATE_FLAG: division value update complete flag. 112 | * - WDT_RLDF_UPDATE_FLAG: reload value update complete flag. 113 | * @retval state of wdt flag 114 | */ 115 | flag_status wdt_flag_get(uint16_t wdt_flag) 116 | { 117 | flag_status status = RESET; 118 | 119 | if ((WDT->sts & wdt_flag) != (uint16_t)RESET) 120 | { 121 | status = SET; 122 | } 123 | else 124 | { 125 | status = RESET; 126 | } 127 | 128 | return status; 129 | } 130 | 131 | /** 132 | * @} 133 | */ 134 | 135 | #endif 136 | 137 | /** 138 | * @} 139 | */ 140 | 141 | /** 142 | * @} 143 | */ 144 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_wdt.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_wdt.h 4 | * @brief at32f421 wdt header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* Define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_WDT_H 27 | #define __AT32F421_WDT_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | /* Includes ------------------------------------------------------------------*/ 35 | #include "at32f421.h" 36 | 37 | /** @addtogroup AT32F421_periph_driver 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup WDT 42 | * @{ 43 | */ 44 | 45 | 46 | /** @defgroup WDT_flags_definition 47 | * @brief wdt flag 48 | * @{ 49 | */ 50 | 51 | #define WDT_DIVF_UPDATE_FLAG ((uint16_t)0x0001) /*!< wdt division value update complete flag */ 52 | #define WDT_RLDF_UPDATE_FLAG ((uint16_t)0x0002) /*!< wdt reload value update complete flag */ 53 | 54 | /** 55 | * @} 56 | */ 57 | 58 | /** @defgroup WDT_exported_types 59 | * @{ 60 | */ 61 | 62 | /** 63 | * @brief wdt division value type 64 | */ 65 | typedef enum 66 | { 67 | WDT_CLK_DIV_4 = 0x00, /*!< wdt clock divider value is 4 */ 68 | WDT_CLK_DIV_8 = 0x01, /*!< wdt clock divider value is 8 */ 69 | WDT_CLK_DIV_16 = 0x02, /*!< wdt clock divider value is 16 */ 70 | WDT_CLK_DIV_32 = 0x03, /*!< wdt clock divider value is 32 */ 71 | WDT_CLK_DIV_64 = 0x04, /*!< wdt clock divider value is 64 */ 72 | WDT_CLK_DIV_128 = 0x05, /*!< wdt clock divider value is 128 */ 73 | WDT_CLK_DIV_256 = 0x06 /*!< wdt clock divider value is 256 */ 74 | } wdt_division_type; 75 | 76 | /** 77 | * @brief wdt cmd value type 78 | */ 79 | typedef enum 80 | { 81 | WDT_CMD_LOCK = 0x0000, /*!< disable write protection command */ 82 | WDT_CMD_UNLOCK = 0x5555, /*!< enable write protection command */ 83 | WDT_CMD_ENABLE = 0xCCCC, /*!< enable wdt command */ 84 | WDT_CMD_RELOAD = 0xAAAA /*!< reload command */ 85 | } wdt_cmd_value_type; 86 | 87 | /** 88 | * @brief type define wdt register all 89 | */ 90 | typedef struct 91 | { 92 | 93 | /** 94 | * @brief wdt cmd register, offset:0x00 95 | */ 96 | union 97 | { 98 | __IO uint32_t cmd; 99 | struct 100 | { 101 | __IO uint32_t cmd : 16;/* [15:0] */ 102 | __IO uint32_t reserved1 : 16;/* [31:16] */ 103 | } cmd_bit; 104 | }; 105 | 106 | /** 107 | * @brief wdt div register, offset:0x04 108 | */ 109 | union 110 | { 111 | __IO uint32_t div; 112 | struct 113 | { 114 | __IO uint32_t div : 3; /* [2:0] */ 115 | __IO uint32_t reserved1 : 29;/* [31:3] */ 116 | } div_bit; 117 | }; 118 | 119 | /** 120 | * @brief wdt rld register, offset:0x08 121 | */ 122 | union 123 | { 124 | __IO uint32_t rld; 125 | struct 126 | { 127 | __IO uint32_t rld : 12;/* [11:0] */ 128 | __IO uint32_t reserved1 : 20;/* [31:12] */ 129 | } rld_bit; 130 | }; 131 | 132 | /** 133 | * @brief wdt sts register, offset:0x0C 134 | */ 135 | union 136 | { 137 | __IO uint32_t sts; 138 | struct 139 | { 140 | __IO uint32_t divf : 1; /* [0] */ 141 | __IO uint32_t rldf : 1; /* [1] */ 142 | __IO uint32_t reserved1 : 30;/* [31:2] */ 143 | } sts_bit; 144 | }; 145 | 146 | } wdt_type; 147 | 148 | /** 149 | * @} 150 | */ 151 | 152 | #define WDT ((wdt_type *) WDT_BASE) 153 | 154 | /** @defgroup WDT_exported_functions 155 | * @{ 156 | */ 157 | 158 | void wdt_enable(void); 159 | void wdt_counter_reload(void); 160 | void wdt_reload_value_set(uint16_t reload_value); 161 | void wdt_divider_set(wdt_division_type division); 162 | void wdt_register_write_enable( confirm_state new_state); 163 | flag_status wdt_flag_get(uint16_t wdt_flag); 164 | 165 | /** 166 | * @} 167 | */ 168 | 169 | /** 170 | * @} 171 | */ 172 | 173 | /** 174 | * @} 175 | */ 176 | 177 | #ifdef __cplusplus 178 | } 179 | #endif 180 | 181 | #endif 182 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_wwdt.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_wwdt.c 4 | * @brief contains all the functions for the wwdt firmware library 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #include "at32f421_conf.h" 26 | 27 | /** @addtogroup AT32F421_periph_driver 28 | * @{ 29 | */ 30 | 31 | /** @defgroup WWDT 32 | * @brief WWDT driver modules 33 | * @{ 34 | */ 35 | 36 | #ifdef WWDT_MODULE_ENABLED 37 | 38 | /** @defgroup WWDT_private_functions 39 | * @{ 40 | */ 41 | 42 | /** 43 | * @brief wwdt reset by crm reset register 44 | * @retval none 45 | */ 46 | void wwdt_reset(void) 47 | { 48 | crm_periph_reset(CRM_WWDT_PERIPH_RESET, TRUE); 49 | crm_periph_reset(CRM_WWDT_PERIPH_RESET, FALSE); 50 | } 51 | 52 | /** 53 | * @brief wwdt division set 54 | * @param division 55 | * this parameter can be one of the following values: 56 | * - WWDT_PCLK1_DIV_4096 (wwdt counter clock = (pclk1/4096)/1) 57 | * - WWDT_PCLK1_DIV_8192 (wwdt counter clock = (pclk1/4096)/2) 58 | * - WWDT_PCLK1_DIV_16384 (wwdt counter clock = (pclk1/4096)/4) 59 | * - WWDT_PCLK1_DIV_32768 (wwdt counter clock = (pclk1/4096)/8) 60 | * @retval none 61 | */ 62 | void wwdt_divider_set(wwdt_division_type division) 63 | { 64 | WWDT->cfg_bit.div = division; 65 | } 66 | 67 | /** 68 | * @brief wwdt reload counter interrupt flag clear 69 | * @param none 70 | * @retval none 71 | */ 72 | void wwdt_flag_clear(void) 73 | { 74 | WWDT->sts = 0; 75 | } 76 | 77 | /** 78 | * @brief wwdt enable and the counter value load 79 | * @param wwdt_cnt (0x40~0x7f) 80 | * @retval none 81 | */ 82 | void wwdt_enable(uint8_t wwdt_cnt) 83 | { 84 | WWDT->ctrl = wwdt_cnt | WWDT_EN_BIT; 85 | } 86 | 87 | /** 88 | * @brief wwdt reload counter interrupt enable 89 | * @param none 90 | * @retval none 91 | */ 92 | void wwdt_interrupt_enable(void) 93 | { 94 | WWDT->cfg_bit.rldien = TRUE; 95 | } 96 | 97 | /** 98 | * @brief wwdt reload counter interrupt flag get 99 | * @param none 100 | * @retval state of reload counter interrupt flag 101 | */ 102 | flag_status wwdt_flag_get(void) 103 | { 104 | return (flag_status)WWDT->sts_bit.rldf; 105 | } 106 | 107 | /** 108 | * @brief wwdt counter value set 109 | * @param wwdt_cnt (0x40~0x7f) 110 | * @retval none 111 | */ 112 | void wwdt_counter_set(uint8_t wwdt_cnt) 113 | { 114 | WWDT->ctrl_bit.cnt = wwdt_cnt; 115 | } 116 | 117 | /** 118 | * @brief wwdt window counter value set 119 | * @param window_cnt (0x40~0x7f) 120 | * @retval none 121 | */ 122 | void wwdt_window_counter_set(uint8_t window_cnt) 123 | { 124 | WWDT->cfg_bit.win = window_cnt; 125 | } 126 | 127 | /** 128 | * @} 129 | */ 130 | 131 | #endif 132 | 133 | /** 134 | * @} 135 | */ 136 | 137 | /** 138 | * @} 139 | */ 140 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/at32f421_wwdt.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file at32f421_wwdt.h 4 | * @brief at32f421 wwdt header file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /* Define to prevent recursive inclusion -------------------------------------*/ 26 | #ifndef __AT32F421_WWDT_H 27 | #define __AT32F421_WWDT_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | 34 | /* Includes ------------------------------------------------------------------*/ 35 | #include "at32f421.h" 36 | 37 | /** @addtogroup AT32F421_periph_driver 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup WWDT 42 | * @{ 43 | */ 44 | 45 | /** @defgroup WWDT_enable_bit_definition 46 | * @brief wwdt enable bit 47 | * @{ 48 | */ 49 | 50 | #define WWDT_EN_BIT ((uint32_t)0x00000080) /*!< wwdt enable bit */ 51 | 52 | /** 53 | * @} 54 | */ 55 | 56 | /** @defgroup WWDT_exported_types 57 | * @{ 58 | */ 59 | 60 | /** 61 | * @brief wwdt division type 62 | */ 63 | typedef enum 64 | { 65 | WWDT_PCLK1_DIV_4096 = 0x00, /*!< wwdt counter clock = (pclk1/4096)/1) */ 66 | WWDT_PCLK1_DIV_8192 = 0x01, /*!< wwdt counter clock = (pclk1/4096)/2) */ 67 | WWDT_PCLK1_DIV_16384 = 0x02, /*!< wwdt counter clock = (pclk1/4096)/4) */ 68 | WWDT_PCLK1_DIV_32768 = 0x03 /*!< wwdt counter clock = (pclk1/4096)/8) */ 69 | } wwdt_division_type; 70 | 71 | /** 72 | * @brief type define wwdt register all 73 | */ 74 | typedef struct 75 | { 76 | 77 | /** 78 | * @brief wwdt ctrl register, offset:0x00 79 | */ 80 | union 81 | { 82 | __IO uint32_t ctrl; 83 | struct 84 | { 85 | __IO uint32_t cnt : 7; /* [6:0] */ 86 | __IO uint32_t wwdten : 1; /* [7] */ 87 | __IO uint32_t reserved1 : 24;/* [31:8] */ 88 | } ctrl_bit; 89 | }; 90 | 91 | /** 92 | * @brief wwdt cfg register, offset:0x04 93 | */ 94 | union 95 | { 96 | __IO uint32_t cfg; 97 | struct 98 | { 99 | __IO uint32_t win : 7; /* [6:0] */ 100 | __IO uint32_t div : 2; /* [8:7] */ 101 | __IO uint32_t rldien : 1; /* [9] */ 102 | __IO uint32_t reserved1 : 22;/* [31:10] */ 103 | } cfg_bit; 104 | }; 105 | 106 | /** 107 | * @brief wwdt cfg register, offset:0x08 108 | */ 109 | union 110 | { 111 | __IO uint32_t sts; 112 | struct 113 | { 114 | __IO uint32_t rldf : 1; /* [0] */ 115 | __IO uint32_t reserved1 : 31;/* [31:1] */ 116 | } sts_bit; 117 | }; 118 | 119 | } wwdt_type; 120 | 121 | /** 122 | * @} 123 | */ 124 | 125 | #define WWDT ((wwdt_type *) WWDT_BASE) 126 | 127 | /** @defgroup WWDT_exported_functions 128 | * @{ 129 | */ 130 | 131 | void wwdt_reset(void); 132 | void wwdt_divider_set(wwdt_division_type division); 133 | void wwdt_flag_clear(void); 134 | void wwdt_enable(uint8_t wwdt_cnt); 135 | void wwdt_interrupt_enable(void); 136 | flag_status wwdt_flag_get(void); 137 | void wwdt_counter_set(uint8_t wwdt_cnt); 138 | void wwdt_window_counter_set(uint8_t window_cnt); 139 | 140 | /** 141 | * @} 142 | */ 143 | 144 | /** 145 | * @} 146 | */ 147 | 148 | /** 149 | * @} 150 | */ 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/system_at32f421.c: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file system_at32f421.c 4 | * @brief contains all the functions for cmsis cortex-m4 system source file 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | /** @addtogroup CMSIS 26 | * @{ 27 | */ 28 | 29 | /** @addtogroup AT32F421_system 30 | * @{ 31 | */ 32 | 33 | #include "at32f421.h" 34 | 35 | /** @addtogroup AT32F421_system_private_defines 36 | * @{ 37 | */ 38 | #define VECT_TAB_OFFSET 0x0 /*!< vector table base offset field. this value must be a multiple of 0x200. */ 39 | /** 40 | * @} 41 | */ 42 | 43 | /** @addtogroup AT32F421_system_private_variables 44 | * @{ 45 | */ 46 | unsigned int system_core_clock = HICK_VALUE; /*!< system clock frequency (core clock) */ 47 | /** 48 | * @} 49 | */ 50 | 51 | /** @addtogroup AT32F421_system_private_functions 52 | * @{ 53 | */ 54 | 55 | /** 56 | * @brief setup the microcontroller system 57 | * initialize the flash interface. 58 | * @note this function should be used only after reset. 59 | * @param none 60 | * @retval none 61 | */ 62 | void SystemInit (void) 63 | { 64 | /* reset the crm clock configuration to the default reset state(for debug purpose) */ 65 | /* set hicken bit */ 66 | CRM->ctrl_bit.hicken = TRUE; 67 | 68 | /* wait hick stable */ 69 | while(CRM->ctrl_bit.hickstbl != SET); 70 | 71 | /* hick used as system clock */ 72 | CRM->cfg_bit.sclksel = CRM_SCLK_HICK; 73 | 74 | /* wait sclk switch status */ 75 | while(CRM->cfg_bit.sclksts != CRM_SCLK_HICK); 76 | 77 | /* reset hexten, hextbyps, cfden and pllen bits */ 78 | CRM->ctrl &= ~(0x010D0000U); 79 | 80 | /* reset cfg register, include sclk switch, ahbdiv, apb1div, apb2div, adcdiv, 81 | clkout pllrcs, pllhextdiv, pllmult, usbdiv and pllrange bits */ 82 | CRM->cfg = 0; 83 | 84 | /* reset pllfr, pllms, pllns and pllfref bits */ 85 | CRM->pll = (0x00001F10U); 86 | 87 | /* reset clkout[3], usbbufs, hickdiv, clkoutdiv */ 88 | CRM->misc1 = 0x00100000; 89 | 90 | /* disable all interrupts enable and clear pending bits */ 91 | CRM->clkint = 0x009F0000; 92 | 93 | #if defined (AT32F421K8T7) || defined (AT32F421G8U7) || defined (AT32F421K6T7) || \ 94 | defined (AT32F421G6U7) || defined (AT32F421K4T7) || defined (AT32F421G4U7) 95 | REG32(0x40021014) |= 0x00060000; 96 | REG32(0x48000400) &= 0xFFFCFFCF; 97 | REG32(0x48000400) |= 0x00010010; 98 | REG32(0x48000404) &= 0xFFFFFEFB; 99 | REG32(0x48000414) &= 0xFFFFFEFB; 100 | REG32(0x48000414) |= 0x00000004; 101 | #if defined (AT32F421G8U7) || defined (AT32F421G6U7) || defined (AT32F421G4U7) 102 | REG32(0x48000000) &= 0xFC3FFFFF; 103 | REG32(0x48000000) |= 0x01400000; 104 | REG32(0x48000004) &= 0xFFFFE7FF; 105 | REG32(0x48000014) &= 0xFFFFE7FF; 106 | #endif 107 | REG32(0x40021014) &= 0xFFF9FFFF; 108 | #endif 109 | 110 | #ifdef VECT_TAB_SRAM 111 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* vector table relocation in internal sram. */ 112 | #else 113 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* vector table relocation in internal flash. */ 114 | #endif 115 | } 116 | 117 | /** 118 | * @brief update system_core_clock variable according to clock register values. 119 | * the system_core_clock variable contains the core clock (hclk), it can 120 | * be used by the user application to setup the systick timer or configure 121 | * other parameters. 122 | * @param none 123 | * @retval none 124 | */ 125 | void system_core_clock_update(void) 126 | { 127 | uint32_t pll_mult = 0, pll_mult_h = 0, pll_clock_source = 0, temp = 0, div_value = 0; 128 | uint32_t pllrcsfreq = 0, pll_ms = 0, pll_ns = 0, pll_fr = 0; 129 | crm_sclk_type sclk_source; 130 | 131 | static const uint8_t sys_ahb_div_table[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; 132 | 133 | /* get sclk source */ 134 | sclk_source = crm_sysclk_switch_status_get(); 135 | 136 | switch(sclk_source) 137 | { 138 | case CRM_SCLK_HICK: 139 | if(((CRM->misc2_bit.hick_to_sclk) != RESET) && ((CRM->misc1_bit.hickdiv) != RESET)) 140 | system_core_clock = HICK_VALUE * 6; 141 | else 142 | system_core_clock = HICK_VALUE; 143 | break; 144 | case CRM_SCLK_HEXT: 145 | system_core_clock = HEXT_VALUE; 146 | break; 147 | case CRM_SCLK_PLL: 148 | pll_clock_source = CRM->cfg_bit.pllrcs; 149 | if(CRM->pll_bit.pllcfgen == FALSE) 150 | { 151 | /* get multiplication factor */ 152 | pll_mult = CRM->cfg_bit.pllmult_l; 153 | pll_mult_h = CRM->cfg_bit.pllmult_h; 154 | /* process high bits */ 155 | if((pll_mult_h != 0U) || (pll_mult == 15U)){ 156 | pll_mult += ((16U * pll_mult_h) + 1U); 157 | } 158 | else 159 | { 160 | pll_mult += 2U; 161 | } 162 | 163 | if (pll_clock_source == 0x00) 164 | { 165 | /* hick divided by 2 selected as pll clock entry */ 166 | system_core_clock = (HICK_VALUE >> 1) * pll_mult; 167 | } 168 | else 169 | { 170 | /* hext selected as pll clock entry */ 171 | if (CRM->cfg_bit.pllhextdiv != RESET) 172 | { 173 | /* hext clock divided by 2 */ 174 | system_core_clock = (HEXT_VALUE / 2) * pll_mult; 175 | } 176 | else 177 | { 178 | system_core_clock = HEXT_VALUE * pll_mult; 179 | } 180 | } 181 | } 182 | else 183 | { 184 | pll_ms = CRM->pll_bit.pllms; 185 | pll_ns = CRM->pll_bit.pllns; 186 | pll_fr = CRM->pll_bit.pllfr; 187 | 188 | if (pll_clock_source == 0x00) 189 | { 190 | /* hick divided by 2 selected as pll clock entry */ 191 | pllrcsfreq = (HICK_VALUE >> 1); 192 | } 193 | else 194 | { 195 | /* hext selected as pll clock entry */ 196 | if (CRM->cfg_bit.pllhextdiv != RESET) 197 | { 198 | /* hext clock divided by 2 */ 199 | pllrcsfreq = (HEXT_VALUE / 2); 200 | } 201 | else 202 | { 203 | pllrcsfreq = HEXT_VALUE; 204 | } 205 | } 206 | system_core_clock = (uint32_t)(((uint64_t)pllrcsfreq * pll_ns) / (pll_ms * (0x1 << pll_fr))); 207 | } 208 | break; 209 | default: 210 | system_core_clock = HICK_VALUE; 211 | break; 212 | } 213 | 214 | /* compute sclk, ahbclk frequency */ 215 | /* get ahb division */ 216 | temp = CRM->cfg_bit.ahbdiv; 217 | div_value = sys_ahb_div_table[temp]; 218 | /* ahbclk frequency */ 219 | system_core_clock = system_core_clock >> div_value; 220 | } 221 | /** 222 | * @} 223 | */ 224 | 225 | /** 226 | * @} 227 | */ 228 | 229 | /** 230 | * @} 231 | */ 232 | 233 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/stdlib/system_at32f421.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************************************************************** 3 | * @file system_at32f421.h 4 | * @brief cmsis cortex-m4 system header file. 5 | ************************************************************************** 6 | * Copyright notice & Disclaimer 7 | * 8 | * The software Board Support Package (BSP) that is made available to 9 | * download from Artery official website is the copyrighted work of Artery. 10 | * Artery authorizes customers to use, copy, and distribute the BSP 11 | * software and its related documentation for the purpose of design and 12 | * development in conjunction with Artery microcontrollers. Use of the 13 | * software is governed by this copyright notice and the following disclaimer. 14 | * 15 | * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, 16 | * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, 17 | * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR 18 | * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, 19 | * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 21 | * 22 | ************************************************************************** 23 | */ 24 | 25 | #ifndef __SYSTEM_AT32F421_H 26 | #define __SYSTEM_AT32F421_H 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /** @addtogroup CMSIS 33 | * @{ 34 | */ 35 | 36 | /** @addtogroup AT32F421_system 37 | * @{ 38 | */ 39 | 40 | /** @defgroup AT32F421_system_clock_stable_definition 41 | * @{ 42 | */ 43 | 44 | #define HEXT_STABLE_DELAY (5000u) 45 | #define PLL_STABLE_DELAY (500u) 46 | #define SystemCoreClock system_core_clock 47 | 48 | /** 49 | * @} 50 | */ 51 | 52 | /** @defgroup AT32F421_system_exported_variables 53 | * @{ 54 | */ 55 | 56 | extern unsigned int system_core_clock; /*!< system clock frequency (core clock) */ 57 | 58 | /** 59 | * @} 60 | */ 61 | 62 | /** @defgroup AT32F421_system_exported_functions 63 | * @{ 64 | */ 65 | 66 | extern void SystemInit(void); 67 | extern void system_core_clock_update(void); 68 | 69 | /** 70 | * @} 71 | */ 72 | 73 | /** 74 | * @} 75 | */ 76 | 77 | /** 78 | * @} 79 | */ 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/tim.cpp: -------------------------------------------------------------------------------- 1 | #include "tim.h" 2 | #include "at32f421_tmr.h" 3 | 4 | volatile uint32_t sys_ticks; 5 | uint32_t tim6_overflow = 0; 6 | 7 | static Timer timer; 8 | static bool timer_inited = false; 9 | 10 | #define SYSTICK_CLOCK_DIV 8 11 | #define SYSTICK_CLOCK (system_core_clock / SYSTICK_CLOCK_DIV) 12 | 13 | void systick_init(void) 14 | { 15 | SysTick_Config(SYSTICK_CLOCK / 1000); 16 | systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_DIV8); 17 | nvic_irq_enable(SysTick_IRQn, 0, 0); 18 | } 19 | 20 | void tmr6_init(void) 21 | { 22 | crm_periph_clock_enable(CRM_TMR6_PERIPH_CLOCK, TRUE); 23 | tmr_base_init(TMR6, 65535, 119); 24 | tmr_cnt_dir_set(TMR6, TMR_COUNT_UP); 25 | tmr_period_buffer_enable(TMR6, FALSE); 26 | tmr_primary_mode_select(TMR6, TMR_PRIMARY_SEL_OVERFLOW); 27 | tmr_overflow_request_source_set(TMR6, TRUE); 28 | tmr_counter_enable(TMR6, TRUE); 29 | tmr_interrupt_enable(TMR6, TMR_OVF_INT, TRUE); 30 | nvic_irq_enable(TMR6_GLOBAL_IRQn, 0, 0); 31 | } 32 | 33 | void tmr14_init(void) 34 | { 35 | crm_periph_clock_enable(CRM_TMR14_PERIPH_CLOCK, TRUE); 36 | tmr_base_init(TMR14, 99, 119); 37 | tmr_cnt_dir_set(TMR14, TMR_COUNT_UP); 38 | tmr_clock_source_div_set(TMR14, TMR_CLOCK_DIV1); 39 | tmr_period_buffer_enable(TMR14, FALSE); 40 | tmr_overflow_request_source_set(TMR14, TRUE); 41 | tmr_counter_enable(TMR14, TRUE); 42 | tmr_interrupt_enable(TMR14, TMR_OVF_INT, TRUE); 43 | nvic_irq_enable(TMR14_GLOBAL_IRQn, 0, 0); 44 | } 45 | 46 | TimerIf *TimerIf::singleton() 47 | { 48 | if (timer_inited) 49 | return &timer; 50 | timer_inited = true; 51 | systick_init(); 52 | tmr6_init(); 53 | tmr14_init(); 54 | return &timer; 55 | } 56 | 57 | void Timer::delay_us(uint16_t nus) 58 | { 59 | uint16_t te = TMR6->cval + nus; 60 | while (TMR6->cval > te) // te overflowed 61 | { 62 | } 63 | while (TMR6->cval < te) 64 | { 65 | } 66 | } 67 | 68 | void Timer::delay_ms(uint16_t nms) 69 | { 70 | uint32_t stop = sys_ticks + nms; 71 | while (sys_ticks < stop) 72 | { 73 | } 74 | } 75 | 76 | uint32_t Timer::now_ms(void) const 77 | { 78 | return sys_ticks; 79 | } 80 | 81 | uint64_t Timer::now_us(void) const 82 | { 83 | return ((uint64_t)tim6_overflow << 16) + (uint64_t)TMR6->cval; 84 | } 85 | 86 | void Timer::timing_task_10kHz(Task task, void *data) 87 | { 88 | timing_data = data; // must set data before task, or, there is risk that data is not set when task is called by SysTick_Handler 89 | timing_task = task; 90 | } 91 | 92 | extern "C" 93 | { 94 | void SysTick_Handler(void) // 1ms 95 | { 96 | sys_ticks++; 97 | } 98 | void TMR6_GLOBAL_IRQHandler(void) // work as time base 99 | { 100 | TMR6->ists = 0; 101 | tim6_overflow++; 102 | } 103 | void TMR14_GLOBAL_IRQHandler(void) // to exec delay task 104 | { 105 | TMR14->ists = 0; 106 | if (timer.timing_task) 107 | timer.timing_task(timer.timing_data); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/tim.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "msp.h" 4 | 5 | extern "C" 6 | { 7 | void SysTick_Handler(void); 8 | void TMR14_GLOBAL_IRQHandler(void); 9 | } 10 | 11 | class Timer : public TimerIf 12 | { 13 | private: 14 | uint64_t exec_time; 15 | Task delay_task; 16 | Task timing_task; 17 | void *delay_data; 18 | void *timing_data; 19 | 20 | friend void SysTick_Handler(void); 21 | friend void TMR14_GLOBAL_IRQHandler(void); 22 | 23 | public: 24 | Timer() : delay_task(nullptr), timing_task(nullptr) {} 25 | virtual void delay_us(uint16_t nus); 26 | virtual void delay_ms(uint16_t nms); 27 | virtual uint32_t now_ms(void) const; // return current time in ms 28 | virtual uint64_t now_us(void) const; // returncurrent time in us 29 | virtual void timing_task_10kHz(Task task, void *data); // support only one task, so caller make sure that the last task is finished before next calling 30 | }; -------------------------------------------------------------------------------- /src/msp/src/AT32F421/usart.cpp: -------------------------------------------------------------------------------- 1 | #include "usart.h" 2 | #include "gpio.h" 3 | #include "assert.h" 4 | 5 | #define ARRAY_CNT(x) (sizeof(x) / sizeof(x[0])) 6 | 7 | usart_t usart_map[] = { 8 | {USART1, 9 | {PA9, GPIO_MUX_1, DMA1_CHANNEL2}, 10 | {PA10, GPIO_MUX_1, DMA1_CHANNEL3}}, 11 | {USART1, 12 | {PB6, GPIO_MUX_0, DMA1_CHANNEL2}, 13 | {PB7, GPIO_MUX_0, DMA1_CHANNEL3}}, 14 | 15 | {USART2, 16 | {PA2, GPIO_MUX_1, DMA1_CHANNEL4}, 17 | {PA3, GPIO_MUX_1, DMA1_CHANNEL5}}, 18 | {USART2, 19 | {PA8, GPIO_MUX_4, DMA1_CHANNEL4}, 20 | {PB0, GPIO_MUX_3, DMA1_CHANNEL5}}, 21 | {USART2, 22 | {PA14, GPIO_MUX_1, DMA1_CHANNEL4}, 23 | {PA15, GPIO_MUX_1, DMA1_CHANNEL5}}, 24 | }; 25 | 26 | static volatile uint8_t rx_head, rx_tail; 27 | 28 | static void dma_buffer_config(dma_channel_type *dmax_channely, uint32_t memory_base_addr, uint16_t buffer_size) 29 | { 30 | dmax_channely->dtcnt = buffer_size; 31 | dmax_channely->maddr = memory_base_addr; 32 | } 33 | 34 | int dma_config(usart_t *usart) 35 | { 36 | usart_type *usart_regs = usart->regs; 37 | dma_init_type dma_init_struct; 38 | dma_default_para_init(&dma_init_struct); 39 | crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE); 40 | 41 | usart_dma_transmitter_enable(usart_regs, TRUE); 42 | usart_dma_receiver_enable(usart_regs, TRUE); 43 | 44 | dma_reset(usart->tx.dma_channel); 45 | dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL; 46 | dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; 47 | dma_init_struct.memory_inc_enable = TRUE; 48 | dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; 49 | dma_init_struct.peripheral_inc_enable = FALSE; 50 | dma_init_struct.priority = DMA_PRIORITY_LOW; 51 | dma_init_struct.loop_mode_enable = FALSE; 52 | dma_init(usart->tx.dma_channel, &dma_init_struct); 53 | 54 | dma_reset(usart->rx.dma_channel); 55 | dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY; 56 | dma_init_struct.loop_mode_enable = TRUE; 57 | dma_init(usart->rx.dma_channel, &dma_init_struct); 58 | 59 | return 0; 60 | } 61 | 62 | enum UsartMode 63 | { 64 | TX_ONLY, 65 | RX_ONLY, 66 | FULL_DUPLEX, 67 | HALF_DUPLEX 68 | }; 69 | 70 | static void usart_config(usart_t *usart_cfg, uint32_t baud, UsartMode mode, float stopbit) 71 | { 72 | usart_type *regs = usart_cfg->regs; 73 | 74 | switch ((uint32_t)regs) 75 | { 76 | case USART1_BASE: 77 | crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE); 78 | break; 79 | case USART2_BASE: 80 | crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, TRUE); 81 | break; 82 | default: 83 | assert(false); 84 | break; 85 | } 86 | 87 | usart_stop_bit_num_type stop; 88 | if (stopbit < 1) 89 | stop = USART_STOP_0_5_BIT; 90 | else if (stopbit == 1) 91 | stop = USART_STOP_1_BIT; 92 | else if (stopbit < 2) 93 | stop = USART_STOP_1_5_BIT; 94 | else 95 | stop = USART_STOP_2_BIT; 96 | 97 | /* configure param */ 98 | usart_init(regs, baud, USART_DATA_8BITS, stop); 99 | 100 | switch (mode) 101 | { 102 | case TX_ONLY: // tx only 103 | Gpio::setup_af(usart_cfg->tx.pin, Gpio::AF_OUTPUT_PP, usart_cfg->tx.af); 104 | usart_transmitter_enable(regs, TRUE); 105 | break; 106 | case RX_ONLY: // rx only 107 | usart_receiver_enable(regs, TRUE); 108 | Gpio::setup_af(usart_cfg->rx.pin, Gpio::AF_INPUT_PU, usart_cfg->rx.af); 109 | /* code */ 110 | break; 111 | case FULL_DUPLEX: // full duplex 112 | Gpio::setup_af(usart_cfg->tx.pin, Gpio::AF_OUTPUT_PP, usart_cfg->tx.af); 113 | Gpio::setup_af(usart_cfg->rx.pin, Gpio::AF_INPUT_PU, usart_cfg->rx.af); 114 | usart_transmitter_enable(regs, TRUE); 115 | usart_receiver_enable(regs, TRUE); 116 | /* code */ 117 | break; 118 | case HALF_DUPLEX: // half duplex 119 | Gpio::setup_af(usart_cfg->tx.pin, Gpio::AF_OUTPUT_OD, usart_cfg->tx.af); // need external pull up resistance 120 | usart_transmitter_enable(regs, TRUE); 121 | usart_receiver_enable(regs, TRUE); 122 | usart_single_line_halfduplex_select(regs, TRUE); 123 | break; 124 | 125 | default: 126 | break; 127 | } 128 | 129 | usart_parity_selection_config(regs, USART_PARITY_NONE); 130 | usart_interrupt_enable(regs, USART_RDBF_INT, TRUE); 131 | usart_enable(regs, TRUE); 132 | } 133 | 134 | UsartIf *UsartIf::new_instance(Pin tx_pin, Pin rx_pin, uint32_t baud, float stopbit) 135 | { 136 | UsartMode mode = FULL_DUPLEX; 137 | assert(tx_pin != PIN_NONE || rx_pin != PIN_NONE); 138 | if (tx_pin == rx_pin) 139 | mode = HALF_DUPLEX; 140 | if (tx_pin == PIN_NONE && rx_pin != PIN_NONE) 141 | mode = RX_ONLY; 142 | if (rx_pin == PIN_NONE && tx_pin != PIN_NONE) 143 | mode = TX_ONLY; 144 | 145 | uint8_t iter; 146 | for (iter = 0; iter < ARRAY_CNT(usart_map); iter++) 147 | { 148 | if ((mode == HALF_DUPLEX || mode == TX_ONLY) && usart_map[iter].tx.pin == tx_pin) 149 | break; 150 | if (mode == RX_ONLY && usart_map[iter].rx.pin == rx_pin) 151 | break; 152 | if (mode == FULL_DUPLEX && usart_map[iter].tx.pin == tx_pin && usart_map[iter].rx.pin == rx_pin) 153 | break; 154 | } 155 | if (iter == ARRAY_CNT(usart_map)) 156 | return nullptr; 157 | 158 | usart_config(&usart_map[iter], baud, mode, stopbit); 159 | dma_config(&usart_map[iter]); 160 | usart_map[iter].tx.dma_channel->paddr = (uint32_t)&usart_map[iter].regs->dt; 161 | usart_map[iter].rx.dma_channel->paddr = (uint32_t)&usart_map[iter].regs->dt; 162 | return new Usart(&usart_map[iter]); 163 | } 164 | 165 | int Usart::async_send(const uint8_t *data, int dsz) 166 | { 167 | assert(dsz); 168 | dma_channel_type *dma = handle->tx.dma_channel; 169 | if (!data) 170 | return dsz - dma->dtcnt; 171 | dma->ctrl_bit.chen = 0; 172 | dma_buffer_config(dma, (uint32_t)data, dsz); 173 | dma->ctrl_bit.chen = 1; 174 | return 0; 175 | } 176 | 177 | void Usart::sync_send(const uint8_t *data, int dsz) 178 | { 179 | async_send(data, dsz); 180 | while (dma_data_number_get(handle->tx.dma_channel) != 0) 181 | { 182 | } // wait for transmission 183 | } 184 | 185 | // return the data size already recieved by set buf = NULL 186 | int Usart::async_recv(uint8_t *buf, int bsz) 187 | { 188 | assert(bsz); 189 | 190 | dma_channel_type *dma = handle->rx.dma_channel; 191 | if (!buf) 192 | return bsz - dma->dtcnt; 193 | 194 | dma->ctrl_bit.chen = 0; 195 | dma_buffer_config(dma, (uint32_t)buf, bsz); 196 | dma->ctrl_bit.chen = 1; 197 | return 0; 198 | } 199 | -------------------------------------------------------------------------------- /src/msp/src/AT32F421/usart.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "msp.h" 5 | #include "at32f421_usart.h" 6 | 7 | typedef struct 8 | { 9 | Pin pin; 10 | gpio_mux_sel_type af; 11 | dma_channel_type *dma_channel; 12 | } usart_pin; 13 | 14 | typedef struct 15 | { 16 | usart_type *regs; 17 | usart_pin tx; 18 | usart_pin rx; 19 | 20 | } usart_t; 21 | 22 | class Usart : public UsartIf 23 | { 24 | private: 25 | usart_t *handle; 26 | 27 | public: 28 | Usart(usart_t *handle) : handle(handle){}; 29 | virtual int async_send(const uint8_t *data, int dsz); 30 | virtual void sync_send(const uint8_t *data, int dsz); 31 | virtual int async_recv(uint8_t *buf, int bsz); 32 | }; -------------------------------------------------------------------------------- /src/msp/src/cm4/arm_const_structs.h: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------- 2 | * Project: CMSIS DSP Library 3 | * Title: arm_const_structs.h 4 | * Description: Constant structs that are initialized for user convenience. 5 | * For example, some can be given as arguments to the arm_cfft_f32() function. 6 | * 7 | * $Date: 27. January 2017 8 | * $Revision: V.1.5.1 9 | * 10 | * Target Processor: Cortex-M cores 11 | * -------------------------------------------------------------------- */ 12 | /* 13 | * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved. 14 | * 15 | * SPDX-License-Identifier: Apache-2.0 16 | * 17 | * Licensed under the Apache License, Version 2.0 (the License); you may 18 | * not use this file except in compliance with the License. 19 | * You may obtain a copy of the License at 20 | * 21 | * www.apache.org/licenses/LICENSE-2.0 22 | * 23 | * Unless required by applicable law or agreed to in writing, software 24 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 25 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 | * See the License for the specific language governing permissions and 27 | * limitations under the License. 28 | */ 29 | 30 | #ifndef _ARM_CONST_STRUCTS_H 31 | #define _ARM_CONST_STRUCTS_H 32 | 33 | #include "arm_math.h" 34 | #include "arm_common_tables.h" 35 | 36 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len16; 37 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len32; 38 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len64; 39 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len128; 40 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len256; 41 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len512; 42 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len1024; 43 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len2048; 44 | extern const arm_cfft_instance_f64 arm_cfft_sR_f64_len4096; 45 | 46 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16; 47 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32; 48 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64; 49 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128; 50 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256; 51 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512; 52 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; 53 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048; 54 | extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096; 55 | 56 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16; 57 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32; 58 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64; 59 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128; 60 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256; 61 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512; 62 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024; 63 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048; 64 | extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096; 65 | 66 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16; 67 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32; 68 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64; 69 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128; 70 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256; 71 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512; 72 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024; 73 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048; 74 | extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/msp/src/cm4/cmsis_version.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * @file cmsis_version.h 3 | * @brief CMSIS Core(M) Version definitions 4 | * @version V5.0.4 5 | * @date 23. July 2019 6 | ******************************************************************************/ 7 | /* 8 | * Copyright (c) 2009-2019 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 ( 4U) /*!< [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 | -------------------------------------------------------------------------------- /src/protocol/protocol.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "msp.h" 3 | #include "config.h" 4 | 5 | class Protocol 6 | { 7 | public: 8 | enum Type 9 | { 10 | BRUSHED, 11 | STD_PWM, 12 | ONESHOT, // oneshot125 oneshot42 multishot 13 | DSHOT, // dshot 150 300 600,bi-direction dshot 14 | PROSHOT, 15 | SERIAL, 16 | }; 17 | virtual ~Protocol() {} 18 | // the callback should copy the package(including the str), then process it outside the callback, warning: don't make the callback take too long 19 | virtual void poll(void) = 0; 20 | virtual bool signal_lost() = 0; // return if the input signal is lost or mismatch 21 | static Protocol *singleton(Type type, Pin pin); 22 | static Type auto_detect(Pin pin); 23 | }; -------------------------------------------------------------------------------- /src/protocol/src/dshot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "msp.h" 3 | #include "protocol.h" 4 | 5 | // Dshot must be singleton 6 | class Dshot : public Protocol 7 | { 8 | private: 9 | public: 10 | Dshot(); 11 | virtual ~Dshot(); 12 | virtual void poll(void); 13 | virtual bool signal_lost(); 14 | 15 | void bind(Pin pin); 16 | void release(void); 17 | }; -------------------------------------------------------------------------------- /src/protocol/src/oneshot.cpp: -------------------------------------------------------------------------------- 1 | #include "oneshot.h" 2 | #include "stdio.h" 3 | #include "motor.h" 4 | 5 | static volatile int pulse = 0; 6 | static SignalPwmIf *pwm = nullptr; 7 | static uint32_t frame_err = 0; 8 | static int min_pulse; 9 | static int max_pulse; 10 | static TimerIf *timer; 11 | static uint32_t run_time = 0; 12 | static bool data_updated = false; 13 | static int valid_low = 0; 14 | static int valid_high = 0; 15 | 16 | extern int throttle; 17 | extern MotorIf *motor; 18 | 19 | #define ARRAY_SZ(x) (sizeof(x) / sizeof(x[0])) 20 | #define DEAD_AREA 50 21 | 22 | Oneshot::Oneshot() 23 | { 24 | timer = TimerIf::singleton(); 25 | } 26 | 27 | Oneshot::~Oneshot() 28 | { 29 | } 30 | 31 | void Oneshot::poll(void) 32 | { 33 | uint32_t now = timer->now_ms(); 34 | if (now > run_time) 35 | { 36 | run_time = now + 10; 37 | frame_err += 10; 38 | 39 | if (data_updated && throttle < DEAD_AREA && throttle > -DEAD_AREA) 40 | motor->arm(true); 41 | } 42 | } 43 | 44 | bool Oneshot::signal_lost() 45 | { 46 | bool res = frame_err > 50; 47 | if (res) 48 | { 49 | motor->arm(false); 50 | pwm->set_up_pulse_callback(nullptr); 51 | valid_low = valid_high = 0; 52 | } 53 | return res; 54 | } 55 | 56 | int calc_average(int data) 57 | { 58 | static uint32_t sum = 0; 59 | static uint32_t i = 0; 60 | static uint32_t buf[64] = {0}; 61 | sum = sum + data - buf[i]; 62 | buf[i++] = data; 63 | if (i >= ARRAY_SZ(buf)) 64 | i = 0; 65 | return sum / ARRAY_SZ(buf); 66 | } 67 | 68 | void calibrate_shot(uint32_t low, uint32_t high) 69 | { 70 | max_pulse = high; 71 | min_pulse = low; 72 | valid_high = high * 1.05f; 73 | valid_low = low * 0.95f; 74 | uint32_t tmp_min; 75 | uint32_t tmp_max; 76 | int mid_v = (int)(high + low) / 2; 77 | if (config.mode_3d) 78 | mid_v = (int)(high + low) * 3 / 4; 79 | 80 | if (pulse < mid_v) 81 | return; 82 | 83 | uint32_t last_time = timer->now_ms(); 84 | uint32_t run_time = 0; 85 | uint32_t second = 0; 86 | printf("throttle calibration start\n"); 87 | timer->delay_ms(10); 88 | printf("sampling max throttle\n"); 89 | while (1) 90 | { 91 | uint32_t now = timer->now_ms(); 92 | if (run_time != now) 93 | { // 1ms per loop 94 | run_time = now; 95 | tmp_max = calc_average(pulse); 96 | if (now - last_time < 200) 97 | motor->beep(TONE5, MotorIf::VOLUME_HIGH); // beep on 98 | else 99 | motor->beep(TONE5, MotorIf::VOLUME_OFF); 100 | ; // beep off 101 | if (now - last_time >= 1000) 102 | { 103 | second++; 104 | last_time = now; 105 | } 106 | if (second >= 3) 107 | break; 108 | } 109 | } 110 | for (uint32_t i = 0; i < 3; i++) 111 | { 112 | motor->beep(TONE2, MotorIf::VOLUME_LOW); 113 | timer->delay_ms(200); 114 | motor->beep(TONE3, MotorIf::VOLUME_LOW); 115 | timer->delay_ms(200); 116 | motor->beep(TONE4, MotorIf::VOLUME_LOW); 117 | timer->delay_ms(200); 118 | motor->beep(TONE5, MotorIf::VOLUME_LOW); 119 | timer->delay_ms(200); 120 | motor->beep(TONE5, MotorIf::VOLUME_OFF); 121 | timer->delay_ms(200); 122 | // four up tone beep 123 | } 124 | printf("max throttle saved, wait for throttle low\n"); 125 | timer->delay_ms(10); 126 | while (pulse > mid_v) 127 | { 128 | } 129 | printf("sampling min throttle\n"); 130 | last_time = timer->now_ms(); 131 | run_time = 0; 132 | second = 0; 133 | while (1) 134 | { 135 | uint32_t now = timer->now_ms(); 136 | if (run_time != now) 137 | { // 1ms per loop 138 | run_time = now; 139 | tmp_min = calc_average(pulse); 140 | if (now - last_time < 200) 141 | motor->beep(TONE2, MotorIf::VOLUME_LOW); // beep on 142 | else if (now - last_time < 300) 143 | motor->beep(TONE2, MotorIf::VOLUME_OFF); // beep off 144 | else if (now - last_time < 500) 145 | motor->beep(TONE2, MotorIf::VOLUME_LOW); // beep on 146 | else 147 | motor->beep(TONE2, MotorIf::VOLUME_OFF); // beep off 148 | if (now - last_time >= 1000) 149 | { 150 | second++; 151 | last_time = now; 152 | } 153 | if (second >= 3) 154 | break; 155 | } 156 | } 157 | printf("min throttle saved, ready to start or reboot\n"); 158 | timer->delay_ms(10); 159 | for (uint32_t i = 0; i < 3; i++) 160 | { 161 | motor->beep(TONE5, MotorIf::VOLUME_LOW); 162 | timer->delay_ms(200); 163 | motor->beep(TONE3, MotorIf::VOLUME_LOW); 164 | timer->delay_ms(200); 165 | motor->beep(TONE4, MotorIf::VOLUME_LOW); 166 | timer->delay_ms(200); 167 | motor->beep(TONE2, MotorIf::VOLUME_LOW); 168 | timer->delay_ms(200); 169 | motor->beep(TONE2, MotorIf::VOLUME_OFF); 170 | timer->delay_ms(200); 171 | // four up tone beep 172 | } 173 | printf("min throttle saved, ready to arm and start or reboot\n"); 174 | timer->delay_ms(10); 175 | 176 | max_pulse = tmp_max; 177 | min_pulse = tmp_min; 178 | valid_high = max_pulse * 1.01f; 179 | valid_low = min_pulse * 0.99f; 180 | } 181 | 182 | void calibration(void) 183 | { 184 | uint32_t timeout = timer->now_ms() + 1000; 185 | timer->delay_ms(10); 186 | while (pulse < 4500) 187 | { 188 | if (timer->now_ms() > timeout) 189 | return; 190 | } 191 | 192 | if (pulse < 30000) 193 | { // multishot 194 | calibrate_shot(config.multishot_min, config.multishot_max); 195 | config.multishot_max = max_pulse; 196 | config.multishot_min = min_pulse; 197 | return; 198 | } 199 | if (pulse < 37000) 200 | { 201 | frame_err++; 202 | return; 203 | } 204 | if (pulse < 89000) 205 | { // onshot42 206 | calibrate_shot(config.oneshot42_min, config.oneshot42_max); 207 | config.oneshot42_max = max_pulse; 208 | config.oneshot42_min = min_pulse; 209 | return; 210 | } 211 | if (pulse < 115000) 212 | { 213 | frame_err++; 214 | return; 215 | } 216 | if (pulse < 260000) 217 | { // oneshot125 218 | calibrate_shot(config.oneshot125_min, config.oneshot125_max); 219 | config.oneshot125_max = max_pulse; 220 | config.oneshot125_min = min_pulse; 221 | return; 222 | } 223 | if (pulse < 950000) 224 | { 225 | frame_err++; 226 | return; 227 | } 228 | if (pulse < 2050000) 229 | { // std pwm 230 | calibrate_shot(config.pwm_min, config.pwm_max); 231 | config.pwm_max = max_pulse; 232 | config.pwm_min = min_pulse; 233 | return; 234 | } 235 | } 236 | 237 | void Oneshot::bind(Pin pin) 238 | { 239 | pulse = 0; 240 | pwm = SignalPwmIf::new_instance(pin); 241 | pwm->set_mode(SignalPwmIf::UP_PULSE_CAPTURE); // measuring range: 4ms 242 | pwm->set_up_pulse_callback( 243 | [](uint32_t p) 244 | { 245 | pulse = p; 246 | if (pulse < valid_low) 247 | { 248 | frame_err++; 249 | return; 250 | } 251 | 252 | if (pulse > valid_high) 253 | { 254 | frame_err++; 255 | return; 256 | } 257 | 258 | data_updated = true; 259 | frame_err = 0; 260 | if (pulse < min_pulse) 261 | pulse = min_pulse; 262 | if (pulse > max_pulse) 263 | pulse = max_pulse; 264 | 265 | throttle = (pulse - min_pulse) * 2000 / (max_pulse - min_pulse); 266 | 267 | if (config.mode_3d) 268 | { 269 | throttle = (throttle - 1000) * 2; 270 | } 271 | 272 | if (throttle < DEAD_AREA && throttle > -DEAD_AREA) // dead area 273 | throttle = 0; 274 | 275 | if (config.spin_dir_reverse) 276 | throttle = -throttle; 277 | motor->set_throttle(throttle); 278 | }); 279 | calibration(); 280 | config.save(); 281 | printf("max pulse: %d min pulse: %d\n", max_pulse, min_pulse); 282 | timer->delay_ms(10); 283 | } 284 | 285 | void Oneshot::release(void) 286 | { 287 | delete pwm; 288 | pwm = nullptr; 289 | } -------------------------------------------------------------------------------- /src/protocol/src/oneshot.h: -------------------------------------------------------------------------------- 1 | #include "protocol.h" 2 | 3 | class Oneshot : public Protocol 4 | { 5 | public: 6 | Oneshot(); 7 | ~Oneshot(); 8 | virtual void poll(void); 9 | virtual bool signal_lost(); // return if the input signal is lost or mismatch 10 | 11 | void bind(Pin pin); 12 | void release(void); 13 | }; -------------------------------------------------------------------------------- /src/protocol/src/protocol.cpp: -------------------------------------------------------------------------------- 1 | #include "protocol.h" 2 | #include "serial.h" 3 | #include "dshot.h" 4 | #include "oneshot.h" 5 | 6 | #include 7 | #include "string.h" 8 | 9 | #ifndef NDEBUG 10 | static Serial *serial = nullptr; 11 | #endif 12 | static Dshot *dshot = nullptr; 13 | static Oneshot *oneshot = nullptr; 14 | 15 | static void reset_protocol(void) 16 | { 17 | if (dshot) 18 | dshot->release(); 19 | if (oneshot) 20 | oneshot->release(); 21 | } 22 | 23 | volatile uint32_t pulse_cnt = 0; 24 | static uint32_t pulses[16] = {0}; // unit ns 25 | #define ARRAY_SZ(x) (sizeof(x) / sizeof(x[0])) 26 | Protocol::Type Protocol::auto_detect(Pin pin) 27 | { 28 | TimerIf *timer = TimerIf::singleton(); 29 | reset_protocol(); 30 | SignalPwmIf *pwm = SignalPwmIf::new_instance(pin); 31 | pwm->set_mode(SignalPwmIf::UP_PULSE_CAPTURE); // measuring range: 4ms 32 | timer->delay_ms(5); // necessary delay 33 | pwm->set_up_pulse_callback( 34 | [](uint32_t p) 35 | { 36 | if (pulse_cnt < ARRAY_SZ(pulses)) 37 | pulses[pulse_cnt++] = p; 38 | }); 39 | Protocol::Type type = BRUSHED; 40 | Protocol::Type last_type = BRUSHED; 41 | uint32_t type_cnt = 1; 42 | REPEAT: 43 | while (1) 44 | { 45 | pulse_cnt = 0; 46 | uint32_t start; 47 | uint32_t period[4] = {0}; // unit us 48 | while (pulse_cnt < 1) 49 | ; 50 | start = timer->now_us(); 51 | while (pulse_cnt < 2) 52 | ; 53 | period[0] = timer->now_us() - start; 54 | while (pulse_cnt < 3) 55 | ; 56 | period[1] = timer->now_us() - start - period[0]; 57 | while (pulse_cnt < 8) 58 | ; 59 | period[2] = timer->now_us() - start; 60 | while (pulse_cnt < 15) 61 | ; 62 | period[3] = timer->now_us() - start - period[2]; 63 | 64 | if (period[0] < 10 || period[1] < 10) 65 | { 66 | uint32_t min = period[0] > period[1] ? period[1] : period[0]; 67 | type = DSHOT; 68 | if (period[2] > min * 7 + 10 && period[3] > min * 7 + 10) 69 | type = PROSHOT; 70 | break; 71 | } 72 | 73 | if (pulses[0] > 6 * (period[0] * 1000 - pulses[0])) // SERIAL send 1s to shake hands 74 | { 75 | type = SERIAL; 76 | break; 77 | } 78 | 79 | if ((pulses[0] < 270000 && pulses[0] > 4500) || 80 | (pulses[1] < 270000 && pulses[1] > 4500)) 81 | { 82 | type = ONESHOT; 83 | break; 84 | } 85 | 86 | if ((pulses[0] > 950000 && pulses[0] < 2050000) || 87 | (pulses[1] > 950000 && pulses[1] < 2050000)) 88 | { 89 | type = STD_PWM; 90 | break; 91 | } 92 | 93 | if ((pulses[0] < 700000 && pulses[0] > 300000) || 94 | (pulses[1] < 700000 && pulses[1] > 300000)) 95 | { 96 | type = BRUSHED; 97 | break; 98 | } 99 | } 100 | 101 | if (type == last_type) 102 | type_cnt++; 103 | else 104 | type_cnt = 1; 105 | last_type = type; 106 | if (type_cnt < 3) // if the detected protocol is the same 3 times continuously, then the protocol is comformed 107 | goto REPEAT; 108 | 109 | delete pwm; 110 | return type; 111 | } 112 | 113 | Protocol *Protocol::singleton(Type type, Pin pin) 114 | { 115 | switch (type) 116 | { 117 | #ifndef NDEBUG 118 | case SERIAL: 119 | if (serial) 120 | return serial; 121 | return serial = new Serial(); 122 | break; 123 | #endif 124 | case DSHOT: 125 | if (!dshot) 126 | dshot = new Dshot(); 127 | dshot->release(); 128 | dshot->bind(pin); 129 | return dshot; 130 | case BRUSHED: 131 | break; 132 | case STD_PWM: 133 | case ONESHOT: 134 | if (!oneshot) 135 | oneshot = new Oneshot(); 136 | oneshot->release(); 137 | oneshot->bind(pin); 138 | return oneshot; 139 | break; 140 | case PROSHOT: 141 | break; 142 | 143 | default: // AUTO_DETECT 144 | break; 145 | } 146 | // assert(false); 147 | return nullptr; 148 | } -------------------------------------------------------------------------------- /src/protocol/src/serial.cpp: -------------------------------------------------------------------------------- 1 | #include "serial.h" 2 | #include "string.h" 3 | #include "stdlib.h" 4 | #include "motor.h" 5 | 6 | #ifndef NDEBUG 7 | 8 | extern UsartIf *debug_usart; 9 | extern MotorIf *motor; 10 | 11 | Serial::Serial() 12 | { 13 | timer = TimerIf::singleton(); 14 | run_time = 0; 15 | restart(); 16 | } 17 | 18 | Serial::~Serial() 19 | { 20 | } 21 | 22 | void Serial::restart(void) 23 | { 24 | state = SYNC; 25 | process_idx = rd_sz = 0; 26 | debug_usart->async_recv(rx_buf, sizeof(rx_buf)); 27 | } 28 | 29 | #define STR_CMP(x, y) strncmp(x, y, sizeof(y) - 1) 30 | 31 | void Serial::proccess(void) 32 | { 33 | if (process_idx == rd_sz) 34 | return; 35 | 36 | process_idx++; 37 | 38 | if (process_idx > 2) 39 | { 40 | if (rx_buf[process_idx - 2] == '\r' && rx_buf[process_idx - 1] == '\n') 41 | { 42 | rx_buf[process_idx - 2] = 0; 43 | char *p = (char *)rx_buf; 44 | if (STR_CMP((char *)rx_buf, "throttle ") == 0) 45 | { 46 | p += 9; 47 | int value = strtol(p, nullptr, 10); 48 | motor->set_throttle(value); 49 | } 50 | if (STR_CMP((char *)rx_buf, "arm") == 0) 51 | { 52 | motor->arm(true); 53 | } 54 | restart(); 55 | } 56 | else if (process_idx == sizeof(rx_buf) / sizeof(rx_buf[0])) 57 | restart(); 58 | } 59 | } 60 | 61 | void Serial::poll(void) 62 | { 63 | proccess(); // one byte once to avoid long time cpu occupation 64 | uint32_t now = timer->now_ms(); 65 | if (now < run_time) 66 | return; 67 | run_time = now + 1; // baudrate > 9600 required 68 | int rd_sz = debug_usart->async_recv(nullptr, sizeof(rx_buf)); 69 | if (rd_sz == 0) 70 | return; 71 | if (rd_sz == this->rd_sz && process_idx == rd_sz) 72 | { // no byte received over 1ms, so restart frame 73 | restart(); 74 | return; 75 | } 76 | this->rd_sz = rd_sz; 77 | } 78 | 79 | bool Serial::signal_lost() 80 | { // serial proto is for debug, so never timeout 81 | return false; 82 | } 83 | 84 | #endif -------------------------------------------------------------------------------- /src/protocol/src/serial.h: -------------------------------------------------------------------------------- 1 | 2 | #include "protocol.h" 3 | #include "msp.h" 4 | 5 | class Serial : public Protocol 6 | { 7 | private: 8 | enum State 9 | { 10 | SYNC, 11 | CMD, 12 | DATA_LENGTH, 13 | DATA, 14 | CRC, 15 | }; 16 | TimerIf *timer; 17 | uint32_t run_time; 18 | uint8_t rx_buf[64]; 19 | int state; 20 | int process_idx; 21 | int rd_sz; 22 | uint8_t crc_sum; 23 | void restart(void); 24 | void proccess(void); 25 | 26 | public: 27 | Serial(); 28 | virtual ~Serial(); 29 | virtual void poll(void); 30 | virtual bool signal_lost(); 31 | }; --------------------------------------------------------------------------------