diff --git a/firmware/Makefile b/firmware/Make_avr similarity index 97% rename from firmware/Makefile rename to firmware/Make_avr index 0929d5a..ad3a34b 100644 --- a/firmware/Makefile +++ b/firmware/Make_avr @@ -13,7 +13,7 @@ PROJ = avr_kazzo #SOURCES=$(wildcard source/**/*.c source/*.c) SOURCES=$(wildcard source/*.c) -CFLAGS = -Iusbdrv_Vusb -Isource -DDEBUG_LEVEL=0 +CFLAGS = -Iusbdrv_Vusb -Isource -DDEBUG_LEVEL=0 -DAVR_CORE USBOBJ = usbdrv_Vusb/usbdrv.o usbdrv_Vusb/usbdrvasm.o usbdrv_Vusb/oddebug.o OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) $(USBOBJ) diff --git a/firmware/Make_stm b/firmware/Make_stm new file mode 100644 index 0000000..b5c3338 --- /dev/null +++ b/firmware/Make_stm @@ -0,0 +1,100 @@ + +#Build directory +BUILD = build_stm + +#project name +#doesn't need to be associated with any file names +PROJ = inlretro_stm + + +# Selecting Core +CORTEX_M=0 + +# Use newlib-nano. To disable it, specify USE_NANO= +#USE_NANO=--specs=nano.specs +USE_NANO= + +# Use seimhosting or not +USE_SEMIHOST=--specs=rdimon.specs +USE_NOHOST=--specs=nosys.specs + +CORE=CM$(CORTEX_M) +BASE=. + +# Compiler & Linker +CC=arm-none-eabi-gcc +CXX=arm-none-eabi-g++ +OBJCOPY=arm-none-eabi-objcopy +SIZE=arm-none-eabi-size + +# Options for specific architecture +ARCH_FLAGS=-mthumb -mcpu=cortex-m$(CORTEX_M) + +# Startup code +STARTUP=$(BASE)/include_stm/startup_ARM$(CORE).S + +# -Os -flto -ffunction-sections -fdata-sections to compile for code size +CFLAGS=$(ARCH_FLAGS) $(STARTUP_DEFS) -Os -flto -ffunction-sections -fdata-sections -g +CXXFLAGS=$(CFLAGS) + +# Link for code size +GC=-Wl,--gc-sections + +# Create map file +MAP=-Wl,-Map=$(BUILD)/$(PROJ).map + +STARTUP_DEFS=-D__STARTUP_CLEAR_BSS -D__START=main -D__NO_SYSTEM_INIT + +LDSCRIPTS=-L. -L$(BASE)/include_stm -T nokeep.ld +LFLAGS=$(USE_NANO) $(USE_NOHOST) $(LDSCRIPTS) $(GC) $(MAP) + +DEFINE+=\ + -DSTM32F070xB \ + -DF_CPU=16000000 \ + -DSTM_CORE +#128KB version of all packages (LQFP-48,64,100) + +# -DSTM32F072x8 \ #64KB version of all packages (LQFP-48,64,100) +# -DSTM32F070xB \ #128KB version of both packages (LQFP-48,64) +# -DSTM32F070x6 \ #32KB version of both packages (TSSOP-20,LQFP-48) +# -DF_CPU=8000000 +INCLUDE=-I ./include_stm +CFLAGS+= $(DEFINE) $(INCLUDE) + +#SOURCES=$(wildcard source/**/*.c source/*.c) +SOURCES=$(wildcard source/*.c source_stm_only/*.c) +OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) + +#all: dir $(BUILD)/$(PROJ).axf $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size +all: dir $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size + +#build axf file output (basically elf with DWARF debug info) +# $@ is shortcut for the target, $^ is shortcut for prereqs +# TARGET: PREREQS +$(BUILD)/$(PROJ).axf: $(STARTUP) $(OBJECTS) + $(CC) $^ $(CFLAGS) $(LFLAGS) -o $@ + +$(BUILD)/$(PROJ).elf: $(STARTUP) $(OBJECTS) + $(CC) $^ $(CFLAGS) $(LFLAGS) -o $@ + +$(BUILD)/$(PROJ).hex: $(BUILD)/$(PROJ).elf + $(OBJCOPY) -O ihex $^ $@ + +$(BUILD)/$(PROJ).bin: $(BUILD)/$(PROJ).elf + $(OBJCOPY) -O binary $^ $@ + +dir: + mkdir -p $(BUILD) + +size: $(BUILD)/$(PROJ).elf + $(SIZE) -t $^ + +program: all + ST-LINK_CLI.exe -c -P $(BUILD)\$(PROJ).hex 0x08000000 -Rst + +disassm: all + arm-none-eabi-objdump $(BUILD)\$(PROJ).elf -d -g + +clean: + rm -rf $(BUILD) + rm -f $(OBJECTS) diff --git a/firmware/Makefile.avr b/firmware/Makefile.avr deleted file mode 100644 index 0929d5a..0000000 --- a/firmware/Makefile.avr +++ /dev/null @@ -1,79 +0,0 @@ -# Name: Makefile -# Project: custom-class example -# Author: Christian Starkjohann -# Creation Date: 2008-04-07 -# Tabsize: 4 -# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH -# License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - -DEVICE = atmega164a -F_CPU = 16000000 # in Hz -PROJ = avr_kazzo -# Fuses and ISP programming handled in bootloader firmware build - -#SOURCES=$(wildcard source/**/*.c source/*.c) -SOURCES=$(wildcard source/*.c) -CFLAGS = -Iusbdrv_Vusb -Isource -DDEBUG_LEVEL=0 -USBOBJ = usbdrv_Vusb/usbdrv.o usbdrv_Vusb/usbdrvasm.o usbdrv_Vusb/oddebug.o -OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) $(USBOBJ) - -COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE) - -# symbolic targets: -help: - @echo "This Makefile has no default rule. Use one of the following:" - @echo "make hex ............ to build $(PROJ).hex" - @echo "make program ........ windows flash firmware via bootloader" - @echo "make program_unix ... unix flash firmware via bootloader" - @echo "make clean .......... to delete objects and hex file" - -hex: $(PROJ).hex - -program: $(PROJ).hex - ../bootloader/commandline/bootloadHID.exe -r $< - -program_unix: $(PROJ).hex - ../bootloader/commandline/bootloadHID -r $< - -# rule for deleting dependent files (those which can be built by Make): -clean: - rm -f $(PROJ).hex $(PROJ).lst $(PROJ).obj $(PROJ).cof $(PROJ).list $(PROJ).map $(PROJ).eep.hex $(PROJ).elf $(OBJECTS) $(PROJ).s usbdrv_Vusb/oddebug.s usbdrv_Vusb/usbdrv.s source/shared_* - -# Generic rule for compiling C files: -.c.o: - $(COMPILE) -c $< -o $@ - -# Generic rule for assembling Assembler source files: -.S.o: - $(COMPILE) -x assembler-with-cpp -c $< -o $@ -# "-x assembler-with-cpp" should not be necessary since this is the default -# file type for the .S (with capital S) extension. However, upper case -# characters are not always preserved on Windows. To ensure WinAVR -# compatibility define the file type manually. - -# Generic rule for compiling C to assembler, used for debugging only. -.c.s: - $(COMPILE) -S $< -o $@ - -# file targets: - -$(PROJ).elf: shared $(OBJECTS) - $(COMPILE) -o $(PROJ).elf $(OBJECTS) - -$(PROJ).hex: $(PROJ).elf - rm -f $(PROJ).hex $(PROJ).eep.hex - avr-objcopy -j .text -j .data -O ihex $(PROJ).elf $(PROJ).hex -# avr-size -C --mcu=${DEVICE} $(PROJ).elf - avr-size $(PROJ).elf - -# debugging targets: - -disasm: $(PROJ).elf - avr-objdump -d $(PROJ).elf - -cpp: - $(COMPILE) -E $(PROJ).c - -#copy shared .h files which are used in host and firmware -shared: - cp -r ../shared/* source/ diff --git a/firmware/build_stm/inlretro_stm.bin b/firmware/build_stm/inlretro_stm.bin new file mode 100644 index 0000000..f3eb682 Binary files /dev/null and b/firmware/build_stm/inlretro_stm.bin differ diff --git a/firmware/build_stm/inlretro_stm.elf b/firmware/build_stm/inlretro_stm.elf new file mode 100644 index 0000000..950aeec Binary files /dev/null and b/firmware/build_stm/inlretro_stm.elf differ diff --git a/firmware/build_stm/inlretro_stm.hex b/firmware/build_stm/inlretro_stm.hex new file mode 100644 index 0000000..fa9c049 --- /dev/null +++ b/firmware/build_stm/inlretro_stm.hex @@ -0,0 +1,87 @@ +:020000040800F2 +:1000000000180020C1000008FD0000088903000856 +:1000100000000000000000000000000000000000E0 +:10002000000000000000000000000000FD000008CB +:100030000000000000000000FD000008FD000008B6 +:10004000FD000008FD000008FD000008FD0000089C +:10005000FD000008FD000008FD000008FD0000088C +:10006000FD000008FD000008FD000008FD0000087C +:10007000FD000008FD000008FD000008FD0000086C +:10008000FD000008FD000008FD000008FD0000085C +:10009000FD000008FD000008FD000008FD0000084C +:1000A000FD000008FD000008FD000008FD0000083C +:1000B000FD000008FD000008FD000008BD0100086B +:1000C00009490A4A0A4B9B1A03DD043BC858D05021 +:1000D000FBDC0849084A0020521A02DD043A885025 +:1000E000FCDC00F053F9000034050008000000209B +:1000F000000000200000002014000020FEE7C046A1 +:10010000224B10B51968224B224C1A885208520013 +:10011000505A214A10801A88023292B21A8052082C +:100120005200505A1D4A10801A88023292B21A8028 +:1001300052085200505A1A4A10801A88194802323E +:1001400092B21A8052085200515A174A11801A88E6 +:100150002188023292B21A808A4210D908318A1A52 +:1001600092B2028022881A801049114B0A881343E8 +:10017000104A1A40302353409BB20B8010BD0E4CE6 +:1001800021888A42EAD808230380EDE71000002086 +:100190000A0000200800002040600040426000404B +:1001A000446000400260004046600040005C004047 +:1001B0008080FFFFBF8FFFFF0600002070B5544C0A +:1001C00023881BB2002B00DB89E02388514A1A40A8 +:1001D00080231343238023881B0500D47CE04E4AF0 +:1001E0007F211368013313604C4B1A7815008D433F +:1001F0004B490D70DD884B490D8000254A490D8023 +:1002000060211140A94201D0484E358052B2002AE7 +:1002100039DA002910D15A78062A0BD15B881A0ADC +:10022000022A16D0032A16D0012A1BD1404A1220D6 +:10023000404B1A603D4B188022883F4B13433F4A86 +:100240001A40C0239B0153409BB22380FFF758FF05 +:1002500036E03B4AEBE7DBB2012B0AD0002B03D0A0 +:10026000022B0BD00800E5E7364A324B04201A6017 +:10027000E0E7354A2F4B35481A60DBE7344A2D4B0F +:1002800034481A60D6E7002908D15A78052A05D1E2 +:100290005B88314A1370314ADBB213800021238816 +:1002A0002F4A13402F4A13439BB223802E4B1980B1 +:1002B00023881A432D4B1A402D4B5A4092B222806C +:1002C0002C4BDA8F520506D580212B4A1180002253 +:1002D000DA872A4B238070BD294B1B88F0E72388DF +:1002E0001B06EDD52388274A1340802212021343B0 +:1002F00023800B4B1B78802BA8D0174A1378002B38 +:10030000DED080210B431C490B8000231370D7E7FC +:10031000005C00408F0F000000000020486000409B +:100320000C000020060000200A0000200800002029 +:100330008E040008100000208081FFFF8FBFFFFFA8 +:100340007C040008A0040008A40400082A0300009C +:10035000F80400081E030000040000205060004064 +:100360008F8EFFFF8080FFFF02600040BFBFFFFF56 +:1003700030300000065C00404C5C00402032000041 +:10038000066000400F8FFFFFFEE7000090222C4B1D +:100390001203196830B50A431A6080229202196864 +:1003A0001142FCD0012259680A435A6080225968E0 +:1003B00052020A435A6080225968D2020A435A60A4 +:1003C0008022196852040A431A6080229204196834 +:1003D0001142FCD080211A6B0A431A638022D8692B +:1003E00012040243DA6162B60220164B4025DA8F0E +:1003F000154C8243DA87DA8F01388243DA8700228C +:100400001248C2872280124C2580124C0835258064 +:100410008025114C6D012580104C2180C287104928 +:10042000104A11808021104A090611608022D98F5C +:10043000D2000A43DA870D4A0D4B1A80FEE7C04608 +:1004400000100240025C0040505C0040065C00402E +:100450000060004004600040066000404C5C0040CA +:1004600020320000005C004000E100E00080FFFF5F +:10047000585C0040F8B5C046F8B5C0460902120005 +:100480000101008032090400000000000000120198 +:100490000002FF000008C016DC0500020102000196 +:1004A000040309042A0349006E00660069006E0017 +:1004B0006900740065004E00650073004C0069001F +:1004C0007600650073002E0063006F006D00000071 +:1004D000000000000000000000000000000000001C +:1004E000000000000000000000000000000000000C +:1004F00000000000000000001E0349004E004C00F8 +:10050000200052006500740072006F002D00500042 +:1005100072006F0067000000000000000000000093 +:1005200000000000000000000000000000000000CB +:0405300000000000C7 +:04000005080000C12E +:00000001FF diff --git a/firmware/build_stm/inlretro_stm.map b/firmware/build_stm/inlretro_stm.map new file mode 100644 index 0000000..c18905b --- /dev/null +++ b/firmware/build_stm/inlretro_stm.map @@ -0,0 +1,395 @@ +Archive member included to satisfy reference by file (symbol) + +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o (exit) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) (_global_impure_ptr) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-init.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o (__libc_init_array) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-memset.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o (memset) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) (__call_exitprocs) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) (atexit) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-fini.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) (__libc_fini_array) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__atexit.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) (__register_exitproc) +c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a(_exit.o) + c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) (_exit) + +Allocating common symbols +Common symbol size file + +usbMsgPtr 0x4 source_stm_only/usbstm.o (symbol from plugin) + +Discarded input sections + + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crti.o + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crti.o + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crti.o + .text 0x00000000 0x60 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .data 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .bss 0x00000000 0x1c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .init_array 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .fini_array 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .eh_frame 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .jcr 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + .text 0x00000000 0x78 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o + .ARM.extab 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o + .ARM.exidx 0x00000000 0x8 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o + .ARM.attributes + 0x00000000 0x1b c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o + .data 0x00000000 0x0 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + .bss 0x00000000 0x0 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + .text 0x00000000 0x0 source/main.o (symbol from plugin) + .text 0x00000000 0x0 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .data 0x00000000 0x0 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .bss 0x00000000 0x0 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .text 0x00000000 0x0 source/usb.o (symbol from plugin) + .text 0x00000000 0x0 source_stm_only/stm_init.o (symbol from plugin) + .text 0x00000000 0x0 source_stm_only/usbstm.o (symbol from plugin) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) + .text.exit 0x00000000 0x20 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) + .debug_frame 0x00000000 0x28 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-exit.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + .data._impure_ptr + 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + .data.impure_data + 0x00000000 0x428 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + .rodata._global_impure_ptr + 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-impure.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-init.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-init.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-init.o) + .text.__libc_init_array + 0x00000000 0x48 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-init.o) + .debug_frame 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-init.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-init.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-memset.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-memset.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-memset.o) + .text.memset 0x00000000 0x94 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-memset.o) + .debug_frame 0x00000000 0x30 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-memset.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-memset.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .text.startup.register_fini + 0x00000000 0x18 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .init_array.00000 + 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .text.__call_exitprocs + 0x00000000 0xf8 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .debug_frame 0x00000000 0x54 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__call_atexit.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) + .text.atexit 0x00000000 0x10 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) + .debug_frame 0x00000000 0x28 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-atexit.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-fini.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-fini.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-fini.o) + .text.__libc_fini_array + 0x00000000 0x34 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-fini.o) + .debug_frame 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-fini.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-fini.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__atexit.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__atexit.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__atexit.o) + .text.__register_exitproc + 0x00000000 0xd4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__atexit.o) + .debug_frame 0x00000000 0x3c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__atexit.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a(lib_a-__atexit.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a(_exit.o) + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a(_exit.o) + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a(_exit.o) + .text._exit 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a(_exit.o) + .debug_frame 0x00000000 0x20 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a(_exit.o) + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a(_exit.o) + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtend.o + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtend.o + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtend.o + .eh_frame 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtend.o + .jcr 0x00000000 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtend.o + .ARM.attributes + 0x00000000 0x2c c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtend.o + .text 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtn.o + .data 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtn.o + .bss 0x00000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtn.o + .init 0x00000000 0x8 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtn.o + .fini 0x00000000 0x8 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtn.o + .ARM.attributes + 0x00000000 0x1e c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtn.o + +Memory Configuration + +Name Origin Length Attributes +FLASH 0x08000000 0x00008000 xr +RAM 0x20000000 0x00001800 xrw +*default* 0x00000000 0xffffffff + +Linker script and memory map + +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crti.o +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m/crt0.o +LOAD C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o +LOAD source/main.o +LOAD C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o +LOAD source/usb.o +LOAD source_stm_only/stm_init.o +LOAD source_stm_only/usbstm.o +START GROUP +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m\libgcc.a +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libg.a +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libc.a +END GROUP +START GROUP +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m\libgcc.a +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libc.a +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libnosys.a +END GROUP +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtend.o +LOAD c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtn.o + +.text 0x08000000 0x534 + *(.isr_vector) + .isr_vector 0x08000000 0xc0 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + 0x08000000 __isr_vector + *(.text*) + .text 0x080000c0 0x40 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + 0x080000c0 Reset_Handler + 0x080000fc TSC_IRQHandler + 0x080000fc ADC1_COMP_IRQHandler + 0x080000fc SysTick_Handler + 0x080000fc PendSV_Handler + 0x080000fc NMI_Handler + 0x080000fc I2C1_IRQHandler + 0x080000fc RCC_CRS_IRQHandler + 0x080000fc SPI1_IRQHandler + 0x080000fc TIM6_DAC_IRQHandler + 0x080000fc USART3_4_IRQHandler + 0x080000fc EXTI2_3_IRQHandler + 0x080000fc I2C2_IRQHandler + 0x080000fc TIM17_IRQHandler + 0x080000fc CEC_CAN_IRQHandler + 0x080000fc PVD_VDDIO2_IRQHandler + 0x080000fc TIM1_CC_IRQHandler + 0x080000fc DMA1_Channel4_5_6_7_IRQHandler + 0x080000fc TIM16_IRQHandler + 0x080000fc TIM3_IRQHandler + 0x080000fc EXTI4_15_IRQHandler + 0x080000fc DMA1_Channel1_IRQHandler + 0x080000fc Default_Handler + 0x080000fc TIM14_IRQHandler + 0x080000fc TIM7_IRQHandler + 0x080000fc TIM15_IRQHandler + 0x080000fc EXTI0_1_IRQHandler + 0x080000fc SPI2_IRQHandler + 0x080000fc SVC_Handler + 0x080000fc RTC_IRQHand + 0x080000fc WWDG_IRQHandler + 0x080000fc TIM2_IRQHandler + 0x080000fc DEF_IRQHandler + 0x080000fc DMA1_Channel2_3_IRQHandler + 0x080000fc USART2_IRQHandler + 0x080000fc FLASH_IRQHandler + 0x080000fc USART1_IRQHandler + 0x080000fc TIM1_BRK_UP_TRG_COM_IRQHandler + .text.control_xfr_in + 0x08000100 0xbc C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .text.USB_IRQHandler + 0x080001bc 0x1cc C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + 0x080001bc USB_IRQHandler + .text.HardFault_Handler + 0x08000388 0x2 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + 0x08000388 HardFault_Handler + *fill* 0x0800038a 0x2 + .text.startup.main + 0x0800038c 0xe8 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + 0x0800038c main + *(.init) + .init 0x08000474 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crti.o + 0x08000474 _init + *(.fini) + .fini 0x08000478 0x4 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crti.o + 0x08000478 _fini + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend.o *crtend?.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend.o *crtend?.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + *(.rodata*) + .rodata.config_desc + 0x0800047c 0x12 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .rodata.device_desc + 0x0800048e 0x12 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .rodata.string0_desc + 0x080004a0 0x4 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .rodata.string1_desc + 0x080004a4 0x54 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .rodata.string2_desc + 0x080004f8 0x3c C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + *(.eh_frame*) + +.glue_7 0x08000534 0x0 + .glue_7 0x08000534 0x0 linker stubs + +.glue_7t 0x08000534 0x0 + .glue_7t 0x08000534 0x0 linker stubs + +.vfp11_veneer 0x08000534 0x0 + .vfp11_veneer 0x08000534 0x0 linker stubs + +.v4_bx 0x08000534 0x0 + .v4_bx 0x08000534 0x0 linker stubs + +.iplt 0x08000534 0x0 + .iplt 0x08000534 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + +.rel.dyn 0x08000534 0x0 + .rel.iplt 0x08000534 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + +.ARM.extab + *(.ARM.extab* .gnu.linkonce.armextab.*) + 0x08000534 __exidx_start = . + +.ARM.exidx + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + 0x08000534 __exidx_end = . + 0x08000534 __etext = ALIGN (0x4) + +.data 0x20000000 0x0 load address 0x08000534 + 0x20000000 __data_start__ = . + *(vtable) + *(.data*) + 0x20000000 . = ALIGN (0x4) + 0x20000000 PROVIDE (__preinit_array_start, .) + *(.preinit_array) + 0x20000000 PROVIDE (__preinit_array_end, .) + 0x20000000 . = ALIGN (0x4) + 0x20000000 PROVIDE (__init_array_start, .) + *(SORT(.init_array.*)) + *(.init_array) + 0x20000000 PROVIDE (__init_array_end, .) + 0x20000000 . = ALIGN (0x4) + 0x20000000 PROVIDE (__fini_array_start, .) + *(SORT(.fini_array.*)) + *(.fini_array) + 0x20000000 PROVIDE (__fini_array_end, .) + *(.jcr) + 0x20000000 . = ALIGN (0x4) + 0x20000000 __data_end__ = . + +.igot.plt 0x20000000 0x0 + .igot.plt 0x20000000 0x0 c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crtbegin.o + +.bss 0x20000000 0x14 + 0x20000000 . = ALIGN (0x4) + 0x20000000 __bss_start__ = . + *(.bss*) + .bss.log 0x20000000 0x4 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .bss.new_address + 0x20000004 0x1 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + *fill* 0x20000005 0x1 + .bss.num_bytes_req + 0x20000006 0x2 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .bss.num_bytes_sending + 0x20000008 0x2 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .bss.num_bytes_xfrd + 0x2000000a 0x2 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + .bss.req_dir 0x2000000c 0x1 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + *fill* 0x2000000d 0x3 + .bss.usbMsgPtr + 0x20000010 0x4 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + *(COMMON) + 0x20000014 . = ALIGN (0x4) + 0x20000014 __bss_end__ = . + +.heap 0x20000018 0x0 + 0x20000018 __end__ = . + [!provide] PROVIDE (end, .) + *(.heap*) + .heap 0x20000018 0x0 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + 0x20000018 __HeapLimit = . + +.stack_dummy 0x20000018 0xc00 + *(.stack*) + .stack 0x20000018 0xc00 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + 0x20001800 __StackTop = (ORIGIN (RAM) + LENGTH (RAM)) + 0x20000c00 __StackLimit = (__StackTop - SIZEOF (.stack_dummy)) + 0x20001800 PROVIDE (__stack, __StackTop) + 0x00000001 ASSERT ((__StackLimit >= __HeapLimit), region RAM overflowed with stack) +OUTPUT(build_stm/inlretro_stm.elf elf32-littlearm) + +.ARM.attributes + 0x00000000 0x28 + .ARM.attributes + 0x00000000 0x1e c:/program files (x86)/gnu tools arm embedded/6.2 2016q4/bin/../lib/gcc/arm-none-eabi/6.2.1/thumb/v6-m/crti.o + .ARM.attributes + 0x0000001e 0x1b C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + .ARM.attributes + 0x00000039 0x2f C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + +.comment 0x00000000 0x6e + .comment 0x00000000 0x6e C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + 0x6f (size before relaxing) + +.debug_line 0x00000000 0x31d + .debug_line 0x00000000 0x6f C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + .debug_line 0x0000006f 0x2ae C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + +.debug_info 0x00000000 0x501 + .debug_info 0x00000000 0x83 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + .debug_info 0x00000083 0x47e C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + +.debug_abbrev 0x00000000 0x277 + .debug_abbrev 0x00000000 0x14 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + .debug_abbrev 0x00000014 0x263 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + +.debug_aranges 0x00000000 0x58 + .debug_aranges + 0x00000000 0x20 C:\Users\Paul\AppData\Local\Temp\ccwRpOLB.o + .debug_aranges + 0x00000020 0x38 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + +.debug_loc 0x00000000 0xa4 + .debug_loc 0x00000000 0xa4 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + +.debug_ranges 0x00000000 0xc0 + .debug_ranges 0x00000000 0xc0 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + +.debug_str 0x00000000 0x360 + .debug_str 0x00000000 0x360 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o + 0x38a (size before relaxing) + +.debug_frame 0x00000000 0x70 + .debug_frame 0x00000000 0x70 C:\Users\Paul\AppData\Local\Temp\ccKBE1yb.ltrans0.ltrans.o diff --git a/firmware/include_stm/README_cortexM0.md b/firmware/include_stm/README_cortexM0.md new file mode 100644 index 0000000..7878be3 --- /dev/null +++ b/firmware/include_stm/README_cortexM0.md @@ -0,0 +1,38 @@ +Paul's super awesome bare cortex M0 bare metal project. + +Got tired sifting through existing bare metal template projects and not liking how everything was setup. +Also feel silly starting such a simple project with some sort of licensing to bother with. +Stumbled upon the example projects included with arm-none-eabi-gcc compiler and decided that was as good as starting point as any. +So that's where the files originated from. + +I cut out files not used by cortex M0 or the minimum example. +Then reorganized the directory into how I like things by default. +Combined everything into one single Makefile and added creation of hex/binary file output and size reporting. + +This could easily be migrated to different core M0plus etc, just by including the proper startup file and modifying Makefile. + +When using as template first thing to do is modify linker file for memory sizes of target chip. +Don't forget to update CPU frequency as needed for any time functions. +Then bring in some library/header files for registers included with target chip. +Finally do something useful in init and main. + +There is option to use nano new lib or not in Makefile for things like printf and malloc which doesn't sound very bare metal to me.. +But whatev it's there and ready to turn on if needed. + +Current size: + text data bss dec hex filename + 148 0 0 148 94 build/baremetal.elf + +Pertenent sections of readme from samples dir: + +ldscripts/mem.ld defines address ranges for flash and RAM. Modify them to +reflect start address and length of flash/RAM banks in your board, by +following the embedded comments. + +Recommend to make clean after modifying mem.ld. + +** minimum - A minimum skeleton to start a C program with limited features. +This case has a empty main. Code size built from it is only about 150 bytes, +since it has almost no "fat" for a Cortex-M C program. Be noticed that this +case doesn't support semihosting or C++ global constructor/destructor. + diff --git a/firmware/include_stm/cmsis_gcc.h b/firmware/include_stm/cmsis_gcc.h new file mode 100644 index 0000000..bb89fbb --- /dev/null +++ b/firmware/include_stm/cmsis_gcc.h @@ -0,0 +1,1373 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* __CMSIS_GCC_H */ diff --git a/firmware/include_stm/core_cm0.h b/firmware/include_stm/core_cm0.h new file mode 100644 index 0000000..711dad5 --- /dev/null +++ b/firmware/include_stm/core_cm0.h @@ -0,0 +1,798 @@ +/**************************************************************************//** + * @file core_cm0.h + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M0 + @{ + */ + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0_REV + #define __CM0_REV 0x0000U + #warning "__CM0_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/firmware/include_stm/core_cmFunc.h b/firmware/include_stm/core_cmFunc.h new file mode 100644 index 0000000..652a48a --- /dev/null +++ b/firmware/include_stm/core_cmFunc.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/firmware/include_stm/core_cmInstr.h b/firmware/include_stm/core_cmInstr.h new file mode 100644 index 0000000..f474b0e --- /dev/null +++ b/firmware/include_stm/core_cmInstr.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/firmware/include_stm/nokeep.ld b/firmware/include_stm/nokeep.ld new file mode 100644 index 0000000..62d2edd --- /dev/null +++ b/firmware/include_stm/nokeep.ld @@ -0,0 +1,212 @@ +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + /* STM32F07x */ + /* $0000 0000 128KB of flash/sram depending on BOOT */ + /* $0002 0000 ~128MB of system reserved */ + /* $0800 0000 always flash size depends on part */ +/* FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K */ /* 0x20000 128K */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* 0x20000 128K */ + /* $0802 0000 ~384MB of system reserved */ + /* $1FFF C800 12KB of system memory (bootloader and etc) */ + /* $1FFF F800 2KB of option bytes */ + /* $2000 0000 always SRAM size depends on part */ +/* RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K */ /* 0x04000 16K */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 6K /* 0x04000 16K */ + /* $2000 4000 ~512MB of system reserved */ + /* $4000 0000 128KB of APB perif regs & reserved */ + /* $4002 0000 17KB of AHB1 perif regs & reserved */ + /* $4002 4400 ~128MB system reserved */ + /* $4800 0000 6KB AHB2 GPIO perif refs */ + /* $4800 1800 ~384MB system reserved */ + /* $E000 0000 1MB Cortex M0 internal peripherals */ + /* $E010 0000 511MB system reserved */ +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + *(.init) + *(.fini) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + *(.eh_frame*) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + /* Location counter can end up 2byte aligned with narrow Thumb code but + __etext is assumed by startup code to be the LMA of a section in RAM + which must be 4byte aligned */ + __etext = ALIGN (4); + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + *(.preinit_array) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + *(SORT(.init_array.*)) + *(.init_array) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/firmware/include_stm/startup_ARMCM0.S b/firmware/include_stm/startup_ARMCM0.S new file mode 100644 index 0000000..1209efe --- /dev/null +++ b/firmware/include_stm/startup_ARMCM0.S @@ -0,0 +1,326 @@ +/* File: startup_ARMCM0.S + * Purpose: startup file for Cortex-M0 devices. Should use with + * GCC for ARM Embedded Processors + * Version: V2.0 + * Date: 16 August 2013 + * +/* Copyright (c) 2011 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + .syntax unified + .arch armv6-m + + .section .stack + .align 3 +#ifdef __STACK_SIZE + .equ Stack_Size, __STACK_SIZE +#else + .equ Stack_Size, 0xc00 +#endif + .globl __StackTop + .globl __StackLimit +__StackLimit: + .space Stack_Size + .size __StackLimit, . - __StackLimit +__StackTop: + .size __StackTop, . - __StackTop + + .section .heap + .align 3 +#ifdef __HEAP_SIZE + .equ Heap_Size, __HEAP_SIZE +#else + .equ Heap_Size, 0 +#endif + .globl __HeapBase + .globl __HeapLimit +__HeapBase: + .if Heap_Size + .space Heap_Size + .endif + .size __HeapBase, . - __HeapBase +__HeapLimit: + .size __HeapLimit, . - __HeapLimit + + .section .isr_vector + .align 2 + .globl __isr_vector +__isr_vector: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* External interrupts */ + .long WWDG_IRQHandler /* Window Watchdog */ + .long PVD_VDDIO2_IRQHandler /* PVD through EXTI Line detect */ + .long RTC_IRQHand /* RTC through EXTI Line */ + .long FLASH_IRQHandler /* FLASH */ + .long RCC_CRS_IRQHandler /* RCC and CRS */ + .long EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */ + .long EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */ + .long EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */ + .long TSC_IRQHandler /* TS */ + .long DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ + .long DMA1_Channel2_3_IRQHandler /* DMA1 Channel 2 and Channel 3 */ + .long DMA1_Channel4_5_6_7_IRQHandler /* DMA1 Channel 4, Channel 5, Channel 6 and Channel 7 */ + .long ADC1_COMP_IRQHandler /* ADC1, COMP1 and COMP2 */ + .long TIM1_BRK_UP_TRG_COM_IRQHandler /* TIM1 Break, Update, Trigger and Commutation */ + .long TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .long TIM2_IRQHandler /* TIM2 */ + .long TIM3_IRQHandler /* TIM3 */ + .long TIM6_DAC_IRQHandler /* TIM6 and DAC */ + .long TIM7_IRQHandler /* TIM7 */ + .long TIM14_IRQHandler /* TIM14 */ + .long TIM15_IRQHandler /* TIM15 */ + .long TIM16_IRQHandler /* TIM16 */ + .long TIM17_IRQHandler /* TIM17 */ + .long I2C1_IRQHandler /* I2C1 */ + .long I2C2_IRQHandler /* I2C2 */ + .long SPI1_IRQHandler /* SPI1 */ + .long SPI2_IRQHandler /* SPI2 */ + .long USART1_IRQHandler /* USART1 */ + .long USART2_IRQHandler /* USART2 */ + .long USART3_4_IRQHandler /* USART3 & USART4 */ + .long CEC_CAN_IRQHandler /* CEC and CAN */ + .long USB_IRQHandler /* USB */ + + .size __isr_vector, . - __isr_vector + + .text + .thumb + .thumb_func + .align 1 + .globl Reset_Handler + .type Reset_Handler, %function +Reset_Handler: +/* Firstly it copies data from read only memory to RAM. There are two schemes + * to copy. One can copy more than one sections. Another can only copy + * one section. The former scheme needs more instructions and read-only + * data to implement than the latter. + * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ + +#ifdef __STARTUP_COPY_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of triplets, each of which specify: + * offset 0: LMA of start of a section to copy from + * offset 4: VMA of start of a section to copy to + * offset 8: size of the section to copy. Must be multiply of 4 + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r4, =__copy_table_start__ + ldr r5, =__copy_table_end__ + +.L_loop0: + cmp r4, r5 + bge .L_loop0_done + ldr r1, [r4] + ldr r2, [r4, #4] + ldr r3, [r4, #8] + +.L_loop0_0: + subs r3, #4 + blt .L_loop0_0_done + ldr r0, [r1, r3] + str r0, [r2, r3] + b .L_loop0_0 + +.L_loop0_0_done: + adds r4, #12 + b .L_loop0 + +.L_loop0_done: +#else +/* Single section scheme. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + + subs r3, r2 + ble .L_loop1_done + +.L_loop1: + subs r3, #4 + ldr r0, [r1,r3] + str r0, [r2,r3] + bgt .L_loop1 + +.L_loop1_done: +#endif /*__STARTUP_COPY_MULTIPLE */ + +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * There are two schemes too. One can clear multiple BSS sections. Another + * can only clear one section. The former is more size expensive than the + * latter. + * + * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. + * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. + */ +#ifdef __STARTUP_CLEAR_BSS_MULTIPLE +/* Multiple sections scheme. + * + * Between symbol address __copy_table_start__ and __copy_table_end__, + * there are array of tuples specifying: + * offset 0: Start of a BSS section + * offset 4: Size of this BSS section. Must be multiply of 4 + */ + ldr r3, =__zero_table_start__ + ldr r4, =__zero_table_end__ + +.L_loop2: + cmp r3, r4 + bge .L_loop2_done + ldr r1, [r3] + ldr r2, [r3, #4] + movs r0, 0 + +.L_loop2_0: + subs r2, #4 + blt .L_loop2_0_done + str r0, [r1, r2] + b .L_loop2_0 +.L_loop2_0_done: + + adds r3, #8 + b .L_loop2 +.L_loop2_done: +#elif defined (__STARTUP_CLEAR_BSS) +/* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 + + subs r2, r1 + ble .L_loop3_done + +.L_loop3: + subs r2, #4 + str r0, [r1, r2] + bgt .L_loop3 +.L_loop3_done: +#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */ + +#ifndef __NO_SYSTEM_INIT + bl SystemInit +#endif + +#ifndef __START +#define __START _start +#endif + bl __START + + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler NMI_Handler + def_irq_handler HardFault_Handler + def_irq_handler SVC_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + def_irq_handler DEF_IRQHandler + def_irq_handler WWDG_IRQHandler + def_irq_handler PVD_VDDIO2_IRQHandler + def_irq_handler RTC_IRQHand + def_irq_handler FLASH_IRQHandler + def_irq_handler RCC_CRS_IRQHandler + def_irq_handler EXTI0_1_IRQHandler + def_irq_handler EXTI2_3_IRQHandler + def_irq_handler EXTI4_15_IRQHandler + def_irq_handler TSC_IRQHandler + def_irq_handler DMA1_Channel1_IRQHandler + def_irq_handler DMA1_Channel2_3_IRQHandler + def_irq_handler DMA1_Channel4_5_6_7_IRQHandler + def_irq_handler ADC1_COMP_IRQHandler + def_irq_handler TIM1_BRK_UP_TRG_COM_IRQHandler + def_irq_handler TIM1_CC_IRQHandler + def_irq_handler TIM2_IRQHandler + def_irq_handler TIM3_IRQHandler + def_irq_handler TIM6_DAC_IRQHandler + def_irq_handler TIM7_IRQHandler + def_irq_handler TIM14_IRQHandler + def_irq_handler TIM15_IRQHandler + def_irq_handler TIM16_IRQHandler + def_irq_handler TIM17_IRQHandler + def_irq_handler I2C1_IRQHandler + def_irq_handler I2C2_IRQHandler + def_irq_handler SPI1_IRQHandler + def_irq_handler SPI2_IRQHandler + def_irq_handler USART1_IRQHandler + def_irq_handler USART2_IRQHandler + def_irq_handler USART3_4_IRQHandler + def_irq_handler CEC_CAN_IRQHandler + def_irq_handler USB_IRQHandler + + .end diff --git a/firmware/include_stm/stm32f070x6.h b/firmware/include_stm/stm32f070x6.h new file mode 100644 index 0000000..9e4e958 --- /dev/null +++ b/firmware/include_stm/stm32f070x6.h @@ -0,0 +1,5576 @@ +/** + ****************************************************************************** + * @file stm32f070x6.h + * @author MCD Application Team + * @version V2.3.1 + * @date 04-November-2016 + * @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File. + * This file contains all the peripheral register's definitions, bits + * definitions and memory mapping for STM32F0xx devices. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral’s registers hardware + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2016 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f070x6 + * @{ + */ + +#ifndef __STM32F070x6_H +#define __STM32F070x6_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + + /** @addtogroup Configuration_section_for_CMSIS + * @{ + */ +/** + * @brief Configuration of the Cortex-M0 Processor and Core Peripherals + */ +#define __CM0_REV 0 /*!< Core Revision r0p0 */ +#define __MPU_PRESENT 0 /*!< STM32F0xx do not provide MPU */ +#define __NVIC_PRIO_BITS 2 /*!< STM32F0xx uses 2 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/** + * @} + */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32F0xx Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ + + /*!< Interrupt Number Definition */ +typedef enum +{ +/****** Cortex-M0 Processor Exceptions Numbers **************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */ + SVC_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */ + +/****** STM32F0 specific Interrupt Numbers ******************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EXTI Lines 17, 19 and 20 */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCC_IRQn = 4, /*!< RCC global Interrupt */ + EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupt */ + EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupt */ + EXTI4_15_IRQn = 7, /*!< EXTI Line 4 to 15 Interrupt */ + DMA1_Channel1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_Channel2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupt */ + DMA1_Channel4_5_IRQn = 11, /*!< DMA1 Channel 4 and Channel 5 Interrupt */ + ADC1_IRQn = 12, /*!< ADC1 Interrupt */ + TIM1_BRK_UP_TRG_COM_IRQn = 13, /*!< TIM1 Break, Update, Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 14, /*!< TIM1 Capture Compare Interrupt */ + TIM3_IRQn = 16, /*!< TIM3 global Interrupt */ + TIM14_IRQn = 19, /*!< TIM14 global Interrupt */ + TIM16_IRQn = 21, /*!< TIM16 global Interrupt */ + TIM17_IRQn = 22, /*!< TIM17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt & EXTI Line23 Interrupt (I2C1 wakeup) */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt & EXTI Line25 Interrupt (USART1 wakeup) */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + USB_IRQn = 31 /*!< USB global Interrupt & EXTI Line18 Interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm0.h" /* Cortex-M0 processor and core peripherals */ +#include "system_stm32f0xx.h" /* STM32F0xx System Header */ +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC interrupt and status register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR1; /*!< ADC configuration register 1, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR; /*!< ADC sampling time register, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved, 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1C */ + __IO uint32_t TR; /*!< ADC analog watchdog 1 threshold register, Address offset: 0x20 */ + uint32_t RESERVED3; /*!< Reserved, 0x24 */ + __IO uint32_t CHSELR; /*!< ADC group regular sequencer register, Address offset: 0x28 */ + uint32_t RESERVED4[5]; /*!< Reserved, 0x2C */ + __IO uint32_t DR; /*!< ADC group regular data register, Address offset: 0x40 */ +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< ADC common configuration register, Address offset: ADC1 base address + 0x308 */ +} ADC_Common_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t RESERVED3; /*!< Reserved, 0x14 */ +} CRC_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ +}DBGMCU_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CMAR; /*!< DMA channel x memory address register */ +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} DMA_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; /*!
© COPYRIGHT(c) 2016 STMicroelectronics
+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f070xb + * @{ + */ + +#ifndef __STM32F070xB_H +#define __STM32F070xB_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + + /** @addtogroup Configuration_section_for_CMSIS + * @{ + */ +/** + * @brief Configuration of the Cortex-M0 Processor and Core Peripherals + */ +#define __CM0_REV 0 /*!< Core Revision r0p0 */ +#define __MPU_PRESENT 0 /*!< STM32F0xx do not provide MPU */ +#define __NVIC_PRIO_BITS 2 /*!< STM32F0xx uses 2 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/** + * @} + */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32F0xx Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ + + /*!< Interrupt Number Definition */ +typedef enum +{ +/****** Cortex-M0 Processor Exceptions Numbers **************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */ + SVC_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */ + +/****** STM32F0 specific Interrupt Numbers ******************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + RTC_IRQn = 2, /*!< RTC Interrupt through EXTI Lines 17, 19 and 20 */ + FLASH_IRQn = 3, /*!< FLASH global Interrupt */ + RCC_IRQn = 4, /*!< RCC global Interrupt */ + EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupt */ + EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupt */ + EXTI4_15_IRQn = 7, /*!< EXTI Line 4 to 15 Interrupt */ + DMA1_Channel1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_Channel2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupt */ + DMA1_Channel4_5_IRQn = 11, /*!< DMA1 Channel 4 and Channel 5 Interrupt */ + ADC1_IRQn = 12, /*!< ADC1 Interrupt */ + TIM1_BRK_UP_TRG_COM_IRQn = 13, /*!< TIM1 Break, Update, Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 14, /*!< TIM1 Capture Compare Interrupt */ + TIM3_IRQn = 16, /*!< TIM3 global Interrupt */ + TIM6_IRQn = 17, /*!< TIM6 global Interrupt */ + TIM7_IRQn = 18, /*!< TIM7 global Interrupt */ + TIM14_IRQn = 19, /*!< TIM14 global Interrupt */ + TIM15_IRQn = 20, /*!< TIM15 global Interrupt */ + TIM16_IRQn = 21, /*!< TIM16 global Interrupt */ + TIM17_IRQn = 22, /*!< TIM17 global Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Event Interrupt & EXTI Line23 Interrupt (I2C1 wakeup) */ + I2C2_IRQn = 24, /*!< I2C2 Event Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 global Interrupt */ + USART1_IRQn = 27, /*!< USART1 global Interrupt */ + USART2_IRQn = 28, /*!< USART2 global Interrupt */ + USART3_4_IRQn = 29, /*!< USART3 and USART4 global Interrupt */ + USB_IRQn = 31 /*!< USB global Interrupt & EXTI Line18 Interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm0.h" /* Cortex-M0 processor and core peripherals */ +//create our own system functions! #include "system_stm32f0xx.h" /* STM32F0xx System Header */ +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC interrupt and status register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR1; /*!< ADC configuration register 1, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR; /*!< ADC sampling time register, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved, 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1C */ + __IO uint32_t TR; /*!< ADC analog watchdog 1 threshold register, Address offset: 0x20 */ + uint32_t RESERVED3; /*!< Reserved, 0x24 */ + __IO uint32_t CHSELR; /*!< ADC group regular sequencer register, Address offset: 0x28 */ + uint32_t RESERVED4[5]; /*!< Reserved, 0x2C */ + __IO uint32_t DR; /*!< ADC group regular data register, Address offset: 0x40 */ +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< ADC common configuration register, Address offset: ADC1 base address + 0x308 */ +} ADC_Common_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t RESERVED3; /*!< Reserved, 0x14 */ +} CRC_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ +}DBGMCU_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CMAR; /*!< DMA channel x memory address register */ +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} DMA_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; /*!
© COPYRIGHT(c) 2016 STMicroelectronics
+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f0xx + * @{ + */ + +#ifndef __STM32F0xx_H +#define __STM32F0xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Library_configuration_section + * @{ + */ + +/** + * @brief STM32 Family + */ +#if !defined (STM32F0) +#define STM32F0 +#endif /* STM32F0 */ + +/* Uncomment the line below according to the target STM32 device used in your + application + */ + +#if !defined (STM32F030x6) && !defined (STM32F030x8) && \ + !defined (STM32F031x6) && !defined (STM32F038xx) && \ + !defined (STM32F042x6) && !defined (STM32F048xx) && !defined (STM32F070x6) && \ + !defined (STM32F051x8) && !defined (STM32F058xx) && \ + !defined (STM32F071xB) && !defined (STM32F072xB) && !defined (STM32F078xx) && !defined (STM32F070xB) && \ + !defined (STM32F091xC) && !defined (STM32F098xx) && !defined (STM32F030xC) + /* #define STM32F030x6 */ /*!< STM32F030x4, STM32F030x6 Devices (STM32F030xx microcontrollers where the Flash memory ranges between 16 and 32 Kbytes) */ + /* #define STM32F030x8 */ /*!< STM32F030x8 Devices (STM32F030xx microcontrollers where the Flash memory is 64 Kbytes) */ + /* #define STM32F031x6 */ /*!< STM32F031x4, STM32F031x6 Devices (STM32F031xx microcontrollers where the Flash memory ranges between 16 and 32 Kbytes) */ + /* #define STM32F038xx */ /*!< STM32F038xx Devices (STM32F038xx microcontrollers where the Flash memory is 32 Kbytes) */ + /* #define STM32F042x6 */ /*!< STM32F042x4, STM32F042x6 Devices (STM32F042xx microcontrollers where the Flash memory ranges between 16 and 32 Kbytes) */ + /* #define STM32F048x6 */ /*!< STM32F048xx Devices (STM32F042xx microcontrollers where the Flash memory is 32 Kbytes) */ + /* #define STM32F051x8 */ /*!< STM32F051x4, STM32F051x6, STM32F051x8 Devices (STM32F051xx microcontrollers where the Flash memory ranges between 16 and 64 Kbytes) */ + /* #define STM32F058xx */ /*!< STM32F058xx Devices (STM32F058xx microcontrollers where the Flash memory is 64 Kbytes) */ + /* #define STM32F070x6 */ /*!< STM32F070x6 Devices (STM32F070x6 microcontrollers where the Flash memory ranges between 16 and 32 Kbytes) */ + /* #define STM32F070xB */ /*!< STM32F070xB Devices (STM32F070xB microcontrollers where the Flash memory ranges between 64 and 128 Kbytes) */ + /* #define STM32F071xB */ /*!< STM32F071x8, STM32F071xB Devices (STM32F071xx microcontrollers where the Flash memory ranges between 64 and 128 Kbytes) */ + /* #define STM32F072xB */ /*!< STM32F072x8, STM32F072xB Devices (STM32F072xx microcontrollers where the Flash memory ranges between 64 and 128 Kbytes) */ + /* #define STM32F078xx */ /*!< STM32F078xx Devices (STM32F078xx microcontrollers where the Flash memory is 128 Kbytes) */ + /* #define STM32F030xC */ /*!< STM32F030xC Devices (STM32F030xC microcontrollers where the Flash memory is 256 Kbytes) */ + /* #define STM32F091xC */ /*!< STM32F091xB, STM32F091xC Devices (STM32F091xx microcontrollers where the Flash memory ranges between 128 and 256 Kbytes) */ + /* #define STM32F098xx */ /*!< STM32F098xx Devices (STM32F098xx microcontrollers where the Flash memory is 256 Kbytes) */ +#endif + +/* Tip: To avoid modifying this file each time you need to switch between these + devices, you can define the device in your toolchain compiler preprocessor. + */ +#if !defined (USE_HAL_DRIVER) +/** + * @brief Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ + /*#define USE_HAL_DRIVER */ +#endif /* USE_HAL_DRIVER */ + +/** + * @brief CMSIS Device version number V2.3.1 + */ +#define __STM32F0_DEVICE_VERSION_MAIN (0x02) /*!< [31:24] main version */ +#define __STM32F0_DEVICE_VERSION_SUB1 (0x03) /*!< [23:16] sub1 version */ +#define __STM32F0_DEVICE_VERSION_SUB2 (0x01) /*!< [15:8] sub2 version */ +#define __STM32F0_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32F0_DEVICE_VERSION ((__STM32F0_DEVICE_VERSION_MAIN << 24)\ + |(__STM32F0_DEVICE_VERSION_SUB1 << 16)\ + |(__STM32F0_DEVICE_VERSION_SUB2 << 8 )\ + |(__STM32F0_DEVICE_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Device_Included + * @{ + */ + +#if defined(STM32F030x6) + #include "stm32f030x6.h" +#elif defined(STM32F030x8) + #include "stm32f030x8.h" +#elif defined(STM32F031x6) + #include "stm32f031x6.h" +#elif defined(STM32F038xx) + #include "stm32f038xx.h" +#elif defined(STM32F042x6) + #include "stm32f042x6.h" +#elif defined(STM32F048xx) + #include "stm32f048xx.h" +#elif defined(STM32F051x8) + #include "stm32f051x8.h" +#elif defined(STM32F058xx) + #include "stm32f058xx.h" +#elif defined(STM32F070x6) + #include "stm32f070x6.h" +#elif defined(STM32F070xB) + #include "stm32f070xb.h" +#elif defined(STM32F071xB) + #include "stm32f071xb.h" +#elif defined(STM32F072xB) + #include "stm32f072xb.h" +#elif defined(STM32F078xx) + #include "stm32f078xx.h" +#elif defined(STM32F091xC) + #include "stm32f091xc.h" +#elif defined(STM32F098xx) + #include "stm32f098xx.h" +#elif defined(STM32F030xC) + #include "stm32f030xc.h" +#else + #error "Please select first the target STM32F0xx device used in your application (in stm32f0xx.h file)" +#endif + +/** + * @} + */ + +/** @addtogroup Exported_types + * @{ + */ +typedef enum +{ + RESET = 0, + SET = !RESET +} FlagStatus, ITStatus; + +typedef enum +{ + DISABLE = 0, + ENABLE = !DISABLE +} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum +{ + ERROR = 0, + SUCCESS = !ERROR +} ErrorStatus; + +/** + * @} + */ + + +/** @addtogroup Exported_macros + * @{ + */ +#define SET_BIT(REG, BIT) ((REG) |= (BIT)) + +#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) + +#define READ_BIT(REG, BIT) ((REG) & (BIT)) + +#define CLEAR_REG(REG) ((REG) = (0x0)) + +#define WRITE_REG(REG, VAL) ((REG) = (VAL)) + +#define READ_REG(REG) ((REG)) + +#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) + + +/** + * @} + */ + +#if defined (USE_HAL_DRIVER) + #include "stm32f0xx_hal.h" +#endif /* USE_HAL_DRIVER */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __STM32F0xx_H */ +/** + * @} + */ + +/** + * @} + */ + + + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/avr_release/main_green_v1_2.hex b/firmware/release/main_green_v1_2.hex similarity index 100% rename from firmware/avr_release/main_green_v1_2.hex rename to firmware/release/main_green_v1_2.hex diff --git a/firmware/avr_release/main_purple_v1_1_v3_0.hex b/firmware/release/main_purple_v1_1_v3_0.hex similarity index 100% rename from firmware/avr_release/main_purple_v1_1_v3_0.hex rename to firmware/release/main_purple_v1_1_v3_0.hex diff --git a/firmware/avr_release/main_v1_2b-v1_4.hex b/firmware/release/main_v1_2b-v1_4.hex similarity index 100% rename from firmware/avr_release/main_v1_2b-v1_4.hex rename to firmware/release/main_v1_2b-v1_4.hex diff --git a/firmware/source/main.c b/firmware/source/main.c index 2dd4230..b525708 100644 --- a/firmware/source/main.c +++ b/firmware/source/main.c @@ -1,15 +1,24 @@ -#include -#include -#include -#include "usbdrv.h" -//#include "io.h" -//#include "pinport.h" -//#include "buffer.h" +#include "usb.h" + +#ifdef AVR_CORE + #include + #include + #include + #include "usbdrv.h" +#endif + +#ifdef STM_CORE + #include + #include "../source_stm_only/stm_init.h" +#endif + + int main(void) { +#ifdef AVR_CORE //set watch dog timer with 1 second timer wdt_enable(WDTO_1S); /* Even if you don't use the watchdog, turn it off here. On newer devices, @@ -20,9 +29,6 @@ int main(void) * additional hardware initialization. */ - //odDebugInit(); //intialize debuging printing via serial port - //DBG1(0x00, 0, 0); //debug serial op: main starts - //initialize V-usb driver before interupts enabled and entering main loop usbInit(); //disconnect from host enforce re-enumeration, interupts must be disabled during this. @@ -43,18 +49,45 @@ int main(void) //enable interrupts sei(); +#endif + +#ifdef STM_CORE + //System is running at reset defaults + + //Default clock is in operation + //Change system clock as needed + init_clock(); + + //Initialize periphery clocks as needed + init_usb_clock(); + + //Initialize WDT, core features, etc + + //enable interrupts + __enable_irq(); //clear's processor PRIMASK register bit to allow interrupts to be taken + //I think this gets done automatically when enabling individual IRQs + + //Initialize io, periphery, etc + //setup LED as outputs and turn them on + //setup user switch as input + + init_usb(); + //Initialize board/system +#endif //================= //MAIN LOOP //================= while (1) { +#ifdef AVR_CORE //pet the watch doggie to keep him happy wdt_reset(); //must call at regular intervals no longer than 50msec - //checks for setup packets from what I understand + //keeps 8Byte EP buffer moving from what I understand usbPoll(); +#endif //check buffer status' and instruct them to //flash/dump as needed to keep data moving diff --git a/firmware/source/usb.c b/firmware/source/usb.c index 84042f0..b24c6ec 100644 --- a/firmware/source/usb.c +++ b/firmware/source/usb.c @@ -2,7 +2,7 @@ #include "usb.h" //used to store success/error code of last transfer for debugging -static uint8_t usbWrite_status; +//static uint8_t usbWrite_status; //USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]); /* This function is called when the driver receives a SETUP transaction from @@ -41,21 +41,26 @@ static uint8_t usbWrite_status; //}usbRequest_t; - +#ifdef AVR_CORE USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { +#endif +#ifdef STM_CORE +uint16_t usbFunctionSetup(uint8_t data[8]) { +#endif //defined and controled by buffer.c // extern buffer *cur_usb_load_buff; -// -// //cast incoming data into the the usb setup packet it is + + //cast incoming data into the the usb setup packet it is // setup_packet *spacket = (void *)data; -// -// //8 Byte buffer to be used for returning error code and return values -// //must be static so V-USB driver can still access after function return + + //8 Byte buffer to be used for returning error code and return values + //must be static so V-USB driver can still access after function return // static uint8_t rv[RETURN_BUFF_SIZE]; -// //rv[RV_ERR_IDX] contains opcode success/error code -// //rv[1-7] available for return data, start with index 1 -// //rv[RETURN_BUFF_FIRST_IDX-RETURN_BUFFER_LAST_IDX] + static uint8_t rv[8]; + //rv[RV_ERR_IDX] contains opcode success/error code + //rv[1-7] available for return data, start with index 1 + //rv[RETURN_BUFF_FIRST_IDX-RETURN_BUFFER_LAST_IDX] /* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data * block and return the length of the data in 'usbFunctionSetup()'. The driver @@ -275,7 +280,12 @@ USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { // with checks: using 8bit rlen = 18sec = 28.3KBps //#define MAKECHECKS 0 +#ifdef AVR_CORE USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len) { +#endif +#ifdef STM_CORE +uint8_t usbFunctionWrite(uint8_t *data, uint8_t len) { +#endif /* //defined and controled by buffer.c @@ -333,8 +343,7 @@ USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len) { return NOT_DONE; } -*/ - + */ return 0; } diff --git a/firmware/source/usb.h b/firmware/source/usb.h index bce00ff..096dcf6 100644 --- a/firmware/source/usb.h +++ b/firmware/source/usb.h @@ -1,13 +1,30 @@ #ifndef _usb_h #define _usb_h -#include -#include "usbdrv.h" +//Define the target core, only define one of these +//these defines are made in Makefile +//#define AVR_CORE +//#define STM_CORE + +//== AVR CORE == AVR CORE == AVR CORE == AVR CORE == AVR CORE +#ifdef AVR_CORE +// #include + + #include "usbdrv.h" +#endif +//end AVR CORE + +//== STM CORE == STM CORE == STM CORE == STM CORE == STM CORE +#ifdef STM_CORE + #include "..\source_stm_only\usbstm.h" +#endif +//end STM CORE + /* -#include "logic.h" -#include "types.h" #include "shared_dictionaries.h" +#include "types.h" +#include "logic.h" #include "shared_errors.h" #include "pinport.h" #include "io.h" @@ -16,6 +33,7 @@ #include "buffer.h" */ +/* #define ENDPOINT_BIT 0x80 //Bit 7 of bmRequest type determines endpoint #define ENDPOINT_IN 0x80 //In: device-to-host. #define ENDPOINT_OUT 0x00 //Out: host-to-device. @@ -27,6 +45,7 @@ #define STALL 0xFF #define PAYLD_DONE 1 #define NOT_DONE 0 +*/ diff --git a/firmware/source_stm_only/stm_init.c b/firmware/source_stm_only/stm_init.c new file mode 100644 index 0000000..028b2c5 --- /dev/null +++ b/firmware/source_stm_only/stm_init.c @@ -0,0 +1,167 @@ + +#include "stm_init.h" + +void HardFault_Handler(void) +{ + + //TODO test out this function + //should retrieve PC of the instruction that follows whatever caused the hardfault + //This didn't work for me earlier bc the stack itself was broke +// asm( +// "movs r0, #4 \n" +// "movs r1, lr \n" +// "tst r0, r1 \n" +// "beq _MSP \n" +// "mrs r0, psp \n" +// "b _HALT \n" +// "_MSP: \n" +// " mrs r0, msp \n" +// "_HALT: \n" +// " ldr r1, [r0,#20] \n" +// //" bkpt #0 \n" +// ); + + while (1) { + } +} + +/* stm32f0x2 devices have HSI48 available which isn't on stm32f0x0 devices + * I'm primarily targetting f070 devices which will require external xtal + * Most generic setup would be to use HSI 8MHz * PLL which is available on all devices + * but can't keep all devices running at 16Mhz while also properly clocking usb with that setup. + * + * After reset all devices select HSI 8MHz as SYSCLK + * To prevent usb over/under run problems, APB clock must be atleast 10Mhz + * 070 can only use PLL to feed USB clock. + * + * Current goal is to have PLL output 48Mhz from a 16Mhz HSE to support 070 devices + * 072 devices won't have ext xtal though, and use HSI 48Mhz for usb block + * Would like to have SYSCLK = 16Mhz to align stm32 and avr kazzo devices core clocks for now + * Have to also supply APB with 10Mhz or more, which is derived from SYSCLK with AHB & APB dividers + * + * While these goals are possible, we have to code them based on 072/070 devices + * 072: HSI 8Mhz -> PLL * 2 = 16Mhz -> SYSCLK -> no division to AHB & APB clocks + * HSI 48Mhz -> USB block + * 070: HSE 16Mhz -> PLL * 4 = 48Mhz -> USB block + * HSE 16Mhz -> SYSCLK -> no division to AHB & APB clocks + * + * Difference between these two is the PLL. + * 072 uses PLL to create 16Mhz SYSCLK from HSI, USB fed directly from HSI 48Mhz + * -HSE not available/used on 072 + * 070 uses PLL to create 48Mhz for USB from HSE, SYSCLK fed directly from 16Mhz HSE. + * -HSI not used for anything on 070 + */ + +//pick define based on xtal setup for init_clock and init_usb_clock functions +//#define NO_XTAL +#define XTAL_16Mhz +void init_clock() +{ +#ifdef NO_XTAL // setup PLL for HSI * 2 = 16Mhz and set SYSCLK to use it + + // To modify the PLL configuration, proceed as follows: + // 1.Disable the PLL by setting PLLON to 0. + // 2. Wait until PLLRDY is cleared. The PLL is now fully stopped. + // * PLL is off and unlocked after reset + + // 3. Change the desired parameter. + // * PLL MUL is set to *2 at reset + + // 4. Enable the PLL again by setting PLLON to 1. + // 5. Wait until PLLRDY is set. + +//Copied from reference manual optimizations possible assuming post-reset +//Cut out parts not needed due to values @ reset, saved 60Bytes! +// /* (1) Test if PLL is used as System clock */ +// if ((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_PLL) { +// RCC->CFGR &= (uint32_t) (~RCC_CFGR_SW); /* (2) Select HSI as system clock */ +// while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) /* (3) Wait for HSI switched */ +// { /* For robust implementation, add here time-out management */ } +// } +// +// RCC->CR &= (uint32_t)(~RCC_CR_PLLON);/* (4) Disable the PLL */ +// while((RCC->CR & RCC_CR_PLLRDY) != 0) /* (5) Wait until PLLRDY is cleared */ +// { /* For robust implementation, add here time-out management */ } +// +// /* (6) Set the PLL multiplier to 2-16 all integers */ +// RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PLLMUL) | RCC_CFGR_PLLMUL2; /* PLLMUL set to *2 at reset) */ + +// // PLL PREDIV should be getting set to zero too! They just assumed not present/reset values... +// RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PLLSRC) | RCC_CFGR_PLLSRC_HSI_PREDIV; /* PLLMUL set to *2 at reset) */ + +// // They also didn't address flash wait states! +// FLASH->ACR |= (uint32_t) 0x01; //If >24Mhz SYSCLK, must add wait state to flash + +// PREDIV is / 2 post reset, so PLL is being sourced with 4Mhz + RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PLLMUL) | RCC_CFGR_PLLMUL4; /* PLLMUL set to *2 at reset) */ + RCC->CR |= RCC_CR_PLLON; /* (7) Enable the PLL */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) /* (8) Wait until PLLRDY is set */ + { /* For robust implementation, add here time-out management */ } + + RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL); /* (9) Select PLL as system clock */ + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) /* (10) Wait until the PLL is switched on */ + { /* For robust implementation, add here time-out management */ } + +#endif + + +#ifdef XTAL_16Mhz + + //Turn on HSE + /* (2) Enable the CSS + * Enable the HSE and set HSEBYP to use the internal clock + * Enable HSE */ + RCC->CR |= (RCC_CR_CSSON | RCC_CR_HSEON); /* (2) */ + + /* (1) Check the flag HSE ready */ + while ((RCC->CR & RCC_CR_HSERDY) == 0) /* (1) */ + { /*spin while waiting for HSE to be ready */ } + + + /* (3) Switch the system clock to HSE */ + //at startup HSI is selected SW = 00 + RCC->CFGR |= RCC_CFGR_SW_HSE; + + //Now the SYSCLK is running directly off the HSE 16Mhz xtal + + /* (1) Test if PLL is used as System clock */ +// if ((RCC->CFGR & RCC_CFGR_SWS) == RCC_CFGR_SWS_PLL) { +// RCC->CFGR &= (uint32_t) (~RCC_CFGR_SW); /* (2) Select HSI as system clock */ +// while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) /* (3) Wait for HSI switched */ +// { /* For robust implementation, add here time-out management */ } +// } +// +// RCC->CR &= (uint32_t)(~RCC_CR_PLLON);/* (4) Disable the PLL */ +// while((RCC->CR & RCC_CR_PLLRDY) != 0) /* (5) Wait until PLLRDY is cleared */ +// { /* For robust implementation, add here time-out management */ } + + //Set PLL Source to HSE, the PLL must be off to do this + RCC->CFGR |= RCC_CFGR_PLLSRC_HSE_PREDIV; //by default HSE isn't divided + + //Set PLL to 16 * 3 = 48Mhz for USB + //RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PLLMUL) | RCC_CFGR_PLLMUL3; /* PLLMUL set to *2 at reset) */ + RCC->CFGR |= RCC_CFGR_PLLMUL3; /* PLLMUL set to *2 at reset) */ + RCC->CR |= RCC_CR_PLLON; /* (7) Enable the PLL */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) /* (8) Wait until PLLRDY is set */ + { /* For robust implementation, add here time-out management */ } + + //test SYSCLK with 48Mhz +// FLASH->ACR |= (uint32_t) 0x01; //If >24Mhz SYSCLK, must add wait state to flash +// RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL; /* (9) Select PLL as system clock */ +// while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) /* (10) Wait until the PLL is switched on */ +// { /* For robust implementation, add here time-out management */ } + +#endif + + // The USB peripheral logic uses a dedicated clock. The frequency of this + // dedicated clock is fixed by the requirements of the USB standard at 48 MHz, + // and this can be different from the clock used for the interface to the APB bus. + // Different clock configurations are possible where the APB clock frequency can be higher or lower than the USB peripheral + // one. + // Due to USB data rate and packet memory interface requirements, + // the APB clock must have a minimum frequency of 10 MHz to avoid data overrun/underrun problems. + + //AHB APB clock setup: + //these are not divided by default +} + diff --git a/firmware/source_stm_only/stm_init.h b/firmware/source_stm_only/stm_init.h new file mode 100644 index 0000000..91e7a8e --- /dev/null +++ b/firmware/source_stm_only/stm_init.h @@ -0,0 +1,5 @@ + +#include + +void init_clock(); + diff --git a/firmware/source_stm_only/usb_descriptors.h b/firmware/source_stm_only/usb_descriptors.h new file mode 100644 index 0000000..dbd4275 --- /dev/null +++ b/firmware/source_stm_only/usb_descriptors.h @@ -0,0 +1,271 @@ +#ifndef _usb_descriptors_h +#define _usb_descriptors_h + +/* Contains all the device, configuration, interface, endpoint, and string descriptor definitions + * The excellent breakdown of the USB standard and field comments have been copy pasted from the + * almighty documentation "USB in a Nutshell" article by BeyondLogic: + * http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors + */ +#define EP0_SIZE 0x08 //8Bytes same as usb 1.1 for now + +#define bLength 0 //offset of bLength in descriptor array +#define bDescriptorType 1 //offset of bDescriptorType in descriptor array +#define DESC_TYPE_MASK 0xFF00 //Descriptor type is upper byte of wValue +#define DESC_IDX_MASK 0x00FF //Descriptor index is lower byte of wValue +#define DESC_TYPE_DEVICE 0x01 +#define DESC_TYPE_CONFIG 0x02 +#define DESC_TYPE_STRING 0x03 +#define DESC_TYPE_INTERFACE 0x04 +#define DESC_TYPE_ENDPOINT 0x05 + +#define DEVICE_DESC_LEN 18 +const uint8_t device_desc[DEVICE_DESC_LEN] = { +// 0 bLength 1 Number Size of the Descriptor in Bytes (18 bytes) + DEVICE_DESC_LEN, +// 1 bDescriptorType 1 Constant Device Descriptor (0x01) + DESC_TYPE_DEVICE, +// 2 bcdUSB 2 BCD USB Specification Number which device complies too. + 0x00, 0x02, +// 4 bDeviceClass 1 Class Class Code (Assigned by USB Org) + 0xFF, +// If equal to Zero, each interface specifies itÎéÎ÷s own class code +// If equal to 0xFF, the class code is vendor specified. +// Otherwise field is valid Class Code. +// 5 bDeviceSubClass 1 SubClass Subclass Code (Assigned by USB Org) + 0x00, +// 6 bDeviceProtocol 1 Protocol Protocol Code (Assigned by USB Org) + 0x00, +// 7 bMaxPacketSize 1 Number Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64 (for usb 2.0) + EP0_SIZE, +// 8 idVendor 2 ID Vendor ID (Assigned by USB Org) + 0xC0, 0x16, +// 10 idProduct 2 ID Product ID (Assigned by Manufacturer) + 0xDC, 0x05, +// 12 bcdDevice 2 BCD Device Release Number + 0x00, 0x02, +// 14 iManufacturer 1 Index Index of Manufacturer String Descriptor + 0x01, +// 15 iProduct 1 Index Index of Product String Descriptor + 0x02, +// 16 iSerialNumber 1 Index Index of Serial Number String Descriptor + 0x00, +// 17 bNumConfigurations 1 Integer Number of Possible Configurations + 0x01 }; + + +// The bcdUSB field reports the highest version of USB the device supports. The value is in binary coded decimal +// with a format of 0xJJMN where JJ is the major version number, M is the minor version number and N is the sub minor +// version number. e.g. USB 2.0 is reported as 0x0200, USB 1.1 as 0x0110 and USB 1.0 as 0x0100. +// +// The bDeviceClass, bDeviceSubClass and bDeviceProtocol are used by the operating system to find a class driver +// for your device. Typically only the bDeviceClass is set at the device level. Most class specifications choose to +// identify itself at the interface level and as a result set the bDeviceClass as 0x00. This allows for the one +// device to support multiple classes. +// +// The bMaxPacketSize field reports the maximum packet size for endpoint zero. All devices must support endpoint zero. +// +// The idVendor and idProduct are used by the operating system to find a driver for your device. The Vendor ID is assigned by the USB-IF. +// +// The bcdDevice has the same format than the bcdUSB and is used to provide a device version number. This value is assigned by the developer. +// +// Three string descriptors exist to provide details of the manufacturer, product and serial number. There is no +// requirement to have string descriptors. If no string descriptor is present, a index of zero should be used. +// +// bNumConfigurations defines the number of configurations the device supports at its current speed. + + +//Configuration Descriptors +// +// A USB device can have several different configurations although the majority of devices are simple and only have one. +// The configuration descriptor specifies how the device is powered, what the maximum power consumption is, the number of +// interfaces it has. Therefore it is possible to have two configurations, one for when the device is bus powered and another +// when it is mains powered. As this is a "header" to the Interface descriptors, its also feasible to have one configuration +// using a different transfer mode to that of another configuration. +// +// Once all the configurations have been examined by the host, the host will send a SetConfiguration command with a non zero +// value which matches the bConfigurationValue of one of the configurations. This is used to select the desired configuration. +// +#define CONFIG_DESC_LEN 9 +#define INTERFACE_DESC_LEN 9 +#define ENDPOINT_DESC_LEN 0 //only describe EP's other than EP0 + //NOTE: current table broken if total is greater 255 bytes!!! +#define CONFIG_TOTAL_LEN (CONFIG_DESC_LEN + INTERFACE_DESC_LEN + ENDPOINT_DESC_LEN) +#define wTotalLength 2 //offset of wTotalLength in descriptor array +const uint8_t config_desc[CONFIG_TOTAL_LEN] = { +// Off Field Size Value Description +// 0 bLength 1 Number Size of Descriptor in Bytes + CONFIG_DESC_LEN, +// 1 bDescriptorType 1 Constant Configuration Descriptor (0x02) + DESC_TYPE_CONFIG, +// 2 wTotalLength 2 Number Total length in bytes of data returned + CONFIG_TOTAL_LEN, 0x00, +// 4 bNumInterfaces 1 Number Number of Interfaces + 0x01, +// 5 bConfigurationValue 1 Number Value to use as an argument to select this configuration + 0x01, +// 6 iConfiguration 1 Index Index of String Descriptor describing this configuration + 0x00, +// 7 bmAttributes 1 Bitmap D7 Reserved, set to 1. (USB 1.0 Bus Powered) +// D6 Self Powered +// D5 Remote Wakeup +// D4..0 Reserved, set to 0. + 0x80, +// 8 bMaxPower 1 mA Maximum Power Consumption in 2mA units +// bus powered devices should request more than 100mA + 100/2, +// +// When the configuration descriptor is read, it returns the entire configuration hierarchy which includes all related +// interface and endpoint descriptors. The wTotalLength field reflects the number of bytes in the hierarchy. +// +// bNumInterfaces specifies the number of interfaces present for this configuration. +// +// bConfigurationValue is used by the SetConfiguration request to select this configuration. +// +// iConfiguration is a index to a string descriptor describing the configuration in human readable form. +// +// bmAttributes specify power parameters for the configuration. If a device is self powered, it sets D6. Bit D7 was used in +// USB 1.0 to indicate a bus powered device, but this is now done by bMaxPower. If a device uses any power from the bus, +// whether it be as a bus powered device or as a self powered device, it must report its power consumption in bMaxPower. +// Devices can also support remote wakeup which allows the device to wake up the host when the host is in suspend. +// +// bMaxPower defines the maximum power the device will drain from the bus. This is in 2mA units, thus a maximum of +// approximately 500mA can be specified. The specification allows a high powered bus powered device to drain no more than +// 500mA from Vbus. If a device loses external power, then it must not drain more than indicated in bMaxPower. It should +// fail any operation it cannot perform without external power. +// +// +// +// +//Interface Descriptors +// +// The interface descriptor could be seen as a header or grouping of the endpoints into a functional group performing a +// single feature of the device. The interface descriptor conforms to the following format, +// +// Off Field Size Value Description +// 0 bLength 1 Number Size of Descriptor in Bytes (9 Bytes) + INTERFACE_DESC_LEN, +// 1 bDescriptorType 1 Constant Interface Descriptor (0x04) + DESC_TYPE_INTERFACE, +// 2 bInterfaceNumber 1 Number Number of Interface + 0x00, +// 3 bAlternateSetting 1 Number Value used to select alternative setting + 0x00, +// 4 bNumEndpoints 1 Number Number of Endpoints used for this interface + 0x00, +// 5 bInterfaceClass 1 Class Class Code (Assigned by USB Org) + 0x00, +// 6 bInterfaceSubClass 1 SubClass Subclass Code (Assigned by USB Org) + 0x00, +// 7 bInterfaceProtocol 1 Protocol Protocol Code (Assigned by USB Org) + 0x00, +// 8 iInterface 1 Index Index of String Descriptor Describing this interface + 0x00}; +// +// bInterfaceNumber indicates the index of the interface descriptor. This should be zero based, and incremented once +// for each new interface descriptor. +// +// bAlternativeSetting can be used to specify alternative interfaces. These alternative interfaces can be selected +// with the Set Interface request. +// +// bNumEndpoints indicates the number of endpoints used by the interface. This value should exclude endpoint zero +// and is used to indicate the number of endpoint descriptors to follow. +// +// bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol can be used to specify supported classes +// (e.g. HID, communications, mass storage etc.) This allows many devices to use class drivers preventing the +// need to write specific drivers for your device. +// +// iInterface allows for a string description of the interface. +// +//Endpoint Descriptors +// +// Endpoint descriptors are used to describe endpoints other than endpoint zero. Endpoint zero is always assumed to be a +// control endpoint and is configured before any descriptors are even requested. The host will use the information returned +// from these descriptors to determine the bandwidth requirements of the bus. +// +// Off Field Size Value Description +// 0 bLength 1 Number Size of Descriptor in Bytes (7 bytes) +// 1 bDescriptorType 1 Constant Endpoint Descriptor (0x05) +// 2 bEndpointAddress 1 Endpoint Endpoint Address +// Bits 0..3b Endpoint Number. +// Bits 4..6b Reserved. Set to Zero +// Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints) +// 3 bmAttributes 1 Bitmap Bits 0..1 Transfer Type +// 00 = Control 01 = Isochronous 10 = Bulk 11 = Interrupt +// Bits 2..7 are reserved. If Isochronous endpoint, +// Bits 3..2 = Synchronisation Type (Iso Mode) +// 00 = No Synchonisation 01 = Asynchronous 10 = Adaptive 11 = Synchronous +// Bits 5..4 = Usage Type (Iso Mode) +// 00 = Data Endpoint 01 = Feedback Endpoint +// 10 = Explicit Feedback Data Endpoint 11 = Reserved +// 4 wMaxPacketSize 2 Number Maximum Packet Size this endpoint is capable of sending or receiving +// 6 bInterval 1 Number Interval for polling endpoint data transfers. Value in frame counts. +// Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may +// range from 1 to 255 for interrupt endpoints. +// +// bEndpointAddress indicates what endpoint this descriptor is describing. +// +// bmAttributes specifies the transfer type. This can either be Control, Interrupt, Isochronous or Bulk Transfers. +// If an Isochronous endpoint is specified, additional attributes can be selected such as the Synchronisation and usage types. +// +// wMaxPacketSize indicates the maximum payload size for this endpoint. +// +// bInterval is used to specify the polling interval of certain transfers. The units are expressed in frames, +// thus this equates to either 1ms for low/full speed devices and 125us for high speed devices. +// +//String Descriptors +// +// String descriptors provide human readable information and are optional. If they are not used, any +// string index fields of descriptors must be set to zero indicating there is no string descriptor available. +// +// The strings are encoded in the Unicode format and products can be made to support multiple languages. +// String Index 0 should return a list of supported languages. A list of USB Language IDs can be found in +// Universal Serial Bus Language Identifiers (LANGIDs) version 1.0 +// +#define STRING0_DESC_LEN 4 +const uint8_t string0_desc[STRING0_DESC_LEN] = { +// Off Field Size Value Description +// 0 bLength 1 Number Size of Descriptor in Bytes + STRING0_DESC_LEN, +// 1 bDescriptorType 1 Constant String Descriptor (0x03) + DESC_TYPE_STRING, +// 2 wLANGID[0] 2 number Supported Language Code Zero +// (e.g. 0x0409 English - United States) + 0x09, 0x04}; +// 4 wLANGID[1] 2 number Supported Language Code One +// (e.g. 0x0c09 English - Australian) +// n wLANGID[x] 2 number Supported Language Code x +// (e.g. 0x0407 German - Standard) +// +// The above String Descriptor shows the format of String Descriptor Zero. The host should read this descriptor to +// determine what languages are available. If a language is supported, it can then be referenced by sending the +// language ID in the wIndex field of a Get Descriptor(String) request. +// +// All subsequent strings take on the format below, +// +// Off Field Size Value Description +// 0 bLength 1 Number Size of Descriptor in Bytes +// 1 bDescriptorType 1 Constant String Descriptor (0x03) +// 2 bString n Unicode Unicode Encoded String +// +// +// + +//Defining string arrays as uint16_t effectively makes the strings UTF-16 as required +#define BYTES_PER_HWORD 2 +#define STRING1_DESC_LEN (21*BYTES_PER_HWORD) //characters plus 1 for bLength & bDescriptorType +const uint16_t string1_desc[STRING1_DESC_LEN] = { +// 0 bLength 1 Number Size of Descriptor in Bytes +// 1 bDescriptorType 1 Constant String Descriptor (0x03) + ((uint16_t)DESC_TYPE_STRING<<8 | STRING1_DESC_LEN), +// 2 bString n Unicode Unicode Encoded String +'I','n','f','i','n','i','t','e','N','e','s','L','i','v','e','s','.','c','o','m'}; + +#define STRING2_DESC_LEN (15*BYTES_PER_HWORD) //characters plus 1 for bLength & bDescriptorType +const uint16_t string2_desc[STRING2_DESC_LEN] = { +// 0 bLength 1 Number Size of Descriptor in Bytes +// 1 bDescriptorType 1 Constant String Descriptor (0x03) + ((uint16_t)DESC_TYPE_STRING<<8 | STRING2_DESC_LEN), +// 2 bString n Unicode Unicode Encoded String +'I','N','L',' ','R','e','t','r','o','-','P','r','o','g'}; + +#endif diff --git a/firmware/source_stm_only/usbstm.c b/firmware/source_stm_only/usbstm.c new file mode 100644 index 0000000..3abf629 --- /dev/null +++ b/firmware/source_stm_only/usbstm.c @@ -0,0 +1,959 @@ +#include "usbstm.h" +#include "usb_descriptors.h" + + +static int log = 0; + +//include target board library files +//this is junk... #include + +//kaz6 is PB1 +//#define LED (1U) +//#define IOP_LED_EN RCC_AHBENR_GPIOBEN +//#define GPIO_LED GPIOB + + ////kaz adapter is PC13 + //#define LED (13U) + //#define IOP_LED_EN RCC_AHBENR_GPIOCEN + //#define GPIO_LED GPIOC + // + ////kaz adapter data0 debug is PB8 + //#define DEBUG (8U) + //#define IOP_DEBUG_EN RCC_AHBENR_GPIOBEN + //#define GPIO_DEBUG GPIOB + // + //#define LED_ON() (GPIO_LED->ODR |= (0x1U<ODR &= ~(0x1U<ODR |= (0x1U<ODR &= ~(0x1U<CFGR3 |= RCC_CFGR3_USBSW_PLLCLK; +#endif + +#ifdef NO_XTAL + //Turn on HSI48 supposedly it will turn itself on if USB is enabled with HSI48 selected as clock + RCC->CR2 |= RCC_CR2_HSI48ON; + + while ((RCC->CR2 & RCC_CR2_HSI48RDY) != RCC_CR2_HSI48RDY) /* (10) Wait until the HSI48 is stable */ + { /* For robust implementation, add here time-out management */ } + + //by default the 072 has HSI 48Mhz selected as USB clock + RCC->CFGR3 &= ~RCC_CFGR3_USBSW_Msk; + //on the 070 this equates to off, so 070 must set USBSW bit + //CRS system must be turned on to keep HSI 48Mhz calibrated + RCC->APB1ENR |= RCC_APB1ENR_CRSEN; + //Default settings are good using SOF packets for calibration +#endif + + //enable USB block by providing clock + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + + +} + + +void usb_reset_recovery(){ + +// USB->CNTR |= USB_CNTR_FRES; +// USB->CNTR &= ~USB_CNTR_FRES; + + //Endpoint-specific registers + //The number of these registers varies according to the number of endpoints that the USB peripheral is designed to handle. + //The USB peripheral supports up to 8 bidirectional endpoints. Each USB device must support a control endpoint whose + //address (EA bits) must be set to 0. The USB peripheral behaves in an undefined way if multiple endpoints + //are enabled having the same endpoint number value. For each endpoint, an USB_EPnR register is available to store + //the endpoint specific information. + + //Enable the USB device and set address to zero + //USB device address (USB_DADDR) + //bit7 must be set to enable USB functionality, bits 6:0 are the address, must be 0 prior to enumeration + USB->DADDR = (uint16_t) USB_DADDR_EF; + + //They are also reset when an USB reset is received from the USB bus or forced through bit FRES in the CTLR register, + //except the CTR_RX and CTR_TX bits, which are kept unchanged to avoid missing a correct packet notification + //immediately followed by an USB reset event. Each endpoint has its USB_EPnR register where n is the endpoint identifier. + //Read-modify-write cycles on these registers should be avoided because between the read and the write operations + //some bits could be set by the hardware and the next write would modify them before the CPU has the time to detect the change. + //For this purpose, all bits affected by this problem have an "invariant" value that must be used whenever their + //modification is not required. It is recommended to modify these registers with a load instruction where all the bits, + //which can be modified only by the hardware, are written with their "invariant" value. + // + //USB endpoint n register (USB_EPnR), n=[0..7] + //Address offset: 0x00 to 0x1C + //Reset value: 0x0000 + // + //Bit 15 CTR_RX: Correct Transfer for reception + // Hardware sets on successful completetion of OUT/SETUP transaction + // a failed transaction won't set this bit + // Software can only clear this bit + // SETUP bit11 signifies if OUT/SETUP was received + // USE: read this bit after interrupt to determine/verify interrupt was due to success + // service OUT/SETUP packet then clear the bit so subsequent interrupt can be detected properly + // write 0 to clear, write 1 to leave as-is + // + //Bit 14 DTOG_RX: Data Toggle, for reception transfers + // For non-isosync xfrs this bit contains Data0/1 expectation of next data packet + // Hardware toggles this bit after ACK'ing the host from successful PID match + // For control EPs HW clears this bit after receiving SETUP PID + // For double buffered, or isosync EPs this bit has other meanings + // Software can toggle this value by writting a 1, writting 0 has no effect. + // -This is manditory for non-control EPs! + // USE: For control endpoints: Seems this bit can be used to determine if upcoming xfr is DATA0/1 + // Shouldn't have to do/care much with this bit for control endpoints + // write 1 to toggle, write 0 to leave as-is + // + // + //Bits 13:12 STAT_RX [1:0]: Status bits, for reception transfers + // 00: Disabled, all reception requests to this EP are ignored (default post-reset) + // 01: Stall, EP is stalled and all reception requests will get STALL handshake + // 10: NAK, all reception requests will get NAK handshake + // 11: Valid, this endpoint is enabled for reception + // Hardware sets these bits to NAK after successful OUT/SETUP xfr + // Software can toggle these bits by writting a 1, writting 0 has no effect + // USE: to enable the endpoint toggle these bits to set. HW will clear bit12 when xfr is recieved. + // That way subsequent xfrs will get NAK'd until software processes EP and ready's it for another. + // Once processed toggle back to VALID so next xfr can occur + // write 1 to toggle, write 0 to leave as-is + // + // + //Bit 11 SETUP: Setup transaction completed + // This bit is read-only and indicates if last completed transaction was a SETUP. + // This bit only gets set for control endpoints. It remains set while CTR_RX is set. + // USE: For control EPs read this bit to determine if received xfr is SETUP or OUT. + // writes have no effect, read only + // + //Bits 10:9 EP_TYPE[1:0]: Endpoint type + // 00: BULK + // 01: CONTROL + // 10: ISO + // 11: INTERRUPT + // EP0 must always be CONTROL and always available (set by address==0) + // USE: set these bits to desired endpoint type. Hardware uses these bits to dictate it's behavior. + // bits are read/write, RMW to leave as is + // + //Bit 8 EP_KIND: Endpoint kind + // BULK: DBL_BUF, this bit is set by software to indicate double buffered EP + // CONTROL: STATUS_OUT, this bit is set by software to indicate that STATUS_OUT is expected. + // This will cause all OUT transactions with more than zero data bytes to be STALL'd instead of ACK. + // When clear, OUT transactions of any data length will be allowed. + // ISO/INT: unused + // USE: set for BULK EPs if want to double buffer the endpoint + // set for CONTROL EPs for robustness, when a STATUS_OUT is expected and want non-zero data to be STALL'd + // Think we can get by ignoring this bit for now + // bit is read/write, RMW to leave as-is + // + //Bit 7 CTR_TX: Correct Transfer for transmission + // Similar to CTR_RX, but for transmissions. Hardware sets this bit on successful transmission completion. + // This won't get set if transfer failed. Software can only write this bit to 0. + // USE: read this bit after interrupt to determine if source of interrupt was due to successful transmission. + // process what's needed for upcoming transmission if needed, and clear this bit to subsequent interrupts + // will be properly detected. + // write 0 to clear, write 1 to leave as-is + // + // + //Bit 6 DTOG_TX: Data Toggle, for transmission transfers + // Similar to DTOG_RX, but for transmissions. Hardware toggles this bit after an ACK of data transmit. + // For control EPs HW sets this bit at reception of SETUP PID + // For double buffered, and iso EPs this bit has different functions + // Software can toggle this bit by writting a 1, writting 0 is ignored. Required for non-control EPs + // USE: should be able to ignore for control EPs. + // To leave as-is write a 0. + // + //Bits 5:4 STAT_TX [1:0]: Status bits, for transmission transfers + // 00: Disabled, all transmission requests to this EP are ignored (default post-reset) + // 01: Stall, EP is stalled and all transmission requests will get STALL handshake + // 10: NAK, all transmission requests will get NAK handshake + // 11: Valid, this endpoint is enabled for transmission + // Hardware changes these bits from Valid to NAK after successful transmission. + // That way subsequent transmit requests will be NAK'd until software can prepare the next one. + // These bits will toggle when wrote to with a 1, writting a 0 doesn't affect them. + // USE: Toggle the bits to Valid when data has been loaded into buffer and ready for transmission. + // write 1 to toggle, write 0 to leave as-is + // + //Bits 3:0 EA[3:0]: Endpoint address + // Software must write the address to these bits to enable the endpoint. + // USE: set these bits to the "endpoint number" ie 0 for EP0, 1 for EP1, etc. + // These default to 0, so post reset all USB_EPnR are set to be EP0. + // But because nothing is initialized they'll all ignore anything going on. + // bits are read/write, RMW to leave as is + + //Reset done, now setup as if USB reset has occured + //USB reset (RESET interrupt) + //When this event occurs, the USB peripheral is put in the same conditions it is left by the system + //reset after the initialization described in the previous paragraph: communication is disabled in all + //endpoint registers (the USB peripheral will not respond to any packet). + //As a response to the USB reset event, the USB function must be enabled, having as USB address 0, + //implementing only the default control endpoint (endpoint address is 0 too). + //This is accomplished by setting the Enable Function (EF) bit of the USB_DADDR register and + //initializing the EP0R register and its related packet buffers accordingly. + // + //During USB enumeration process, the host assigns a unique address to this device, + //which must be written in the ADD[6:0] bits of the USB_DADDR register, and configures any other necessary endpoint. + //When a RESET interrupt is received, the application software is responsible to enable again + //the default endpoint of USB function 0 within 10 ms from the end of reset sequence which triggered the interrupt. + + //clear any pending interrupts + USB->ISTR = 0; + + //initialize EP specific register for EP0 as CONTROL and ready for RX of any OUT + //assuming reset condition with all bits clear, except CTR_RX/TX holding prior to reset value + USB->EP0R = (uint16_t) (USB_EP_RX_VALID | USB_EP_CONTROL | USB_EP_TX_NAK); + //clears CTR_RX/TX bits, ready to recieve, transmit disabled, sets to control type, expect any out, set addr to EP0 + // + + + +} + + +//Create pointer to 16bit array with 512 entries (1024Bytes) +//can only be accessed in byte or half words, not full 32bit words! +//uint16_t volatile (* const usb_buff)[512] = (void*)USB_PMAADDR; +//this was suggestion by: http://a3f.at/articles/register-syntax-sugar +//which errors on compilation due to assigning of type array +uint16_t volatile (* const usb_buff) = (void*)USB_PMAADDR; + + +//#define TSSOP20 //defined when using TSSOP-20 part to get PA11/12 alternate mapping to the pins + +void init_usb() +{ + + + //initialize i/o + // TSSOP-20: On STM32F070x6 devices, pin pair PA11/12 can be remapped instead of pin pair PA9/10 using SYSCFG_CFGR1 register. +#ifdef TSSOP20 + //by default PA9/10 are configured to pins 17/18, have to set bits to map PA11/12 which contain USB PHY + SYSCFG->CFGR1 |= PA11_PA12_RMP; +#endif + // + // ensure GPIO bank A is enabled after the discussion below, I'm not even sure this is needed.. +// RCC->AHBENR |= (uint32_t) (1<APB1RSTR |= RCC_APB1RSTR_USBRST; //reset +// RCC->APB1RSTR &= ~RCC_APB1RSTR_USBRST; //release reset + + + //Sections copied from reference manual + //As a first step application software needs to activate register macrocell clock and de-assert + //macrocell specific reset signal using related control bits provided by device clock management logic. + // + //clock was already done in init_usb_clk function. + //de-assert translates to set reset high I believe, but I'm still not sure I understand. + //The next section talks about removing the reset condition with FRES/CNTR reg, but that can't be done yet. + //So I think it's just covering bases to say the RCC_APB1RSTR register can't be set "in reset condition" + //Actually I think this section of the datasheet is referring to how the first thing a host does once + //a device is detected is send it a reset condition (lack of SOF packets) and as this code is being ran that + //has yet to occur. So we need to set things up to expect the first "USB command" to be recieved via the cable + //as reset which equates to enabling the reset interrupt and having it call reset recovery routine. + + //After that, the analog part of the device related to the USB transceiver must be + //switched on using the PDWN bit in CNTR register, which requires a special handling. + USB->CNTR &= ~USB_CNTR_PDWN; //default is set, clear to power up USB + + //This bit is intended to switch on the internal voltage references that supply the port transceiver. + //This circuit has a defined startup time (tSTARTUP specified in the datasheet) tSTARTUP = 1usec + //during which the behavior of the USB transceiver is not defined. + int delay = 0; + for( delay = 0; delay < 48; delay++ ){ + //16Mhz = 62.5nsec clock, 1usec = 1Mhz + //need 16 clocks to delay 1usec this loop will take a few instruction cycles at least + //Perhaps this code will be ran while the core is running at 48Mhz + //So future proof by waiting 3 times as long + } + + //It is thus necessary to wait this time, after setting the PDWN bit in the CNTR register, + //before removing the reset condition on the USB part (by clearing the FRES bit in the CNTR register). + USB->CNTR &= ~USB_CNTR_FRES; //default set, clear to remove reset + + //Clearing the ISTR register then removes any spurious pending interrupt before any other macrocell operation is enabled. + //Entire register is read, or clear by writing 0. + USB->ISTR = 0; + + //At system reset, the microcontroller must initialize all required registers and the packet buffer description table, + //to make the USB peripheral able to properly generate interrupts and data transfers. + // + //Structure and usage of packet buffers + //Each bidirectional endpoint may receive or transmit data from/to the host. The received data + //is stored in a dedicated memory buffer reserved for that endpoint, while another memory + //buffer contains the data to be transmitted by the endpoint. Access to this memory is + //performed by the packet buffer interface block, which delivers a memory access request + //and waits for its acknowledgment. Since the packet buffer memory has to be accessed by + //the microcontroller also, an arbitration logic takes care of the access conflicts, using half + //APB cycle for microcontroller access and the remaining half for the USB peripheral access. + //In this way, both the agents can operate as if the packet memory is a dual-port SRAM, + //without being aware of any conflict even when the microcontroller is performing back-to- + //back accesses. The USB peripheral logic uses a dedicated clock. The frequency of this + //dedicated clock is fixed by the requirements of the USB standard at 48 MHz, and this can be + //different from the clock used for the interface to the APB bus. Different clock configurations + //are possible where the APB clock frequency can be higher or lower than the USB peripheral + //one. + // + //Note: Due to USB data rate and packet memory interface requirements, the APB clock must have a minimum + //frequency of 10 MHz to avoid data overrun/underrun problems. + // + //Each endpoint is associated with two packet buffers (usually one for transmission and the + //other one for reception). Buffers can be placed anywhere inside the packet memory + //because their location and size is specified in a buffer description table, which is also + //located in the packet memory at the address indicated by the USB_BTABLE register. + // + //Each table entry is associated to an endpoint register and it is composed of four 16-bit half-words + //so that table start address must always be aligned to an 8-byte boundary (the lowest three + //bits of USB_BTABLE register are always "000"). Buffer descriptor table entries are + //described in the Section30.6.2: Buffer descriptor table. If an endpoint is unidirectional and it + //is neither an Isochronous nor a double-buffered bulk, only one packet buffer is required + //(the one related to the supported transfer direction). Other table locations related to unsupported + //transfer directions or unused endpoints, are available to the user. Isochronous and double- + //buffered bulk endpoints have special handling of packet buffers (Refer to Section 30.5.4: + //Isochronous transfers and Section 30.5.3: Double-buffered endpoints respectively). The + //relationship between buffer description table entries and packet buffer areas is depicted in Figure323. + // + //Each packet buffer is used either during reception or transmission starting from the bottom. + //The USB peripheral will never change the contents of memory locations adjacent to the + //allocated memory buffers; if a packet bigger than the allocated buffer length is received + //(buffer overrun condition) the data will be copied to the memory only up to the last available + //location. + // + //Buffer descriptor table + //Although the buffer descriptor table is located inside the packet buffer memory, its entries + //can be considered as additional registers used to configure the location and size of the + //packet buffers used to exchange data between the USB macro cell and the device. + //The first packet memory location is located at 0x40006000. The buffer descriptor table + //entry associated with the USB_EPnR registers is described below. The packet memory + //should be accessed only by byte (8-bit) or half-word (16-bit) accesses. Word (32-bit) accesses are not allowed. + // + //Buffer table address (USB_BTABLE) this is the address of the buffer table which is contained in the 1KB of RAM itself + //By default this value is set to zero, that's what I would have choosen anyway, so doesn't need initialized + //But let's go ahead and do it so it's easy to move later if needed and gives us defines to use for addressing + USB->BTABLE = USB_BTABLE_BASE; + + + //Endpoint initialization + //The first step to initialize an endpoint is to write appropriate values to the ADDRn_TX/ADDRn_RX registers + //so that the USB peripheral finds the data to be transmitted already available and the data to be received can be buffered. + //The EP_TYPE bits in the USB_EPnR register must be set according to the endpoint type, eventually using + //the EP_KIND bit to enable any special required feature. + //On the transmit side, the endpoint must be enabled using the STAT_TX bits in the USB_EPnR register + //and COUNTn_TX must be initialized. + //For reception, STAT_RX bits must be set to enable reception and COUNTn_RX must be written with + //the allocated buffer size using the BL_SIZE and NUM_BLOCK fields. + + //only setup endpoint zero buffers for now that's all that's required to satisfy USB and get started + usb_buff[USB_ADDR0_TX] = EP0_TX_ADDR; + //TX count is set to the number of bytes to xfr in next packet + //usb_buff[USB_COUNT0_TX] = EP0_SIZE; + usb_buff[USB_ADDR0_RX] = EP0_RX_ADDR; + //RX count is made up of 3 parts + //the MSB is block size 0->2Bytes, 1->32Bytes + //bit 14:10 is number of blocks + //end point size = block size * num blocks + //bits 9:0 are set by USB block based on actual count received + //usb_buff[USB_COUNT0_RX] = (uint16_t) ((BL_SIZE2) | ((EP0_SIZE/2)<CNTR |= (USB_CNTR_CTRM | USB_CNTR_PMAOVRM | USB_CNTR_ERRM | USB_CNTR_WKUPM | +// USB_CNTR_SUSPM | USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_L1REQM ); + USB->CNTR |= ( USB_CNTR_RESETM ); + //USB control register (USB_ISTR) will indicate what endpoint and direction created the interrupt + //Apparently you don't even need to set the CTRM interrupt as it's not of much use + //The EP0R register creates it's own interrupt which is always enabled upon completion of transfer + //The ITSR is still useful for determining which EP and dir of transfer that occured. + //Having the reset interrupt is vital as apparently the first thing that occurs over the USB bus is a reset. + //Not sure if that's caused by the host intentionally, or just the nature of hot plugging where some + //SOF's are missed during the mating of the connectors or what. Banged my head for awhile till actually + //serviced the reset interrupt as needed + + //Battery charging detector (USB_BCDR) + //Bit 15 DPPU: DP pull-up control + //This bit is set by software to enable the embedded pull-up on the DP line. Clearing it to Î÷Îõ0ÎéÎ÷ + //can be used to signalize disconnect to the host when needed by the user software. + //all other bits have to do with battery charging which is off by default + // + //Enable the data plus pull up resistor to signal to host that USB device is connected + USB->BCDR = USB_BCDR_DPPU; +} + + + + +static uint16_t num_bytes_req; +static uint16_t num_bytes_sending; +static uint16_t num_bytes_expecting; +static uint16_t num_bytes_xfrd; +static uint8_t req_dir; +uint16_t *usbMsgPtr; + +//function gets called after reception of setup packet for IN transfer, +//and each time an interrupt for successful data tx from control EP +//So it's as if this function gets called *AFTER* each transmission +//Therefore it's task is to prep the next transmission should there be one needed +//If we don't need another transmission, prepare to receive status from host +//currently hardcoded for EP0 only +//num_bytes_sending, num_bytes_xfrd, and *usbMsgPtr must be initialized prior to entry + +static void control_xfr_in(){ + //determine if have data remaining to be sent + +// We should never get to this point, if we did there was an error and should prob send STALL +// if ( num_bytes_xfrd == num_bytes_sending ) { +// //no more data to send +// //wrap up transfer and prep endpoint for next setup packet +// // +// //While enabling the last data stage, the opposite direction should be set to NAK, so that, if +// //the host reverses the transfer direction (to perform the status stage) immediately, it is kept +// //waiting for the completion of the control operation. If the control operation completes +// //successfully, the software will change NAK to VALID, otherwise to STALL. At the same time, +// //if the status stage will be an OUT, the STATUS_OUT (EP_KIND in the USB_EPnR register) +// //bit should be set, so that an error is generated if a status transaction is performed with not- +// //zero data. When the status transaction is serviced, the application clears the STATUS_OUT +// //bit and sets STAT_RX to VALID (to accept a new command) and STAT_TX to NAK (to delay +// //a possible status stage immediately following the next setup). +// +// return; +// } + + //copy over 8bytes from transmit data to EP0 buffer + //copy data into EP0 buffer table ram + //usb buffer ram is only accessible in halfwords/bytes (16/8bits) + usb_buff[EP0_TX_BASE] = usbMsgPtr[num_bytes_xfrd/2]; + num_bytes_xfrd += 2; + usb_buff[EP0_TX_BASE+1] = usbMsgPtr[num_bytes_xfrd/2]; + num_bytes_xfrd += 2; + usb_buff[EP0_TX_BASE+2] = usbMsgPtr[num_bytes_xfrd/2]; + num_bytes_xfrd += 2; + usb_buff[EP0_TX_BASE+3] = usbMsgPtr[num_bytes_xfrd/2]; + num_bytes_xfrd += 2; + + //if there aren't 8bytes of data to send, junk will be copied into end of EP0 TX buffer + //to correct for this, simply set tx count to amount of good data + if ( num_bytes_xfrd > num_bytes_sending ) { + //set tx count to number of bytes we actually want to send + usb_buff[USB_COUNT0_TX] = EP0_SIZE - (num_bytes_xfrd - num_bytes_sending); + //stop lying about how many bytes will be sent + num_bytes_xfrd = num_bytes_sending; + } else if ( num_bytes_req < num_bytes_xfrd ) { + //set tx count to number bytes requested since host didn't want everything + usb_buff[USB_COUNT0_TX] = EP0_SIZE - (num_bytes_xfrd - num_bytes_req); + num_bytes_xfrd = num_bytes_req; + } else { + //update tx count + usb_buff[USB_COUNT0_TX] = EP0_SIZE; + } + +// if (num_bytes_xfrd == num_bytes_sending ) { +// //expect next token to be OUT STATUS zero data length from host to end transaction +// //setting EP_KIND to STATUS_OUT: +// //STATUS_OUT: This bit is set by the software to indicate that a status out transaction is +// //expected: in this case all OUT transactions containing more than zero data bytes are +// //answered "STALL" instead of "ACK". This bit may be used to improve the robustness of the +// //application to protocol errors during control transfers and its usage is intended for control +// //endpoints only. When STATUS_OUT is reset, OUT transactions can have any number of +// //bytes, as required. +// +// //Don't really feel like doing this on only the last packet, and really should be fine without it. +// //The host doesn't always take all the data it asks for in the setup packet, sometimes it simply +// //sends an OUT in the midst of large IN xfr asking the device to end current transfer +// //This seems like something we should just do during init of SETUP with IN xfr to follow. +// } + + + //setup EP0R for transmit + USB_EP0R_TX_VALID(); + + return; +} + + //Need to decode the setup packet to determine what type of standard request was made + //Beyondlogic.com's USB in a nutshell is the best resource for this stuff: + //http://www.beyondlogic.org/usbnutshell/usb6.shtml + // + // + //STANDARD DEVICE REQUESTS + //bmRequestType bRequest (1Byte) wValue (2Bytes) wIndex (2Bytes) wLength (2Bytes) Data(based on SETUP) + //1000 0000b GET_STATUS (0x00) Zero Zero Two Device Status +#define STD_REQ_GET_STATUS 0x00 + //0000 0000b CLEAR_FEATURE (0x01) Feature Selector Zero Zero None +#define STD_REQ_CLEAR_FEATURE 0x01 + //0000 0000b SET_FEATURE (0x03) Feature Selector Zero Zero None +#define STD_REQ_SET_FEATURE 0x03 + //0000 0000b SET_ADDRESS (0x05) Device Address Zero Zero None +#define STD_REQ_SET_ADDRESS 0x05 + //1000 0000b GET_DESCRIPTOR (0x06) Descriptor Type & Index Zero or Language ID Descriptor Length Descriptor +#define STD_REQ_GET_DESCRIPTOR 0x06 + //0000 0000b SET_DESCRIPTOR (0x07) Descriptor Type & Index Zero or Language ID Descriptor Length Descriptor +#define STD_REQ_SET_DESCRIPTOR 0x07 + //1000 0000b GET_CONFIGURATION (0x08) Zero Zero 1 Configuration Value +#define STD_REQ_GET_CONFIGURATION 0x08 + //0000 0000b SET_CONFIGURATION (0x09) Configuration Value Zero Zero None +#define STD_REQ_SET_CONFIGURATION 0x09 + // + // + // The Get Status request directed at the device will return two bytes during the data stage with the following format, + // D15 - D2 D1 D0 + // Reserved Remote Wakeup Self Powered + // If D0 is set, then this indicates the device is self powered. If clear, the device is bus powered. If D1 is set, + // the device has remote wakeup enabled and can wake the host up during suspend. The remote wakeup bit can be by the + // SetFeature and ClearFeature requests with a feature selector of DEVICE_REMOTE_WAKEUP (0x01) + // + // Clear Feature and Set Feature requests can be used to set boolean features. When the designated recipient is the device, + // the only two feature selectors available are DEVICE_REMOTE_WAKEUP and TEST_MODE. Test mode allows the device to exhibit + // various conditions. These are further documented in the USB Specification Revision 2.0. + // + // + // Set Descriptor/Get Descriptor is used to return the specified descriptor in wValue. A request for the configuration + // descriptor will return the device descriptor and all interface and endpoint descriptors in the one request. + // Endpoint Descriptors cannot be accessed directly by a GetDescriptor/SetDescriptor Request. + // Interface Descriptors cannot be accessed directly by a GetDescriptor/SetDescriptor Request. + // String Descriptors include a Language ID in wIndex to allow for multiple language support. + // + // Get Configuration/Set Configuration is used to request or set the current device configuration. In the case of a + // Get Configuration request, a byte will be returned during the data stage indicating the devices status. A zero value + // means the device is not configured and a non-zero value indicates the device is configured. + // Set Configuration is used to enable a device. It should contain the value of bConfigurationValue of the desired + // configuration descriptor in the lower byte of wValue to select which configuration to enable. + // + +//void control_xfr_out(uint16_t len){ +// +// usbFunctionWrite( +// +//} + +//flag and value, since can't change address until after STATUS stage, must use this value +//to denote that the USB device address needs updated after the status stage. +static uint8_t new_address = 0; + + +//return number of bytes expected +static uint16_t standard_req_out( usbRequest_t *spacket ){ + + switch ( spacket->bRequest ) { + + //STANDARD DEVICE REQUESTS + //bmRequestType bRequest (1Byte) wValue (2Bytes) wIndex (2Bytes) wLength (2Bytes) Data(based on SETUP) + //0000 0000b CLEAR_FEATURE (0x01) Feature Selector Zero Zero None + case STD_REQ_CLEAR_FEATURE: + break; + + //0000 0000b SET_FEATURE (0x03) Feature Selector Zero Zero None + case STD_REQ_SET_FEATURE: + break; + + //0000 0000b SET_ADDRESS (0x05) Device Address Zero Zero None + // Set Address is used during enumeration to assign a unique address to the USB device. The address is specified in wValue + // and can only be a maximum of 127. This request is unique in that the device does not set its address until after the + // completion of the status stage. (See Control Transfers.) All other requests must complete before the status stage. + case STD_REQ_SET_ADDRESS: + new_address = spacket->wValue; + usb_buff[LOG0] = new_address; + return 0; + break; + + //0000 0000b SET_DESCRIPTOR (0x07) Descriptor Type & Index Zero or Language ID Descriptor Length Descriptor + case STD_REQ_GET_CONFIGURATION: + break; + + //0000 0000b SET_CONFIGURATION (0x09) Configuration Value Zero Zero None + case STD_REQ_SET_CONFIGURATION: + break; + + default: + //ERROR send STALL? + break; + + } + + + +} + +static uint16_t standard_req_in( usbRequest_t *spacket ){ + + switch ( spacket->bRequest ) { + + //STANDARD DEVICE REQUESTS + //bmRequestType bRequest (1Byte) wValue (2Bytes) wIndex (2Bytes) wLength (2Bytes) Data(based on SETUP) + //1000 0000b GET_STATUS (0x00) Zero Zero Two Device Status + case STD_REQ_GET_STATUS: + break; + + //1000 0000b GET_DESCRIPTOR (0x06) Descriptor Type & Index Zero or Language ID Descriptor Length Descriptor + case STD_REQ_GET_DESCRIPTOR: + switch ( (spacket->wValue & DESC_TYPE_MASK)>>8) { //must mask out upper byte and shift to get desc type + case DESC_TYPE_DEVICE: + usbMsgPtr = (uint16_t *)device_desc; + return device_desc[bLength]; + case DESC_TYPE_CONFIG: //Must return all config, interface, and endpoint descriptors in one shot + usbMsgPtr = (uint16_t *)config_desc; + return config_desc[wTotalLength]; + case DESC_TYPE_STRING: + //determine which string index + switch ( spacket->wValue & DESC_IDX_MASK ) { //Must mask out index from lower byte + case 0: usbMsgPtr = (uint16_t *)string0_desc; + return string0_desc[bLength]; + case 1: usbMsgPtr = (uint16_t *)string1_desc; + return string1_desc[bLength]; + case 2: usbMsgPtr = (uint16_t *)string2_desc; + return string2_desc[bLength]; + default: //error send stall + return 0; + } + // interface and endpoint descriptors can't be accessed directly, get them via config desc + // case DESC_TYPE_INTERFACE: + // usbMsgPtr = (uint16_t *)interface_desc; + // return interface_desc[bLength]; + // case DESC_TYPE_ENDPOINT: + // usbMsgPtr = (uint16_t *)endpoint_desc; + // return endpoint_desc[bLength]; + default: + //TODO error send stall + return 0; + } + + //1000 0000b GET_CONFIGURATION (0x08) Zero Zero 1 Configuration Value + case STD_REQ_GET_CONFIGURATION: + break; + + } + + //just return device descriptor for now + + +} + +//USB IRQ handler calls this function after recieving a control setup packet +//function is responsible for preparing follow on data/status transfers to complete control xfr +//must set everything up for control_xfr_in/out functions to be called during data packets +static void control_xfr_init( usbRequest_t *spacket ) { + + //determine number of requested data payload bytes + num_bytes_req = spacket->wLength; + num_bytes_xfrd = 0; + + //Vusb calls usbFunctionSetup which sets usbMsgPtr to point to IN data array + //and returns length of data to be returned. + //Vusb needs nothing else for IN transfers as it already has the data + //Vusb calls usbFunctionWrite for OUT xfr on subsequent of data packet arrival (8bytes max) + + //if data is IN (tx) need to aquire pointer to data that we'd like to transmit + //don't think we'll get a zero data length IN as that would mean the host sends all packets + //I suppose this is possible for poorly written host application..? + //Vusb had option to provide function that would be called for each IN data packet + //I found that to be slow and best avoided, so not going to bother supporting that for now.. + //Also need to get amount of data that the device would like to return, possible the + //device has less data to send back than requested in wLength. + + +/*USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]); + * If the SETUP indicates a control-in transfer, you should provide the + * requested data to the driver. There are two ways to transfer this data: + * (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data + * block and return the length of the data in 'usbFunctionSetup()'. The driver + * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The + * driver will then call 'usbFunctionRead()' when data is needed. See the + * documentation for usbFunctionRead() for details. + * + * If the SETUP indicates a control-out transfer, the only way to receive the + * data from the host is through the 'usbFunctionWrite()' call. If you + * implement this function, you must return USB_NO_MSG in 'usbFunctionSetup()' + * to indicate that 'usbFunctionWrite()' should be used. See the documentation + * of this function for more information. If you just want to ignore the data + * sent by the host, return 0 in 'usbFunctionSetup()'. + */ + //setup packets not handled by standard requests sent to usbFunctionSetup (just like Vusb) + if ((spacket->bmRequestType & REQ_TYPE) != REQ_TYPE_STD) { + //function must set usbMsgPtr to point to return data for IN transfers + num_bytes_sending = usbFunctionSetup( (uint8_t*) spacket ); + } + + + if ( (spacket->bmRequestType & REQ_DIR) == REQ_DIR_IN ) { + //IN transfer Host wants us to send data (tx) + switch ( spacket->bmRequestType & REQ_TYPE ) { + case REQ_TYPE_STD: + num_bytes_sending = standard_req_in( spacket ); + break; + // case REQ_TYPE_CLASS: + // num_bytes_sending = 0;//class_req_in( spacket ); + // break; + // case REQ_TYPE_VEND: + // num_bytes_sending = 0;//vendor_req_in( spacket ); + // break; + // case REQ_TYPE_RES: + // default: + // num_bytes_sending = 0; + // break; + } + //A USB device can determine the number and + //direction of data stages by interpreting the data transferred in the SETUP stage, and is + //required to STALL the transaction in the case of errors. To do so, at all data stages before + //the last, the unused direction should be set to STALL, so that, if the host reverses the + //transfer direction too soon, it gets a STALL as a status stage. + // + //WRONG!!! This ended up being a shot in the foot. The VERY first request from the host is a + //SETUP device descriptor request for 16KBytes worth of data!! + //HOWEVER, the host tells us the device to shut it's mouth after the first data stage as if + //it doesn't want any more info by sending a STATUS state (OUT xfr expecting zero data) + //So we need to be ready for this condition and be prepared to recieve a STATUS OUT zero data "shutup" command + //Maybe this is only an issue for standard type requests during enumeration..? + // + //Need to set RX to stall it should be NAK right now + + //TODO decide if want to set EP_KIND to STATUS_OUT during this time. I don't think there is much benefit + //currently and will cause more hassle than it's worth currently, since have to ensure it's clear for other OUT xfrs + USB_EP0R_RX_VALID_STATUS_OUT(); + + //TODO decide if want to set EP0_RX_COUNT to 0 so we can only receive STATUS OUT with zero data, however that + //is effectively what EP_KIND= STATUS_OUT is intended for.. I don't think RX count matters since it can't overflow + + //Now we've got the pointer to return data initialized + //and number of bytes the firmware would like to return + control_xfr_in(); + + } else { + //OUT transfer Host is sending us data (rx) + //if data is OUT (rx) need a function pointer of what to call when data is received + //or if there is no data stage, we just need to send status packet + + //num_byte_req contains number of bytes expected to be transferred in upcoming OUT xfrs + + switch ( spacket->bmRequestType & REQ_TYPE ) { + case REQ_TYPE_STD: + num_bytes_expecting = standard_req_out( spacket ); + break; + // case REQ_TYPE_CLASS: + // //num_bytes_sending = 0;//class_req_in( spacket ); + // //break; + // case REQ_TYPE_VEND: + // //num_bytes_sending = 0;//vendor_req_in( spacket ); + // //num_bytes_sending = usbFunctionSetup( spacket ); + // break; + // case REQ_TYPE_RES: + // default: + // //num_bytes_sending = 0; + // break; + } + + //Clear EP_KIND so OUT transfers of any length are accepted + USB_EP0R_EP_KIND_ANY(); + + //TODO if there is no DATA stage, then we expect the next token to be IN + //in which case device need to be prepared to send IN transfer of zero data length + + //prepare IN STATUS packet of zero length + usb_buff[USB_COUNT0_TX] = 0; + //enable any packet + USB_EP0R_RXTX_VALID(); + + + + //control_xfr_out(); + } + +} + + + + +//This is the ISR that gets called for USB interrupts + //At the end of the transaction, an endpoint-specific interrupt is generated, reading status registers + //and/or using different interrupt response routines. The microcontroller can determine: + // -which endpoint has to be served, + // -which type of transaction took place, if errors occurred (bit stuffing, format, CRC, + // protocol, missing ACK, over/underrun, etc.). + + //USB interrupt status register (USB_ISTR) + //This register contains the status of all the interrupt sources allowing application + //software to determine, which events caused an interrupt request. +void USB_IRQHandler(void) +{ + + //all interrupts enabled by USB_CNTR, plus any successful rx/tx to an endpoint triggers this ISR + + //should be our goal to get out of this ISR asap, signal the transaction to the main thread + //and let the main thread process the data. + //That isn't really how V-usb is setup which we're looking to replace and be compatible with for starters. + //So for now this isn't going to be setup ideally, but if USB is our top priority then maybe it's not so bad.. + + //Plan is to determine source of interrupt + //Service what's needed for the interrupt + //Clear the pending/active interrupts which have been serviced + //If there are other interrupts occuring simulateously we don't have to catch em all + // they'll trigger this ISR again + //Return from interrupt + + //First check for successful transfer of USB packets + //High level we can determine this by USB_ISTR: + // CTR:set if correct transfer occured (read only, cleared via the EP) + // DIR: 0-TX, 1-RX + // EP_ID[3:0]: endpoint that triggered the interrupt with following priority: + // -isosync & double-buffered bulk are considered first getting hi pri + // -then EPnR register number ie EP0R gets priority over EP2R + // NOTE: you can put whatever endpoint number in whichever register you choose + // endpoint0 doesn't have to go in EP0R register, the endpoint number is programmable! + // would probably make more sense if they used letters to define EPnR registers.. + //Low level we don't have to use EP_ID's priority assignments we could just check EPnR CTR_RX/TX bits + //Kinda like EP_ID though as it allows us to focus on a single EP for the given ISR call + + //CAUTION!!! usb_buff data can only be accessed in half words, or bytes. No 32bit accesses!!! + + usbRequest_t *setup_packet; + uint8_t endpoint_num; + + + //only have EP0 for now + + //check for OUT/SETUP + if ( USB->EP0R & USB_EP_CTR_RX ) { + + + //clear RX interrupt leave everything else unaffected, reference manual says this should be the first thing + //we do, but with control endpoints, any subsequent SETUP will stomp over the prior one if CTR_RX is clear + //It'll stomp it even if STAT is set to STALL/NAK, setting to DISABLE is only way to prevent it.. + //If last setup data is vital to maintain it should be stored more permanently somewhere besides buffer ram. + EP0R_CLR_CTR_RX(); + //Note: clearing CTR_RX on a control EP, is enough for another setup packet to be accepted + //this is true even if STAT_RX is STALL/NAK, so if the data needs retained it must be copied + //elsewhere, or set STAT_RX to DISABLED to keep it from being stomped by the next setup + + if ( USB->EP0R & USB_EP_SETUP ) { //SETUP packet + log ++; //inc log for each setup packet used for debugging purposes to trigger logic analyzer at desired packet +#define LOG_COUNT 3 +// if ( log >= LOG_COUNT) { DEBUG_HI(); DEBUG_LO(); } +//usb_buff[LOG0] = USB->EP0R; + //set pointer to usb buffer, type ensures 8/16bit accesses to usb_buff + setup_packet = (void*) &usb_buff[EP0_RX_BASE]; + req_dir = (setup_packet->bmRequestType & REQ_DIR); //set to REQ_DIR_IN/OUT for data stage dir + control_xfr_init( setup_packet ); + + } else { //OUT packet +// if ( log >= LOG_COUNT) { DEBUG_HI(); DEBUG_LO(); } + //number of bytes received is denoted in USB_COUNTn_RX buffer table + //control_xfr_out(); + usbFunctionWrite((uint8_t*) &usb_buff[EP0_RX_BASE], (usb_buff[USB_COUNT0_RX] & RX_COUNT_MSK)); + } + + + } else if ( USB->EP0R & USB_EP_CTR_TX ) { //IN packet +// if ( log >= LOG_COUNT) { DEBUG_HI(); DEBUG_LO(); } +//DEBUG_HI(); DEBUG_LO(); + // log ++; + //LED_ON(); + // if (log >= 2) { + // LED_ON(); + // } + //Servicing of the CTR_TX event starts clearing the interrupt bit; + +//usb_buff[LOG4] = USB->EP0R; + //clear TX interrupt + EP0R_CLR_CTR_TX(); + //USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX) //set rx field to keep from accidentally clearing + // & USB_EPREG_MASK ) //mask out toggle feilds making them zero + // & ~USB_EP_CTR_TX ); //clear tx bit removing active interrupt + +// LED_ON(); +//usb_buff[LOG8] = USB->EP0R; + + //the application software then prepares another buffer full of data to be sent, + //updates the COUNTn_TX table location with the number of byte to be transmitted during the next transfer, + //and finally sets STAT_TX to 11 (VALID) to re-enable transmissions. + //this is only done if the IN transfer had data, if there was no data, it was a status stage + //if ( (usb_buff[USB_COUNT0_RX] & RX_COUNT_MSK) != 0 ) { + if ( req_dir == REQ_DIR_IN ) { + control_xfr_in(); + } else { + //OUT request, IN denotes STATUS stage + + //check if USB device address needs set must be after completion of STATUS stage + if (new_address) { + USB->DADDR = (new_address | USB_DADDR_EF); //update address and keep USB function enabled + new_address = 0; //clear flag value so don't come back here again + //LED_ON(); + } + } + +//usb_buff[LOGC] = USB->EP0R; +//usb_buff[LOG10] = log; + //While the STAT_TX bits are equal to 10 (NAK), any IN request addressed to that endpoint is NAKed, + //indicating a flow control condition: the USB host will retry the transaction until it succeeds. + //It is mandatory to execute the sequence of operations in the above mentioned order to avoid losing the + //notification of a second IN transaction addressed to the same endpoint immediately following the one + //which triggered the CTR interrupt. + + //I wasn't doing things in this order thinking that explains why I can't get a second transfer out + + } + + if ( USB->ISTR & USB_ISTR_RESET ) { //USB reset event occured + //Anytime a reset condition occurs, the EPnR registers are cleared + //Must re-enable the USB function and setup EP0 after any reset condition within 10msec + usb_reset_recovery(); + //handled in reset recovery: USB->ISTR &= ~USB_ISTR_RESET; + } + +} + diff --git a/firmware/source_stm_only/usbstm.h b/firmware/source_stm_only/usbstm.h new file mode 100644 index 0000000..a7e1c56 --- /dev/null +++ b/firmware/source_stm_only/usbstm.h @@ -0,0 +1,249 @@ +#ifndef _usbstm_h +#define _usbstm_h + + +//include target chip port definition library files +#include + + +//clear RX interrupt +//set tx field to keep from accidentally clearing //mask out toggle feilds making them zero //clear rx bit removing active interrupt +#define EP0R_CLR_CTR_RX() USB->EP0R = (((USB->EP0R | USB_EP_CTR_TX) & USB_EPREG_MASK ) & ~USB_EP_CTR_RX ) + +//clear TX interrupt +#define EP0R_CLR_CTR_TX() USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX) & USB_EPREG_MASK ) & ~USB_EP_CTR_TX ) + +//VALID need to get both status bits set +//XOR the current value of status bits with 1 to write back inverted value, gets all status bits set +// OR in bits that need set, AND in bits to keep or avail for XOR, XOR toggles to invert +#define USB_EP0R_RXTX_VALID() USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & ~(USB_EP_DTOG_RX | USB_EP_DTOG_TX)) ^ (USB_EPTX_STAT | USB_EPRX_STAT)) +#define USB_EP0R_RX_VALID() USB->EP0R = ((((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX)) & (USB_EPREG_MASK | USB_EPRX_STAT)) ^ USB_EPRX_STAT ) +#define USB_EP0R_TX_VALID() USB->EP0R = ((((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX)) & (USB_EPREG_MASK | USB_EPTX_STAT)) ^ USB_EPTX_STAT ) +#define USB_EP0R_RX_VALID_STATUS_OUT() USB->EP0R = ((((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX | USB_EP_KIND)) & (USB_EPREG_MASK | USB_EPRX_STAT)) ^ USB_EPRX_STAT ) +#define USB_EP0R_EP_KIND_ANY() USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX)) & (USB_EPREG_MASK & ~USB_EP_KIND)) + +//DISABLE need to get both bits cleared +//write back current value of status bits to toggle all 1's to zeros +// OR in bits that need set AND in bits to keep or toggle from 1 to 0 +#define USB_EP0R_RXTX_DIS() USB->EP0R = ((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & ~(USB_EP_DTOG_RX | USB_EP_DTOG_TX)) +#define USB_EP0R_RX_DIS() USB->EP0R = ((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK | USB_EPRX_STAT)) +#define USB_EP0R_TX_DIS() USB->EP0R = ((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK | USB_EPTX_STAT)) + +//NAK/STALL need to get one bit set, and the other cleared +//Easiest way would be to DISABLE, and then set desired bit, uses two accesses to EP0R +// DISABLE first OR in bits that need set AND in bits to keep or toggle +#define USB_EP0R_RX_NAK() USB_EP0R_RX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_RX_NAK) +#define USB_EP0R_TX_NAK() USB_EP0R_TX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_TX_NAK) +#define USB_EP0R_RXTX_NAK() USB_EP0R_RXTX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | (USB_EP_RX_NAK | USB_EP_TX_NAK)) + +#define USB_EP0R_RX_STALL() USB_EP0R_RX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_RX_STALL) +#define USB_EP0R_TX_STALL() USB_EP0R_TX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | USB_EP_TX_STALL) +#define USB_EP0R_RXTX_STALL() USB_EP0R_RXTX_DIS(); USB->EP0R = (((USB->EP0R | USB_EP_CTR_RX | USB_EP_CTR_TX) & (USB_EPREG_MASK)) | (USB_EP_RX_STALL | USB_EP_TX_STALL)) + +//USB_COUNTn_RX table entries are a little annoying.. +//create some macros to simplify setting RX COUNT +#define BL_SIZE32 (uint16_t) 0x8000 +#define BL_SIZE2 (uint16_t) 0x0000 +#define NUM_BLOCKS 10U //shift number of blocks by this amount +#define RX_COUNT_MSK (uint16_t) 0x03FF + +// Cannot setup for 0 bytes to be received, that's equivalent of STATUS OUT packet which isn't a true data reception +#define _ADDRX_SET(oper) _DATA_OP(); DATA_OUT = oper; _AXL_CLK(); _DATA_IP(); +#define USB_RX_2TO62_MUL2B(oper) ((uint16_t) ((BL_SIZE2) | ((oper/2)<