Initial checkin (cdcacm).
This commit is contained in:
commit
f767e7d75b
12 changed files with 893 additions and 0 deletions
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.o
|
||||
*.d
|
||||
*.elf
|
||||
*.hex
|
||||
*.bin
|
||||
*.map
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "libopencm3"]
|
||||
path = libopencm3
|
||||
url = https://github.com/libopencm3/libopencm3
|
57
README.md
Normal file
57
README.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
A few examples of code for [the bat board], using [libopencm3].
|
||||
|
||||
Most of them are just modified examples from the official [libopencm3 examples].
|
||||
|
||||
They aren't too specific for the bat boards, except the usual pinout considerations. What's sometimes not so easy to change/adapt is the chip. These examples are for STM32 F072 and L052.
|
||||
|
||||
## Short summary for the examples
|
||||
|
||||
### usb_cdcacm
|
||||
|
||||
The board presents itself as a serial port (CDC). It echoes back what it receives; toggling the LED after each received packet. Pressing the `PA1` button will print `hello, world` over this port.
|
||||
|
||||
|
||||
## General setup notes
|
||||
|
||||
You are expected to a C compiler (for ARM) and some development tools (e.g. make and git) installed and ready to use. You can get a [toolchain from arm.com]; or use one provided by your system package manager (if you're on a normal system like some linux, bsd or mac). For the development tools, use your package manager.
|
||||
|
||||
[libopencm3] is supposed to go into the `libopencm3` directory; it's git submodule if you're going the git way; otherwise just unpack it there. You'll need to run `make` in the `libopencm3` directory once, to compile the library. Any subsequent compilation of the examples here will just use these precompiled objects. This means that if you update, or make any changes to, libopencm3 sources, you'll need to recompile it explicitly like this. In other words, running `make` in any of the examples it not going to recompile the library.
|
||||
|
||||
From time to time there are breaking changes in the library (e.g. L0 support is relatively new), so no guarantees that things compile (although they should with the commit referenced for the submodule). From time to time I pull in the new updates, but again, no guarantees. (Timestamp 2017-12-02T18:41:26).
|
||||
|
||||
To compile an example, `cd` into its directory and run `make -f Makefile.l0btld` to compile. The three versions of the `Makefile`s are for STM32F072CBT6 (f0), STM32L052C8T6 (l0), STM32L052C8T6 with DFU bootloader occupying the first 8k of the flash (more about this setup on [the bat board] page). Cleaning up (important if you're switching to a different chip!) is done with the usual `make clean`.
|
||||
|
||||
I didn't set up flashing to the board into the `Makefiles`, so flashing should be done manually. Here are the most common options:
|
||||
|
||||
### DFU bootloader
|
||||
|
||||
This requires [dfu-util] software. Put the board into DFU mode (on F072 by holding the `PA1` button during reset; on L052 by shorting `GND` and `PB3` during reset). The command is then
|
||||
```sh
|
||||
dfu-util -d 0483:df11 -a 0 -s 0x08002000 -D cdcacm.bin
|
||||
```
|
||||
where the adjustable parts are of course the name of the firmware (`cdcacm.bin` above) and importantly the address: it should be `0x08002000` for L052 with the 8k DFU bootloader, otherwise `0x08000000`).
|
||||
|
||||
### built-in USART bootloader
|
||||
|
||||
This requires a means of communicating over serial port (ideally 3.3V levels; although the required pins are 5V tolerant on L052 and F072). This usually means an external hardware, an USB-to-serial converter (there are loads on e.g. ebay; the most commonly used chips are FT231X, FT232RL, CP2102, CH340G). Although on boards like the Pi you can use the built-in UART.
|
||||
|
||||
The built-in USART bootloader talks on PA9(TX) and PA10(RX) (and some others; but these are conveniently placed on the bat board). It is entered by holding the `PA1` button during a reset.
|
||||
|
||||
On the software side, I prefer [stm32flash]. The command is then
|
||||
```sh
|
||||
stm32flash -e 255 -v -w cdcacm.bin /dev/ttyUSB0
|
||||
```
|
||||
where the adjustable parts are of course firmware filename and the serial port (`/dev/ttyUSB0` above).
|
||||
|
||||
|
||||
|
||||
|
||||
[the bat board]: https://flabbergast.github.io/bat-board
|
||||
[libopencm3]: https://github.com/libopencm3/libopencm3
|
||||
[libopencm3 examples]: https://github.com/libopencm3/libopencm3-examples
|
||||
[toolchain from arm.com]: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
|
||||
[dfu-util]: http://dfu-util.sourceforge.net/
|
||||
|
||||
|
||||
License (for the original bits): CC-by-SA 2.0
|
||||
|
43
common.f0.mk
Normal file
43
common.f0.mk
Normal file
|
@ -0,0 +1,43 @@
|
|||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
LIBNAME = opencm3_stm32f0
|
||||
DEFS += -DSTM32F0
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m0 $(FP_FLAGS)
|
||||
|
||||
################################################################################
|
||||
# OpenOCD specific variables
|
||||
|
||||
OOCD ?= openocd
|
||||
OOCD_INTERFACE ?= stlink-v2-1
|
||||
OOCD_BOARD ?= st_nucleo_f0
|
||||
|
||||
################################################################################
|
||||
# Black Magic Probe specific variables
|
||||
# Set the BMP_PORT to a serial port and then BMP is used for flashing
|
||||
BMP_PORT ?=
|
||||
|
||||
################################################################################
|
||||
# texane/stlink specific variables
|
||||
#STLINK_PORT ?= :4242
|
||||
|
||||
include ../libopencm3.rules.mk
|
44
common.l0.mk
Normal file
44
common.l0.mk
Normal file
|
@ -0,0 +1,44 @@
|
|||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
LIBNAME = opencm3_stm32l0
|
||||
DEFS += -DSTM32L0
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m0plus $(FP_FLAGS)
|
||||
|
||||
################################################################################
|
||||
# OpenOCD specific variables
|
||||
|
||||
OOCD ?= openocd
|
||||
OOCD_INTERFACE ?= stlink-v2-1
|
||||
OOCD_BOARD ?= stm32l0discovery
|
||||
|
||||
################################################################################
|
||||
# Black Magic Probe specific variables
|
||||
# Set the BMP_PORT to a serial port and then BMP is used for flashing
|
||||
BMP_PORT ?=
|
||||
|
||||
################################################################################
|
||||
# texane/stlink specific variables
|
||||
#STLINK_PORT ?= :4242
|
||||
|
||||
|
||||
include ../libopencm3.rules.mk
|
32
l052-bldr.ld
Normal file
32
l052-bldr.ld
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for stm32duino (STM32F103RBT6, 128K flash, 20K RAM,
|
||||
* minus 8k flash and 3k RAM for the DFU bootloader). */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08002000, LENGTH = 64K-0x2000
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32l0.ld
|
||||
|
1
libopencm3
Submodule
1
libopencm3
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 953bf531ea1c0b36a5b32b05ede8c6c77e480009
|
294
libopencm3.rules.mk
Normal file
294
libopencm3.rules.mk
Normal file
|
@ -0,0 +1,294 @@
|
|||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
## Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
NULL := 2>/dev/null
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Colour stuff
|
||||
NO_COLOR=\033[0m
|
||||
OK_COLOR=\033[32;01m
|
||||
ERROR_COLOR=\033[31;01m
|
||||
WARN_COLOR=\033[33;01m
|
||||
|
||||
OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR)
|
||||
ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR)
|
||||
WARN_STRING=$(WARN_COLOR)[WARNINGS]$(NO_COLOR)
|
||||
|
||||
AWK_CMD = awk '{ printf "%-30s %-10s\n",$$1, $$2; }'
|
||||
PRINT_ERROR = printf "$@ $(ERROR_STRING)\n" | $(AWK_CMD) && printf "$(CMD)\n$$LOG\n" && false
|
||||
PRINT_WARNING = printf "$@ $(WARN_STRING)\n" | $(AWK_CMD) && printf "$(CMD)\n$$LOG\n"
|
||||
PRINT_OK = printf "$@ $(OK_STRING)\n" | $(AWK_CMD)
|
||||
BUILD_CMD = LOG=$$($(CMD) 2>&1) ; if [ $$? -eq 1 ]; then $(PRINT_ERROR); elif [ "$$LOG" != "" ] ; then $(PRINT_WARNING); else $(PRINT_OK); fi;
|
||||
## can use separately with '@$(PRINT_OK)'
|
||||
|
||||
## can use with '$(call colorecho,<string>)'
|
||||
define colorecho
|
||||
@tput setaf 6
|
||||
@echo $1
|
||||
@tput sgr0
|
||||
endef
|
||||
|
||||
## can use as '$(call buildcmd,<command_to_run_as_string>)'
|
||||
define buildcmd
|
||||
LOG=$$($1 2>&1) ; if [ $$? -eq 1 ]; then $(PRINT_ERROR); elif [ "$$LOG" != "" ] ; then $(PRINT_WARNING); else $(PRINT_OK); fi;
|
||||
endef
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
|
||||
PREFIX ?= arm-none-eabi
|
||||
|
||||
CC := $(PREFIX)-gcc
|
||||
CXX := $(PREFIX)-g++
|
||||
LD := $(PREFIX)-gcc
|
||||
AR := $(PREFIX)-ar
|
||||
AS := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
STFLASH = $(shell which st-flash)
|
||||
STYLECHECK := /checkpatch.pl
|
||||
STYLECHECKFLAGS := --no-tree -f --terse --mailback
|
||||
STYLECHECKFILES := $(shell find . -name '*.[ch]')
|
||||
OPT := -Os
|
||||
CSTD ?= -std=c99
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Source files
|
||||
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
|
||||
OBJS += $(BINARY).o
|
||||
|
||||
|
||||
ifeq ($(strip $(OPENCM3_DIR)),)
|
||||
# user has not specified the library path, so we try to detect it
|
||||
|
||||
# where we search for the library
|
||||
LIBPATHS := ./libopencm3 ../../../../libopencm3 ../../../../../libopencm3
|
||||
|
||||
OPENCM3_DIR := $(wildcard $(LIBPATHS:=/locm3.sublime-project))
|
||||
OPENCM3_DIR := $(firstword $(dir $(OPENCM3_DIR)))
|
||||
|
||||
ifeq ($(strip $(OPENCM3_DIR)),)
|
||||
$(warning Cannot find libopencm3 library in the standard search paths.)
|
||||
$(error Please specify it through OPENCM3_DIR variable!)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(V),1)
|
||||
$(info Using $(OPENCM3_DIR) path to library)
|
||||
endif
|
||||
|
||||
define ERR_DEVICE_LDSCRIPT_CONFLICT
|
||||
You can either specify DEVICE=blah, and have the LDSCRIPT generated,
|
||||
or you can provide LDSCRIPT, and ensure CPPFLAGS, LDFLAGS and LDLIBS
|
||||
all contain the correct values for the target you wish to use.
|
||||
You cannot provide both!
|
||||
endef
|
||||
|
||||
ifeq ($(strip $(DEVICE)),)
|
||||
# Old style, assume LDSCRIPT exists
|
||||
DEFS += -I$(OPENCM3_DIR)/include
|
||||
LDFLAGS += -L$(OPENCM3_DIR)/lib
|
||||
LDLIBS += -l$(LIBNAME)
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
else
|
||||
# New style, assume device is provided, and we're generating the rest.
|
||||
ifneq ($(strip $(LDSCRIPT)),)
|
||||
$(error $(ERR_DEVICE_LDSCRIPT_CONFLICT))
|
||||
endif
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
endif
|
||||
|
||||
OPENCM3_SCRIPT_DIR = $(OPENCM3_DIR)/scripts
|
||||
LOCAL_SCRIPT_DIR ?= ./scripts
|
||||
|
||||
###############################################################################
|
||||
# C flags
|
||||
|
||||
TGT_CFLAGS += $(OPT) $(CSTD) -g
|
||||
TGT_CFLAGS += $(ARCH_FLAGS)
|
||||
TGT_CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration
|
||||
TGT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
|
||||
TGT_CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
###############################################################################
|
||||
# C++ flags
|
||||
|
||||
TGT_CXXFLAGS += $(OPT) $(CXXSTD) -g
|
||||
TGT_CXXFLAGS += $(ARCH_FLAGS)
|
||||
TGT_CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++
|
||||
TGT_CXXFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
###############################################################################
|
||||
# C & C++ preprocessor common flags
|
||||
|
||||
TGT_CPPFLAGS += -MD
|
||||
TGT_CPPFLAGS += -Wall -Wundef
|
||||
TGT_CPPFLAGS += $(DEFS)
|
||||
|
||||
###############################################################################
|
||||
# Linker flags
|
||||
|
||||
TGT_LDFLAGS += --static -nostartfiles
|
||||
TGT_LDFLAGS += -T$(LDSCRIPT)
|
||||
TGT_LDFLAGS += $(ARCH_FLAGS)
|
||||
TGT_LDFLAGS += -Wl,-Map=$(*).map
|
||||
TGT_LDFLAGS += -Wl,--gc-sections
|
||||
ifeq ($(V),99)
|
||||
TGT_LDFLAGS += -Wl,--print-gc-sections
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Used libraries
|
||||
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
|
||||
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
||||
.SUFFIXES: .elf .bin .hex .srec .list .map .images
|
||||
.SECONDEXPANSION:
|
||||
.SECONDARY:
|
||||
|
||||
all: elf hex bin
|
||||
|
||||
elf: $(BINARY).elf
|
||||
bin: $(BINARY).bin
|
||||
hex: $(BINARY).hex
|
||||
srec: $(BINARY).srec
|
||||
list: $(BINARY).list
|
||||
|
||||
images: $(BINARY).images
|
||||
flash: $(BINARY).flash
|
||||
|
||||
# Either verify the user provided LDSCRIPT exists, or generate it.
|
||||
ifeq ($(strip $(DEVICE)),)
|
||||
$(LDSCRIPT):
|
||||
ifeq (,$(wildcard $(LDSCRIPT)))
|
||||
$(error Unable to find specified linker script: $(LDSCRIPT))
|
||||
endif
|
||||
else
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
endif
|
||||
|
||||
# Define a helper macro for debugging make errors online
|
||||
# you can type "make print-OPENCM3_DIR" and it will show you
|
||||
# how that ended up being resolved by all of the included
|
||||
# makefiles.
|
||||
print-%:
|
||||
@echo $*=$($*)
|
||||
|
||||
%.images: %.bin %.hex %.srec %.list %.map
|
||||
@#printf "*** $* images generated ***\n"
|
||||
|
||||
%.bin: %.elf
|
||||
@#printf " OBJCOPY $(*).bin\n"
|
||||
$(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
|
||||
|
||||
%.hex: %.elf
|
||||
@#printf " OBJCOPY $(*).hex\n"
|
||||
$(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex
|
||||
|
||||
%.srec: %.elf
|
||||
@#printf " OBJCOPY $(*).srec\n"
|
||||
$(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec
|
||||
|
||||
%.list: %.elf
|
||||
@#printf " OBJDUMP $(*).list\n"
|
||||
$(Q)$(OBJDUMP) -S $(*).elf > $(*).list
|
||||
|
||||
%.elf %.map: $(OBJS) $(LDSCRIPT)
|
||||
@#printf " LD $(*).elf\n"
|
||||
$(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(*).elf
|
||||
|
||||
%.o: %.c
|
||||
@#printf " CC $(*).c\n"
|
||||
$(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).c
|
||||
|
||||
%.o: %.cxx
|
||||
@#printf " CXX $(*).cxx\n"
|
||||
$(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).cxx
|
||||
|
||||
%.o: %.cpp
|
||||
@#printf " CXX $(*).cpp\n"
|
||||
$(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).cpp
|
||||
|
||||
clean:
|
||||
@#printf " CLEAN\n"
|
||||
$(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map generated.* ${OBJS} ${OBJS:%.o:%.d}
|
||||
|
||||
stylecheck: $(STYLECHECKFILES:=.stylecheck)
|
||||
styleclean: $(STYLECHECKFILES:=.styleclean)
|
||||
|
||||
# the cat is due to multithreaded nature - we like to have consistent chunks of text on the output
|
||||
%.stylecheck: %
|
||||
$(Q)$(OPENCM3_SCRIPT_DIR)$(STYLECHECK) $(STYLECHECKFLAGS) $* > $*.stylecheck; \
|
||||
if [ -s $*.stylecheck ]; then \
|
||||
cat $*.stylecheck; \
|
||||
else \
|
||||
rm -f $*.stylecheck; \
|
||||
fi;
|
||||
|
||||
%.styleclean:
|
||||
$(Q)rm -f $*.stylecheck;
|
||||
|
||||
|
||||
%.stlink-flash: %.bin
|
||||
@printf " FLASH $<\n"
|
||||
$(Q)$(STFLASH) write $(*).bin 0x8000000
|
||||
|
||||
ifeq ($(BMP_PORT),)
|
||||
ifeq ($(OOCD_FILE),)
|
||||
%.flash: %.elf
|
||||
@printf " FLASH $<\n"
|
||||
$(Q)(echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \
|
||||
$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
|
||||
-f target/$(OOCD_TARGET).cfg \
|
||||
-c "program $(*).elf verify reset exit" \
|
||||
$(NULL)
|
||||
else
|
||||
%.flash: %.elf
|
||||
@printf " FLASH $<\n"
|
||||
$(Q)(echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \
|
||||
$(OOCD) -f $(OOCD_FILE) \
|
||||
-c "program $(*).elf verify reset exit" \
|
||||
$(NULL)
|
||||
endif
|
||||
else
|
||||
%.flash: %.elf
|
||||
@printf " GDB $(*).elf (flash)\n"
|
||||
$(GDB) --batch \
|
||||
-ex 'target extended-remote $(BMP_PORT)' \
|
||||
-x $(LOCAL_SCRIPT_DIR)/black_magic_probe_flash.scr \
|
||||
$(*).elf
|
||||
endif
|
||||
|
||||
.PHONY: images clean stylecheck styleclean elf bin hex srec list
|
||||
|
||||
-include $(OBJS:.o=.d)
|
26
usb_cdcacm/Makefile.f0
Normal file
26
usb_cdcacm/Makefile.f0
Normal file
|
@ -0,0 +1,26 @@
|
|||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
BINARY = cdcacm
|
||||
|
||||
OPENCM3_DIR=../libopencm3
|
||||
LDSCRIPT = $(OPENCM3_DIR)/lib/stm32/f0/stm32f07xzb.ld
|
||||
|
||||
include ../common.f0.mk
|
||||
|
26
usb_cdcacm/Makefile.l0
Normal file
26
usb_cdcacm/Makefile.l0
Normal file
|
@ -0,0 +1,26 @@
|
|||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
BINARY = cdcacm
|
||||
|
||||
OPENCM3_DIR=../libopencm3
|
||||
LDSCRIPT = $(OPENCM3_DIR)/lib/stm32/l0/stm32l0xx8.ld
|
||||
|
||||
include ../common.l0.mk
|
||||
|
27
usb_cdcacm/Makefile.l0btld
Normal file
27
usb_cdcacm/Makefile.l0btld
Normal file
|
@ -0,0 +1,27 @@
|
|||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## This library is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU Lesser General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public License
|
||||
## along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
BINARY = cdcacm
|
||||
|
||||
OPENCM3_DIR=../libopencm3
|
||||
LDSCRIPT = ../l052-bldr.ld
|
||||
DEFS += -DBOOTLOADER8K
|
||||
|
||||
include ../common.l0.mk
|
||||
|
334
usb_cdcacm/cdcacm.c
Normal file
334
usb_cdcacm/cdcacm.c
Normal file
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/flash.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/syscfg.h>
|
||||
#include <libopencm3/stm32/crs.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
#include <libopencm3/usb/cdc.h>
|
||||
|
||||
static const struct usb_device_descriptor dev = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = USB_CLASS_CDC,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = 64,
|
||||
.idVendor = 0x0483,
|
||||
.idProduct = 0x5740,
|
||||
.bcdDevice = 0x0200,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* This notification endpoint isn't implemented. According to CDC spec its
|
||||
* optional, but its absence causes a NULL pointer dereference in Linux
|
||||
* cdc_acm driver.
|
||||
*/
|
||||
static const struct usb_endpoint_descriptor comm_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x83,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||
.wMaxPacketSize = 16,
|
||||
.bInterval = 255,
|
||||
}};
|
||||
|
||||
static const struct usb_endpoint_descriptor data_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x01,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}, {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}};
|
||||
|
||||
static const struct {
|
||||
struct usb_cdc_header_descriptor header;
|
||||
struct usb_cdc_call_management_descriptor call_mgmt;
|
||||
struct usb_cdc_acm_descriptor acm;
|
||||
struct usb_cdc_union_descriptor cdc_union;
|
||||
} __attribute__((packed)) cdcacm_functional_descriptors = {
|
||||
.header = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_HEADER,
|
||||
.bcdCDC = 0x0110,
|
||||
},
|
||||
.call_mgmt = {
|
||||
.bFunctionLength =
|
||||
sizeof(struct usb_cdc_call_management_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
|
||||
.bmCapabilities = 0,
|
||||
.bDataInterface = 1,
|
||||
},
|
||||
.acm = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_ACM,
|
||||
.bmCapabilities = 0,
|
||||
},
|
||||
.cdc_union = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
|
||||
.bControlInterface = 0,
|
||||
.bSubordinateInterface0 = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_interface_descriptor comm_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_CDC,
|
||||
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
|
||||
.bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = comm_endp,
|
||||
|
||||
.extra = &cdcacm_functional_descriptors,
|
||||
.extralen = sizeof(cdcacm_functional_descriptors)
|
||||
}};
|
||||
|
||||
static const struct usb_interface_descriptor data_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_DATA,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = data_endp,
|
||||
}};
|
||||
|
||||
static const struct usb_interface ifaces[] = {{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = comm_iface,
|
||||
}, {
|
||||
.num_altsetting = 1,
|
||||
.altsetting = data_iface,
|
||||
}};
|
||||
|
||||
static const struct usb_config_descriptor config = {
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = 0,
|
||||
.bNumInterfaces = 2,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32,
|
||||
|
||||
.interface = ifaces,
|
||||
};
|
||||
|
||||
static const char *usb_strings[] = {
|
||||
"flabbergast",
|
||||
"CDC-ACM Test",
|
||||
"DeMo",
|
||||
};
|
||||
|
||||
/* Buffer to be used for control requests. */
|
||||
uint8_t usbd_control_buffer[128];
|
||||
|
||||
/* Aux functions */
|
||||
static void led_flip(void) {
|
||||
if(GPIOA_IDR & (1<<15)) {
|
||||
GPIOA_BRR = GPIO15;
|
||||
} else {
|
||||
GPIOA_BSRR = GPIO15;
|
||||
}
|
||||
}
|
||||
|
||||
static int cdcacm_control_request(usbd_device *usbd_dev,
|
||||
struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
|
||||
void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
|
||||
{
|
||||
(void)complete;
|
||||
(void)buf;
|
||||
(void)usbd_dev;
|
||||
|
||||
switch(req->bRequest) {
|
||||
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
|
||||
/*
|
||||
* This Linux cdc_acm driver requires this to be implemented
|
||||
* even though it's optional in the CDC spec, and we don't
|
||||
* advertise it in the ACM functional descriptor.
|
||||
*/
|
||||
char local_buf[10];
|
||||
struct usb_cdc_notification *notif = (void *)local_buf;
|
||||
|
||||
/* We echo signals back to host as notification. */
|
||||
notif->bmRequestType = 0xA1;
|
||||
notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
|
||||
notif->wValue = 0;
|
||||
notif->wIndex = 0;
|
||||
notif->wLength = 2;
|
||||
local_buf[8] = req->wValue & 3;
|
||||
local_buf[9] = 0;
|
||||
// usbd_ep_write_packet(0x83, buf, 10);
|
||||
return 1;
|
||||
}
|
||||
case USB_CDC_REQ_SET_LINE_CODING:
|
||||
if(*len < sizeof(struct usb_cdc_line_coding))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
(void)ep;
|
||||
|
||||
char buf[64];
|
||||
int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
|
||||
|
||||
if (len) {
|
||||
usbd_ep_write_packet(usbd_dev, 0x82, buf, len);
|
||||
buf[len] = 0;
|
||||
led_flip();
|
||||
}
|
||||
}
|
||||
|
||||
static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
|
||||
{
|
||||
(void)wValue;
|
||||
|
||||
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
|
||||
usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
|
||||
|
||||
usbd_register_control_callback(
|
||||
usbd_dev,
|
||||
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
||||
cdcacm_control_request);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
usbd_device *usbd_dev;
|
||||
|
||||
#if defined(BOOTLOADER8K)
|
||||
# define SCB_VTOR MMIO32(0xE000ED08)
|
||||
SCB_VTOR = (uint32_t) 0x08002000;
|
||||
#endif
|
||||
|
||||
#if defined(STM32F0)
|
||||
rcc_clock_setup_in_hsi_out_48mhz();
|
||||
crs_autotrim_usb_enable();
|
||||
rcc_set_usbclk_source(RCC_HSI48);
|
||||
|
||||
// this is needed for F042 in TSSOP-20 package; USB is on shared pins
|
||||
//rcc_periph_clock_enable(RCC_SYSCFG_COMP);
|
||||
//SYSCFG_CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
|
||||
|
||||
#elif defined(STM32L0)
|
||||
|
||||
// libopencm3 clock setup can be a bit ad-hoc, so let's configure manually
|
||||
// 32MHz, PLL supplied by the internal HSI16 oscillator
|
||||
/* Set the flash latency */
|
||||
FLASH_ACR |= FLASH_ACR_LATENCY_1WS;
|
||||
/* Turn on HSI16 */
|
||||
RCC_CR |= RCC_CR_HSI16ON;
|
||||
while ((RCC_CR & RCC_CR_HSI16RDY) == 0);
|
||||
/* Make sure PLL is off (it should be after reset, but ...) */
|
||||
RCC_CR &= ~RCC_CR_PLLON;
|
||||
while (RCC_CR & RCC_CR_PLLRDY);
|
||||
/* Set the PLL source to HSI16 */
|
||||
RCC_CFGR &= ~(1<<16); // RCC_CFGR_PLLSRC
|
||||
/* Set up the PLL */
|
||||
uint32_t reg = RCC_CFGR
|
||||
& ~( (RCC_CFGR_PLLMUL_MASK << RCC_CFGR_PLLMUL_SHIFT)
|
||||
| (RCC_CFGR_PLLDIV_MASK << RCC_CFGR_PLLDIV_SHIFT));
|
||||
RCC_CFGR = reg | (RCC_CFGR_PLLMUL_MUL4 << RCC_CFGR_PLLMUL_SHIFT)
|
||||
| (RCC_CFGR_PLLDIV_DIV2 << RCC_CFGR_PLLDIV_SHIFT);
|
||||
/* Turn on PLL and switch to it */
|
||||
RCC_CR |= RCC_CR_PLLON;
|
||||
while ((RCC_CR & RCC_CR_PLLRDY) == 0);
|
||||
RCC_CFGR |= RCC_CFGR_SW_PLL;
|
||||
/* Set the peripheral clock frequencies used. */
|
||||
rcc_ahb_frequency = 32000000;
|
||||
rcc_apb1_frequency = 32000000;
|
||||
rcc_apb2_frequency = 32000000;
|
||||
// end of manual clock configuration
|
||||
|
||||
// Enable VREFINT reference for HSI48
|
||||
rcc_periph_clock_enable(RCC_SYSCFG);
|
||||
SYSCFG_CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48;
|
||||
|
||||
rcc_set_hsi48_source_rc48();
|
||||
crs_autotrim_usb_enable();
|
||||
|
||||
rcc_osc_on(RCC_HSI48);
|
||||
rcc_wait_for_osc_ready(RCC_HSI48);
|
||||
|
||||
/* MCO on PA9, to verify MCU speed with a scope */
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9);
|
||||
gpio_set_af(GPIOA, GPIO_AF0, GPIO9);
|
||||
RCC_CFGR |= (RCC_CFGR_MCO_SYSCLK << RCC_CFGR_MCO_SHIFT) | (RCC_CFGR_MCOPRE_DIV16 << 28);
|
||||
|
||||
#else
|
||||
#error "Edit the sources and do the clock setup!"
|
||||
#endif
|
||||
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO15); // LED
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO1); // button, has external pull-down
|
||||
|
||||
usbd_dev = usbd_init(&st_usbfs_v2_usb_driver, &dev, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||
|
||||
usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
|
||||
|
||||
char greeting[16] = "hello, world\r\n";
|
||||
|
||||
while (1) {
|
||||
usbd_poll(usbd_dev);
|
||||
if (gpio_get(GPIOA, GPIO1)) {
|
||||
usbd_ep_write_packet(usbd_dev, 0x82, greeting, 15);
|
||||
for (uint32_t i = 0; i < 2000000; i++) { /* Wait a bit, cheap "debounce" */
|
||||
__asm__("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue