Successfully building avr & stm core with one set of files.

Two different Makefiles, specify which with -f file flag:
make -f Make_avr clean program
make -f Make_stm clean program

made release dir to put released .hex firmware files
Need to make separate avr build folder
Need to make one master Makefile that calls one of the other makefiles as
instructed.

Currently device is recognized by PC but does nothing else other than
being recognized by app during connection process:

arm-none-eabi-size -t build_stm/inlretro_stm.elf
text    data     bss     dec     hex filename
1332       0      20    1352     548 build_stm/inlretro_stm.elf
1332       0      20    1352     548 (TOTALS)

avr-size avr_kazzo.elf
text    data     bss     dec     hex filename
1496       2      43    1541     605 avr_kazzo.elf
This commit is contained in:
Paul Molloy 2017-07-22 17:03:23 -05:00
parent 895bd6a737
commit 3779afe88d
28 changed files with 16826 additions and 107 deletions

View File

@ -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)

100
firmware/Make_stm Normal file
View File

@ -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)

View File

@ -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/

Binary file not shown.

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -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.

File diff suppressed because it is too large Load Diff

View File

@ -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 <stdint.h>
#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.<br>
Function definitions in header files are used to allow 'inlining'.
\li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
Unions are used for effective representation of core registers.
\li Advisory Rule 19.7, Function-like macro defined.<br>
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
<strong>IO Type Qualifiers</strong> 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 <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
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 */

View File

@ -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 <cmsis_iar.h>
/*------------------ TI CCS Compiler -------------------*/
#elif defined ( __TMS470__ )
#include <cmsis_ccs.h>
/*------------------ 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 <cmsis_csm.h>
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */

View File

@ -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 <cmsis_iar.h>
/*------------------ TI CCS Compiler -------------------*/
#elif defined ( __TMS470__ )
#include <cmsis_ccs.h>
/*------------------ 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 <cmsis_csm.h>
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CMINSTR_H */

View File

@ -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")
}

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
/**
******************************************************************************
* @file stm32f0xx.h
* @author MCD Application Team
* @version V2.3.1
* @date 04-November-2016
* @brief CMSIS STM32F0xx Device Peripheral Access Layer Header File.
*
* The file is the unique include file that the application programmer
* is using in the C source code, usually in main.c. This file contains:
* - Configuration section that allows to select:
* - The STM32F0xx device used in the target application
* - To use or not the peripherals drivers in application code(i.e.
* code will be based on direct access to peripherals registers
* rather than drivers API), this option is controlled by
* "#define USE_HAL_DRIVER"
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
*
* 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****/

View File

@ -1,15 +1,24 @@
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include "usbdrv.h"
//#include "io.h"
//#include "pinport.h"
//#include "buffer.h"
#include "usb.h"
#ifdef AVR_CORE
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include "usbdrv.h"
#endif
#ifdef STM_CORE
#include <stm32f0xx.h>
#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

View File

@ -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;
}

View File

@ -1,13 +1,30 @@
#ifndef _usb_h
#define _usb_h
#include <avr/io.h>
#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 <avr/io.h>
#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
*/

View File

@ -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
}

View File

@ -0,0 +1,5 @@
#include <stm32f0xx.h>
void init_clock();

View File

@ -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

View File

@ -0,0 +1,959 @@
#include "usbstm.h"
#include "usb_descriptors.h"
static int log = 0;
//include target board library files
//this is junk... #include <stm32f072b_discovery.h>
//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<<LED))
//#define LED_OFF() (GPIO_LED->ODR &= ~(0x1U<<LED))
//
//#define DEBUG_HI() (GPIO_DEBUG->ODR |= (0x1U<<DEBUG))
//#define DEBUG_LO() (GPIO_DEBUG->ODR &= ~(0x1U<<DEBUG))
//Here's where the LEDs and switch are located
//PA0 user switch
//#define SWITCH (0U)
//pick define based on xtal setup for init_clock and init_usb_clock functions
//#define NO_XTAL
#define XTAL_16Mhz
void init_usb_clock()
{
// stm32f0x2 devices have HSI 48Mhz available to clock usb block, or PLL if it's source accurate enough
// stm32f0x0 devices must have ext xtal and use PLL output to drive usb block
#ifdef XTAL_16Mhz
//by default the 072 has HSI 48Mhz selected as USB clock
//on the 070 this equates to off, so 070 must set USBSW bit
RCC->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<<IOPAEN);
// set GPIO alternate function to USB
// Can't find the USB alternate function mapping on the datasheets!
// Not sure how this is supposed to work..
// Considering the USB PHY are terminated, they don't lend themselves well to the basic GPIO structure
// which can be taken over by common alternate functions. Wondering if the PHY are hardwired to the pins.
// If that were the case, then really just need to make sure the USB GPIO are left floating inputs at reset/default.
// Can't find anything in the datasheet that explains this so I'm left to assume there's nothing to do
// As the only other thing I can do is take wild stabs in the dark as to what alternate function mapping is needed..
// Considering the USB PHY has it's own power and clock supply, this logic seems reasonable enough
//reset USB device and release, don't think this is needed, but I'm at a loss of what's wrong...
// RCC->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)<<NUM_BLOCKS)) ; //set EP0 to 8 bytes
//usb_buff[USB_COUNT0_RX] = USB_RX_8BYTES; //set EP0 to 8 bytes
usb_buff[USB_COUNT0_RX] = USB_RX_2TO62_MUL2B(EP0_SIZE); //set EP0 to 8 bytes or whatever it's defined as
//Clear buffers for debug purposes
// usb_buff[EP0_TX_BASE] = (uint16_t) 0x1111;
// usb_buff[EP0_TX_BASE+1] = (uint16_t) 0x2222;
// usb_buff[EP0_TX_BASE+2] = (uint16_t) 0x3333;
// usb_buff[EP0_TX_BASE+3] = (uint16_t) 0x4444;
//
// usb_buff[EP0_RX_BASE] = (uint16_t) 0x5555;
// usb_buff[EP0_RX_BASE+1] = (uint16_t) 0x6666;
// usb_buff[EP0_RX_BASE+2] = (uint16_t) 0x7777;
// usb_buff[EP0_RX_BASE+3] = (uint16_t) 0x8888;
//All registers not specific to any endpoint must be initialized according to the needs of application software
//(choice of enabled interrupts, chosen address of packet buffers, etc.).
//Then the process continues as for the USB reset case (see further paragraph).
//initialize all registers not specific to any endpoint
//
//LPM control and status register (USB_LPMCSR)
//Link power management, this is disabled by default, lets leave it that way.
//now all the registers and buffers are setup so endpoint specific registers can be set
usb_reset_recovery();
NVIC_EnableIRQ( USB_IRQn );
//enable interrupts
//USB control register (USB_CNTR)
//only enable interrupts for correct transfers for now
// USB->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;
}
}

View File

@ -0,0 +1,249 @@
#ifndef _usbstm_h
#define _usbstm_h
//include target chip port definition library files
#include <stm32f0xx.h>
//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)<<NUM_BLOCKS)))
#define USB_RX_32TO992_MUL32B(oper) ((uint16_t) ((BL_SIZE32) | ((oper/32-1)<<NUM_BLOCKS)))
//#define USB_RX_2BYTES ((uint16_t) ((BL_SIZE2) | ((2/2)<<NUM_BLOCKS)))
//#define USB_RX_4BYTES ((uint16_t) ((BL_SIZE2) | ((4/2)<<NUM_BLOCKS)))
//#define USB_RX_6BYTES ((uint16_t) ((BL_SIZE2) | ((6/2)<<NUM_BLOCKS)))
//#define USB_RX_8BYTES ((uint16_t) ((BL_SIZE2) | ((8/2)<<NUM_BLOCKS)))
//#define USB_RX_16BYTES ((uint16_t) ((BL_SIZE2) | ((16/2)<<NUM_BLOCKS)))
//// Can set from 2-62B in increments of 2B, just haven't bothered defining them all here...
//#define USB_RX_32BYTES ((uint16_t) ((BL_SIZE32) | ((32/32-1)<<NUM_BLOCKS)))
//#define USB_RX_64BYTES ((uint16_t) ((BL_SIZE32) | ((64/32-1)<<NUM_BLOCKS)))
//#define USB_RX_96BYTES ((uint16_t) ((BL_SIZE32) | ((96/32-1)<<NUM_BLOCKS)))
//#define USB_RX_128BYTES ((uint16_t) ((BL_SIZE32) | ((128/32-1)<<NUM_BLOCKS)))
//#define USB_RX_256BYTES ((uint16_t) ((BL_SIZE32) | ((256/32-1)<<NUM_BLOCKS)))
//#define USB_RX_512BYTES ((uint16_t) ((BL_SIZE32) | ((512/32-1)<<NUM_BLOCKS)))
//// Can set from 32-992B in increments of 32B, just haven't bothered defining them all here...
//#define USB_RX_992BYTES ((uint16_t) ((BL_SIZE32) | ((992/32-1)<<NUM_BLOCKS)))
// while 1024 is max size of packet for USB 2.0, this part's designed USB buffer memory
// creates the limit of 992B xfr buffer + 32B buffer table (also in buffer ram) = 1024B size of USB buffer ram
//buffer table itself is located in 1KB buffer above, but it's location is programmable
#define USB_BTABLE_BASE ((uint16_t) 0x0000) //least 3 significant bits are forced to zero
#define USB_BTABLE_SIZE 64 //32x 16bit halfwords
//Endpoint 0: setup as 8Bytes TX & RX following buffer table
// endpoint 0 size defined in usb_descriptors.h as it's needed there
//#define EP0_SIZE 0x08 //8Bytes same as usb 1.1 for now
#define EP0_TX_ADDR (USB_BTABLE_BASE + USB_BTABLE_SIZE)
#define EP0_TX_BASE (EP0_TX_ADDR / 2)
//NOTE!!! control_xfr functions are hardcoded for EP0 size of 8Bytes currently, must update if changing
#define EP0_RX_ADDR (EP0_TX_ADDR + EP0_SIZE)
#define EP0_RX_BASE (EP0_RX_ADDR / 2)
//#define LOG0 (EP0_RX_ADDR + EP0_SIZE)
#define LOG0 (64+16) / 2
#define LOG4 LOG0 + 2
#define LOG8 LOG0 + 4
#define LOGC LOG0 + 6
#define LOG10 LOG0 + 8
//Transmission buffer address n (USB_ADDRn_TX)
//Address offset: [USB_BTABLE] + n*8
//Note: In case of double-buffered or isochronous endpoints in the IN direction, this address location is referred to as USB_ADDRn_TX_0.
//In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is used for USB_ADDRn_RX_0.
#define USB_ADDR0_TX (USB_BTABLE_BASE + 0*8)
#define USB_ADDR1_TX (USB_BTABLE_BASE + 1*8)
#define USB_ADDR2_TX (USB_BTABLE_BASE + 2*8)
#define USB_ADDR3_TX (USB_BTABLE_BASE + 3*8)
#define USB_ADDR4_TX (USB_BTABLE_BASE + 4*8)
#define USB_ADDR5_TX (USB_BTABLE_BASE + 5*8)
#define USB_ADDR6_TX (USB_BTABLE_BASE + 6*8)
#define USB_ADDR7_TX (USB_BTABLE_BASE + 7*8)
//Bits 15:1 ADDRn_TX[15:1]: Transmission buffer address
//These bits point to the starting address of the packet buffer containing data to be transmitted
//by the endpoint associated with the USB_EPnR register at the next IN token addressed to it.
//Bit 0 Must always be written as Î÷Îõ0 since packet memory is half-word wide and all packet buffers
//must be half-word aligned.
//Transmission byte count n (USB_COUNTn_TX)
//Address offset: [USB_BTABLE] + n*8 + 2
//Note: In case of double-buffered or isochronous endpoints in the IN direction, this address location is referred to as USB_COUNTn_TX_0.
//In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is used for USB_COUNTn_RX_0.
#define USB_COUNT0_TX (USB_BTABLE_BASE + 0*8 + 1)
#define USB_COUNT1_TX (USB_BTABLE_BASE + 1*8 + 1)
#define USB_COUNT2_TX (USB_BTABLE_BASE + 2*8 + 1)
#define USB_COUNT3_TX (USB_BTABLE_BASE + 3*8 + 1)
#define USB_COUNT4_TX (USB_BTABLE_BASE + 4*8 + 1)
#define USB_COUNT5_TX (USB_BTABLE_BASE + 5*8 + 1)
#define USB_COUNT6_TX (USB_BTABLE_BASE + 6*8 + 1)
#define USB_COUNT7_TX (USB_BTABLE_BASE + 7*8 + 1)
//Bits 15:10These bits are not used since packet size is limited by USB specifications to 1023 bytes. Their
//value is not considered by the USB peripheral.
//Bits 9:0 COUNTn_TX[9:0]: Transmission byte count
//These bits contain the number of bytes to be transmitted by the endpoint associated with the
//USB_EPnR register at the next IN token addressed to it.
//Reception buffer address n (USB_ADDRn_RX)
//Address offset: [USB_BTABLE] + n*8 + 4
//Note: In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is referred to as USB_ADDRn_RX_1.
//In case of double-buffered or isochronous endpoints in the IN direction, this address location is used for USB_ADDRn_TX_1.
#define USB_ADDR0_RX (USB_BTABLE_BASE + 0*8 + 2)
#define USB_ADDR1_RX (USB_BTABLE_BASE + 1*8 + 2)
#define USB_ADDR2_RX (USB_BTABLE_BASE + 2*8 + 2)
#define USB_ADDR3_RX (USB_BTABLE_BASE + 3*8 + 2)
#define USB_ADDR4_RX (USB_BTABLE_BASE + 4*8 + 2)
#define USB_ADDR5_RX (USB_BTABLE_BASE + 5*8 + 2)
#define USB_ADDR6_RX (USB_BTABLE_BASE + 6*8 + 2)
#define USB_ADDR7_RX (USB_BTABLE_BASE + 7*8 + 2)
//Bits 15:1 ADDRn_RX[15:1]: Reception buffer address
//These bits point to the starting address of the packet buffer, which will contain the data
//received by the endpoint associated with the USB_EPnR register at the next OUT/SETUP
//token addressed to it.
//Bit 0 This bit must always be written as Î÷Îõ0 since packet memory is half-word wide and all packet
//buffers must be half-word aligned.
//Reception byte count n (USB_COUNTn_RX)
//Address offset: [USB_BTABLE] + n*8 + 6
//Note: In case of double-buffered or isochronous endpoints in the OUT direction, this address
//location is referred to as USB_COUNTn_RX_1.
//In case of double-buffered or isochronous endpoints in the IN direction, this address location is used for USB_COUNTn_TX_1.
#define USB_COUNT0_RX (USB_BTABLE_BASE + 0*8 + 3)
#define USB_COUNT1_RX (USB_BTABLE_BASE + 1*8 + 3)
#define USB_COUNT2_RX (USB_BTABLE_BASE + 2*8 + 3)
#define USB_COUNT3_RX (USB_BTABLE_BASE + 3*8 + 3)
#define USB_COUNT4_RX (USB_BTABLE_BASE + 4*8 + 3)
#define USB_COUNT5_RX (USB_BTABLE_BASE + 5*8 + 3)
#define USB_COUNT6_RX (USB_BTABLE_BASE + 6*8 + 3)
#define USB_COUNT7_RX (USB_BTABLE_BASE + 7*8 + 3)
//This table location is used to store two different values, both required during packet
//reception. The most significant bits contains the definition of allocated buffer size, to allow
//buffer overflow detection, while the least significant part of this location is written back by the
//USB peripheral at the end of reception to give the actual number of received bytes. Due to the
//restrictions on the number of available bits, buffer size is represented using the number of allocated
//memory blocks, where block size can be selected to choose the trade-off between fine-granularity/small-buffer
//and coarse-granularity/large-buffer. The size of allocated buffer is a part of the endpoint descriptor
//and it is normally defined during the enumeration process according to its maxPacketSize parameter value
//(See ÎéÎíUniversal Serial Bus SpecificationÎéÎí).
//
//Bit 15 BL_SIZE: Block size
//This bit selects the size of memory block used to define the allocated buffer area.
// -If BL_SIZE=0, the memory block is 2-byte large, which is the minimum block
// allowed in a half-word wide memory. With this block size the allocated buffer size
// ranges from 2 to 62 bytes.
// -If BL_SIZE=1, the memory block is 32-byte large, which allows to reach the
// maximum packet length defined by USB specifications. With this block size the
// allocated buffer size theoretically ranges from 32 to 1024 bytes, which is the longest
// packet size allowed by USB standard specifications. However, the applicable size is limited by the available buffer memory.
//
//Bits 14:10 NUM_BLOCK[4:0]: Number of blocks
//These bits define the number of memory blocks allocated to this packet buffer. The actual amount of
//allocated memory depends on the BL_SIZE value as illustrated in Table127.
//
//Bits 9:0 COUNTn_RX[9:0]: Reception byte count
//These bits contain the number of bytes received by the endpoint associated with the
//USB_EPnR register during the last OUT/SETUP transaction addressed to it.
//#define __packed __attribute((packed))__
typedef struct usbRequest_t{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
}usbRequest_t;
//}__attribute((__packed__))usbRequest_t;
// bmRequestType
//D7 Data Phase Transfer Direction
//0 = Host to Device
//1 = Device to Host
#define REQ_DIR 0x80
#define REQ_DIR_OUT 0x00
#define REQ_DIR_IN 0x80
//D6..5 Type
//0 = Standard
//1 = Class
//2 = Vendor
//3 = Reserved
#define REQ_TYPE 0x60
#define REQ_TYPE_STD 0x00
#define REQ_TYPE_CLASS 0x20
#define REQ_TYPE_VEND 0x40
#define REQ_TYPE_RES 0x60
//D4..0 Recipient
//0 = Device
//1 = Interface
//2 = Endpoint
//3 = Other
#define REQ_RECIP 0x0F
#define REQ_RECIP_DEV 0x00
#define REQ_RECIP_INT 0x01
#define REQ_RECIP_EP 0x02
#define REQ_RECIP_OTH 0x03
//4..31 = Reserved
#define usbMsgPtr_t uint16_t
extern uint16_t *usbMsgPtr;
extern uint16_t usbFunctionSetup(uint8_t data[8]);
extern uint8_t usbFunctionWrite(uint8_t *data, uint8_t len);
void init_clock();
void init_usb_clock();
void usb_reset_recovery();
void init_usb();
#endif