git subrepo clone https://github.com/libopencm3/libopencm3
subrepo: subdir: "libopencm3" merged: "f5813a54" upstream: origin: "https://github.com/libopencm3/libopencm3" branch: "master" commit: "f5813a54" git-subrepo: version: "0.4.3" origin: "???" commit: "???"
This commit is contained in:
2
libopencm3/tests/gadget-zero/.gitignore
vendored
Normal file
2
libopencm3/tests/gadget-zero/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
openocd.*.local.cfg
|
||||
generated.*
|
||||
6
libopencm3/tests/gadget-zero/70-libopencm3.rules
Normal file
6
libopencm3/tests/gadget-zero/70-libopencm3.rules
Normal file
@@ -0,0 +1,6 @@
|
||||
# Put this in /etc/udev/rules.d/70-libopencm3.rules
|
||||
# then do "sudo udevadm control --reload" and unplug/replug the usb device.
|
||||
# This grants user accesss to the "cafe" USB Vendor ID used/hijacked/squatted by the test gadget
|
||||
|
||||
# libopencm hacking
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="cafe", TAG+="uaccess"
|
||||
84
libopencm3/tests/gadget-zero/Jenkinsfile
vendored
Normal file
84
libopencm3/tests/gadget-zero/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
pipeline {
|
||||
agent {label 'locm3-usb'}
|
||||
parameters {
|
||||
string(name:'pr_from_git_url', description:'the git url we are going to clone the pr from')
|
||||
string(name:'pr_from_sha', description:'what we are going to build')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('checkout') {
|
||||
steps {
|
||||
sh "echo karl we are building $pr_from_sha"
|
||||
checkout([$class: 'GitSCM', branches: [[name: "$pr_from_sha"]], userRemoteConfigs: [[url: "$pr_from_git_url"]]])
|
||||
step([
|
||||
$class: "GitHubCommitStatusSetter",
|
||||
commitShaSource: [$class: "ManuallyEnteredShaSource", sha: "$pr_from_sha"],
|
||||
reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/libopencm3/libopencm3"],
|
||||
contextSource: [$class: "DefaultCommitContextSource"],
|
||||
statusResultSource: [ $class: "DefaultStatusResultSource"]
|
||||
]);
|
||||
}
|
||||
}
|
||||
stage('prepare') {
|
||||
steps {
|
||||
sh label: 'preparing python', script: '''
|
||||
[ -f .env3 ] || python3 -m venv .env3
|
||||
. .env3/bin/activate
|
||||
pip install pyusb
|
||||
pip install unittest-xml-reporting
|
||||
'''
|
||||
}
|
||||
}
|
||||
stage('build') {
|
||||
steps {
|
||||
sh '''
|
||||
. .env3/bin/activate
|
||||
make V=1
|
||||
make -C tests/gadget-zero all V=s
|
||||
'''
|
||||
}
|
||||
}
|
||||
stage('Testprepare') {
|
||||
steps {
|
||||
sh label: 'gadget0', script: '''
|
||||
cd tests/gadget-zero
|
||||
echo "hla_serial 53FF6E066765505136472567" > openocd.stm32f3-disco.local.cfg
|
||||
echo "hla_serial 57FF6B064967485630481087" > openocd.stm32f4disco.local.cfg
|
||||
'''
|
||||
}
|
||||
}
|
||||
stage('flashin') {
|
||||
steps {
|
||||
dir('tests/gadget-zero') {
|
||||
sh '''
|
||||
make -f Makefile.stm32f3-disco flash V=1
|
||||
make -f Makefile.stm32f4disco flash V=1
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('run-test') {
|
||||
steps {
|
||||
sh '''
|
||||
. .env3/bin/activate
|
||||
cd tests/gadget-zero
|
||||
rm -rf tests
|
||||
python test_gadget0.py -X
|
||||
for x in tests/*; do TT=$(basename \$x); sed -i "s/testcase\\ classname=\\"/testcase\\ classname=\\"\${TT}./g" \$x/TEST-*; done
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
step([$class: "GitHubCommitStatusSetter",
|
||||
commitShaSource: [$class: "ManuallyEnteredShaSource", sha: "$pr_from_sha"],
|
||||
reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/libopencm3/libopencm3"],
|
||||
contextSource: [$class: "DefaultCommitContextSource"],
|
||||
statusResultSource: [ $class: "DefaultStatusResultSource"]
|
||||
]);
|
||||
junit 'tests/gadget-zero/tests/*/TEST-*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
15
libopencm3/tests/gadget-zero/Makefile
Normal file
15
libopencm3/tests/gadget-zero/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
# This is just a stub makefile used for travis builds
|
||||
# to keep things all compiling. Normally you'd use
|
||||
# one of the makefiles directly.
|
||||
|
||||
# These hoops are to enable parallel make correctly.
|
||||
GZ_ALL := $(wildcard Makefile.*)
|
||||
|
||||
all: $(GZ_ALL:=.all)
|
||||
clean: $(GZ_ALL:=.clean)
|
||||
|
||||
%.all:
|
||||
$(MAKE) -f $* all
|
||||
%.clean:
|
||||
$(MAKE) -f $* clean
|
||||
|
||||
40
libopencm3/tests/gadget-zero/Makefile.efm32hg309-generic
Normal file
40
libopencm3/tests/gadget-zero/Makefile.efm32hg309-generic
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = efm32hg309-generic
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c
|
||||
CFILES += delay_efm32.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=efm32hg309f64
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.stm32f072disco
Normal file
40
libopencm3/tests/gadget-zero/Makefile.stm32f072disco
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32f072disco
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c
|
||||
CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32f072rb
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.stm32f103-generic
Normal file
40
libopencm3/tests/gadget-zero/Makefile.stm32f103-generic
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32f103-generic
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c trace.c trace_stdio.c
|
||||
CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../../
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32f103x8
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.stm32f3-disco
Normal file
40
libopencm3/tests/gadget-zero/Makefile.stm32f3-disco
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32f3-disco
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c trace.c trace_stdio.c
|
||||
CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32f303xc
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.stm32f429i-disco
Normal file
40
libopencm3/tests/gadget-zero/Makefile.stm32f429i-disco
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32f429i-disco
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c trace.c trace_stdio.c
|
||||
CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32f405re
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.stm32f4disco
Normal file
40
libopencm3/tests/gadget-zero/Makefile.stm32f4disco
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32f4disco
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c trace.c trace_stdio.c
|
||||
CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32f405re
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.stm32l053disco
Normal file
40
libopencm3/tests/gadget-zero/Makefile.stm32l053disco
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32l053disco
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c
|
||||
CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32l053x8
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.stm32l1-generic
Normal file
40
libopencm3/tests/gadget-zero/Makefile.stm32l1-generic
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = stm32l1-generic
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c trace.c trace_stdio.c
|
||||
CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=stm32l151c8
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
40
libopencm3/tests/gadget-zero/Makefile.tilm4f120xl
Normal file
40
libopencm3/tests/gadget-zero/Makefile.tilm4f120xl
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
BOARD = tilm4f120xl
|
||||
PROJECT = usb-gadget0-$(BOARD)
|
||||
BUILD_DIR = bin-$(BOARD)
|
||||
|
||||
SHARED_DIR = ../shared
|
||||
|
||||
CFILES = main-$(BOARD).c
|
||||
CFILES += usb-gadget0.c trace.c trace_stdio.c
|
||||
#CFILES += delay.c
|
||||
|
||||
VPATH += $(SHARED_DIR)
|
||||
|
||||
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
|
||||
|
||||
OPENCM3_DIR=../..
|
||||
|
||||
### This section can go to an arch shared rules eventually...
|
||||
DEVICE=lm4f120xl
|
||||
OOCD_FILE = openocd.$(BOARD).cfg
|
||||
|
||||
include $(OPENCM3_DIR)/mk/genlink-config.mk
|
||||
include $(OPENCM3_DIR)/mk/genlink-rules.mk
|
||||
include ../rules.mk
|
||||
71
libopencm3/tests/gadget-zero/README.md
Normal file
71
libopencm3/tests/gadget-zero/README.md
Normal file
@@ -0,0 +1,71 @@
|
||||
This project, inspired by [usbtest](http://www.linux-usb.org/usbtest/) and
|
||||
the linux usb gadget zero driver is used for regression testing changes to the
|
||||
libopencm3 usb stack.
|
||||
|
||||
The firmware itself is meant to be portable to any supported hardware, and then
|
||||
identical unit test code is run against all platforms. This project can and
|
||||
should be built for multiple devices.
|
||||
|
||||
## Requirements:
|
||||
* [pyusb](https://walac.github.io/pyusb/) for running the tests.
|
||||
* [OpenOCD](http://openocd.org/) >= 0.9 for automated flashing of specific boards
|
||||
* python3 for running the tests at the command line.
|
||||
* unittest-xml-reporting, only if running in CI mode. XX
|
||||
|
||||
### Building the device firmware
|
||||
There are Makefile.xxxxx files for all the currently tested targets.
|
||||
```
|
||||
make -f Makefile.stm32f4disco clean all V=1
|
||||
```
|
||||
The ```V=1``` is optional, and turns on verbose mode, which can be useful if
|
||||
things don't work. This will give you a .elf file you can program using your
|
||||
own toolchain, but if you have a functional OpenOCD installed, then...
|
||||
```
|
||||
make -f Makefile.stm32f4disco clean all flash
|
||||
```
|
||||
Will handle flashing as well.
|
||||
|
||||
### Setting up the test runner (using python virtual environments)
|
||||
```
|
||||
pyvenv .env # ensures a python3 virtual env
|
||||
. .env/bin/activate
|
||||
pip install pyusb
|
||||
```
|
||||
|
||||
If you have multiple test boards connected, have a look at opencd.common.cfg
|
||||
for some tips on selectively matching the right board. For people with just
|
||||
a single matching board, you don't need to do anything.
|
||||
|
||||
Tests marked as @unittest.skip are either for functionality that is known to be
|
||||
broken, and are awaiting code fixes, or are long running performance tests
|
||||
|
||||
### Access rights
|
||||
On some systems (most linux systems) you probably won't have access to the
|
||||
usb vendor id being used/hijacked by the test cases. See 70-libopencm3.rules
|
||||
for installation instructions, or, if you have your own system, grant yourself
|
||||
access to the usb vid: 0xcafe
|
||||
|
||||
## Running the tests
|
||||
Below is an example of running the full suite of tests from the command line.
|
||||
The argument specifies the serial number to look for in the usb gadget, if
|
||||
you have more than one. No argument will the tests against all
|
||||
gadget-zero's found.
|
||||
```
|
||||
$ python test_gadget0.py
|
||||
Running tests for DUT: stm32f072disco
|
||||
.........ss................
|
||||
----------------------------------------------------------------------
|
||||
Ran 27 tests in 0.388s
|
||||
|
||||
OK (skipped=2)
|
||||
```
|
||||
|
||||
To be even more brutal, run this in a shell loop.
|
||||
```
|
||||
$ while true; do python test_gadget0.py -d stm32f072disco; done
|
||||
```
|
||||
|
||||
You can also run individual tests, or individual sets of tests, see the [unittest documentation](https://docs.python.org/3/library/unittest.html) for more information.
|
||||
|
||||
Many development environments, such as [PyCharm](https://www.jetbrains.com/pycharm/) can
|
||||
also be used to edit and run the tests, in whole or individually, with a nice visual test runner.
|
||||
50
libopencm3/tests/gadget-zero/delay.c
Normal file
50
libopencm3/tests/gadget-zero/delay.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements some simple busy timers. They are designed to be
|
||||
* portable, not performant.
|
||||
* TIM6 is appropriated for usage.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
|
||||
#include "delay.h"
|
||||
|
||||
void delay_setup(void)
|
||||
{
|
||||
/* set up a microsecond free running timer for ... things... */
|
||||
rcc_periph_clock_enable(RCC_TIM6);
|
||||
/* microsecond counter */
|
||||
timer_set_prescaler(TIM6, rcc_apb1_frequency / 1000000 - 1);
|
||||
timer_set_period(TIM6, 0xffff);
|
||||
timer_one_shot_mode(TIM6);
|
||||
}
|
||||
|
||||
void delay_us(uint16_t us)
|
||||
{
|
||||
TIM_ARR(TIM6) = us;
|
||||
TIM_EGR(TIM6) = TIM_EGR_UG;
|
||||
TIM_CR1(TIM6) |= TIM_CR1_CEN;
|
||||
//timer_enable_counter(TIM6);
|
||||
while (TIM_CR1(TIM6) & TIM_CR1_CEN);
|
||||
}
|
||||
|
||||
|
||||
39
libopencm3/tests/gadget-zero/delay.h
Normal file
39
libopencm3/tests/gadget-zero/delay.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize the timers used for delays.
|
||||
*/
|
||||
void delay_setup(void);
|
||||
|
||||
/**
|
||||
* busy wait for a number of usecs.
|
||||
* @param us number of usecs to delay.
|
||||
*/
|
||||
void delay_us(uint16_t us);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
45
libopencm3/tests/gadget-zero/delay_efm32.c
Normal file
45
libopencm3/tests/gadget-zero/delay_efm32.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2018 Seb Holzapfel <schnommus@gmail.com>
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <libopencm3/efm32/cmu.h>
|
||||
#include <libopencm3/efm32/timer.h>
|
||||
|
||||
#include "delay.h"
|
||||
|
||||
extern const uint32_t ahb_frequency;
|
||||
|
||||
void delay_setup(void)
|
||||
{
|
||||
cmu_periph_clock_enable(CMU_TIMER2);
|
||||
/* efm32hg doesn't support a nice 1us prescaler */
|
||||
timer_start(TIMER2);
|
||||
}
|
||||
|
||||
void delay_us(uint16_t us)
|
||||
{
|
||||
volatile uint16_t time_now = 0;
|
||||
/* Convert microseconds into timer ticks */
|
||||
uint16_t delay_ahb_cycles = us * (ahb_frequency / 1000000);
|
||||
|
||||
TIMER2_CNT = 0;
|
||||
while (time_now < delay_ahb_cycles) {
|
||||
time_now = TIMER2_CNT;
|
||||
}
|
||||
}
|
||||
57
libopencm3/tests/gadget-zero/main-efm32hg309-generic.c
Normal file
57
libopencm3/tests/gadget-zero/main-efm32hg309-generic.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
* Copyright (C) 2018 Seb Holzapfel <schnommus@gmail.com>
|
||||
*
|
||||
* 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 <libopencm3/cm3/common.h>
|
||||
#include <libopencm3/cm3/vector.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
/* no trace on cm0 #define ER_DEBUG */
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
const uint32_t ahb_frequency = 14000000;
|
||||
|
||||
#include "trace.h"
|
||||
void trace_send_blocking8(int stimulus_port, char c)
|
||||
{
|
||||
(void)stimulus_port;
|
||||
(void)c;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
usbd_device *usbd_dev = gadget0_init(&efm32hg_usb_driver,
|
||||
"efm32hg309-generic");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
|
||||
while (1) {
|
||||
gadget0_run(usbd_dev);
|
||||
}
|
||||
}
|
||||
66
libopencm3/tests/gadget-zero/main-stm32f072disco.c
Normal file
66
libopencm3/tests/gadget-zero/main-stm32f072disco.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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 <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/crs.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
/* no trace on cm0 #define ER_DEBUG */
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
#include "trace.h"
|
||||
void trace_send_blocking8(int stimulus_port, char c)
|
||||
{
|
||||
(void)stimulus_port;
|
||||
(void)c;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rcc_clock_setup_in_hsi48_out_48mhz();
|
||||
crs_autotrim_usb_enable();
|
||||
rcc_set_usbclk_source(RCC_HSI48);
|
||||
|
||||
/* LED on for boot progress */
|
||||
rcc_periph_clock_enable(RCC_GPIOC);
|
||||
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7);
|
||||
gpio_set(GPIOC, GPIO7);
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&st_usbfs_v2_usb_driver,
|
||||
"stm32f072disco");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
gpio_clear(GPIOC, GPIO7);
|
||||
while (1) {
|
||||
gadget0_run(usbd_dev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
71
libopencm3/tests/gadget-zero/main-stm32f103-generic.c
Normal file
71
libopencm3/tests/gadget-zero/main-stm32f103-generic.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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 <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
#define ER_DEBUG
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rcc_clock_setup_pll(&rcc_hsi_configs[RCC_CLOCK_HSI_48MHZ]);
|
||||
/* LED to indicate boot process */
|
||||
rcc_periph_clock_enable(RCC_GPIOC);
|
||||
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
|
||||
gpio_set(GPIOC, GPIO13);
|
||||
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
/*
|
||||
* Vile hack to reenumerate, physically _drag_ d+ low.
|
||||
* do NOT do this if you're board has proper usb pull up control!
|
||||
* (need at least 2.5us to trigger usb disconnect)
|
||||
*/
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
|
||||
gpio_clear(GPIOA, GPIO12);
|
||||
for (unsigned int i = 0; i < 800000; i++) {
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
rcc_periph_clock_enable(RCC_OTGFS);
|
||||
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&st_usbfs_v1_usb_driver,
|
||||
"stm32f103-generic");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
gpio_clear(GPIOC, GPIO13);
|
||||
while (1) {
|
||||
gadget0_run(usbd_dev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
75
libopencm3/tests/gadget-zero/main-stm32f3-disco.c
Normal file
75
libopencm3/tests/gadget-zero/main-stm32f3-disco.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* "generic" could be any L1 board, but this file is pre-configured for the
|
||||
* libopencm3-tests "hw1" board, with an stm32l151c8-A part.
|
||||
*/
|
||||
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/flash.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/syscfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
#define ER_DEBUG
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_GPIOE);
|
||||
gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO11|GPIO12);
|
||||
gpio_set(GPIOE, GPIO12);
|
||||
rcc_clock_setup_pll(&rcc_hse8mhz_configs[RCC_CLOCK_HSE8_72MHZ]);
|
||||
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
/*
|
||||
* Vile hack to reenumerate, physically _drag_ d+ low.
|
||||
* do NOT do this if you're board has proper usb pull up control!
|
||||
* (need at least 2.5us to trigger usb disconnect)
|
||||
*/
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12);
|
||||
gpio_clear(GPIOA, GPIO12);
|
||||
for (unsigned int i = 0; i < 800000; i++) {
|
||||
__asm__("nop");
|
||||
}
|
||||
/* now return PA11/PA12 to usb AF */
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11|GPIO12);
|
||||
gpio_set_af(GPIOA, GPIO_AF14, GPIO11|GPIO12);
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&st_usbfs_v1_usb_driver,
|
||||
"stm32f3-disco");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
gpio_clear(GPIOE, GPIO12);
|
||||
static int i = 0;
|
||||
while (1) {
|
||||
gadget0_run(usbd_dev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
59
libopencm3/tests/gadget-zero/main-stm32f429i-disco.c
Normal file
59
libopencm3/tests/gadget-zero/main-stm32f429i-disco.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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 <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
#define ER_DEBUG
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
|
||||
rcc_periph_clock_enable(RCC_GPIOB);
|
||||
rcc_periph_clock_enable(RCC_OTGHS);
|
||||
|
||||
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE,
|
||||
GPIO13 | GPIO14 | GPIO15);
|
||||
gpio_set_af(GPIOB, GPIO_AF12, GPIO13 | GPIO14 | GPIO15);
|
||||
|
||||
/* LEDS on discovery board */
|
||||
rcc_periph_clock_enable(RCC_GPIOD);
|
||||
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT,
|
||||
GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15);
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&otghs_usb_driver, "stm32f429i-disco");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
while (1) {
|
||||
gadget0_run(usbd_dev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
58
libopencm3/tests/gadget-zero/main-stm32f4disco.c
Normal file
58
libopencm3/tests/gadget-zero/main-stm32f4disco.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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 <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
#define ER_DEBUG
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_OTGFS);
|
||||
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12);
|
||||
gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12);
|
||||
|
||||
/* LEDS on discovery board */
|
||||
rcc_periph_clock_enable(RCC_GPIOD);
|
||||
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT,
|
||||
GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15);
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&otgfs_usb_driver, "stm32f4disco");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
while (1) {
|
||||
gadget0_run(usbd_dev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
90
libopencm3/tests/gadget-zero/main-stm32l053disco.c
Normal file
90
libopencm3/tests/gadget-zero/main-stm32l053disco.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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 <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/crs.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/syscfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
/* no trace on cm0 #define ER_DEBUG */
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
#include "trace.h"
|
||||
void trace_send_blocking8(int stimulus_port, char c)
|
||||
{
|
||||
(void)stimulus_port;
|
||||
(void)c;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* LED for boot progress */
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO5);
|
||||
gpio_set(GPIOA, GPIO5);
|
||||
|
||||
/* PLL from HSI16, just to exercise that code */
|
||||
struct rcc_clock_scale myclock = {
|
||||
.ahb_frequency = 32e6,
|
||||
.apb1_frequency = 32e6,
|
||||
.apb2_frequency = 32e6,
|
||||
.flash_waitstates = 1,
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSI16_CLK, /* not even sure there's hse on l053 disco */
|
||||
/* .msi_range doesn't matter */
|
||||
.pll_mul = RCC_CFGR_PLLMUL_MUL4,
|
||||
.pll_div = RCC_CFGR_PLLDIV_DIV2,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE1_NODIV,
|
||||
.ppre2 = RCC_CFGR_PPRE2_NODIV,
|
||||
};
|
||||
rcc_clock_setup_pll(&myclock);
|
||||
|
||||
/* HSI48 needs the vrefint turned on */
|
||||
rcc_periph_clock_enable(RCC_SYSCFG);
|
||||
SYSCFG_CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48 | SYSCFG_CFGR3_EN_VREFINT;
|
||||
while (!(SYSCFG_CFGR3 & SYSCFG_CFGR3_REF_HSI48_RDYF));
|
||||
|
||||
/* For USB, but can't use HSI48 as a sysclock on L0 */
|
||||
crs_autotrim_usb_enable();
|
||||
rcc_set_hsi48_source_rc48();
|
||||
|
||||
rcc_osc_on(RCC_HSI48);
|
||||
rcc_wait_for_osc_ready(RCC_HSI48);
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&st_usbfs_v2_usb_driver,
|
||||
"stm32l053disco");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
gpio_clear(GPIOA, GPIO5);
|
||||
while (1) {
|
||||
gadget0_run(usbd_dev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
81
libopencm3/tests/gadget-zero/main-stm32l1-generic.c
Normal file
81
libopencm3/tests/gadget-zero/main-stm32l1-generic.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* "generic" could be any L1 board, but this file is pre-configured for the
|
||||
* libopencm3-tests "hw1" board, with an stm32l151c8-A part.
|
||||
*/
|
||||
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/flash.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/syscfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
#define ER_DEBUG
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
const struct rcc_clock_scale this_clock_config = {
|
||||
/* 32MHz PLL from 16MHz HSE, 96MHz for USB on PLL VCO out */
|
||||
.pll_source = RCC_CFGR_PLLSRC_HSE_CLK,
|
||||
.pll_mul = RCC_CFGR_PLLMUL_MUL6,
|
||||
.pll_div = RCC_CFGR_PLLDIV_DIV3,
|
||||
.hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
|
||||
.ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
|
||||
.voltage_scale = PWR_SCALE1,
|
||||
.flash_waitstates = 1,
|
||||
.ahb_frequency = 32000000,
|
||||
.apb1_frequency = 32000000,
|
||||
.apb2_frequency = 32000000,
|
||||
};
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_GPIOB);
|
||||
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8|GPIO9);
|
||||
gpio_set(GPIOB, GPIO8);
|
||||
rcc_clock_setup_pll(&this_clock_config);
|
||||
|
||||
/* Enable built in USB pullup on L1 */
|
||||
rcc_periph_clock_enable(RCC_SYSCFG);
|
||||
SYSCFG_PMC |= SYSCFG_PMC_USB_PU;
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&st_usbfs_v1_usb_driver,
|
||||
"stm32l1-generic");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
gpio_clear(GPIOB, GPIO8);
|
||||
while (1) {
|
||||
gpio_set(GPIOB, GPIO9);
|
||||
gadget0_run(usbd_dev);
|
||||
gpio_clear(GPIOB, GPIO9);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
70
libopencm3/tests/gadget-zero/main-tilm4f120xl.c
Normal file
70
libopencm3/tests/gadget-zero/main-tilm4f120xl.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2018 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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 <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/lm4f/gpio.h>
|
||||
#include <libopencm3/lm4f/rcc.h>
|
||||
#include <libopencm3/lm4f/systemcontrol.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "delay.h"
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
#define ER_DEBUG
|
||||
#ifdef ER_DEBUG
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
/* FIXME - implement delay functionality for better test coverage */
|
||||
void delay_setup(void) {
|
||||
}
|
||||
|
||||
void delay_us(uint16_t us) {
|
||||
(void)us;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
gpio_enable_ahb_aperture();
|
||||
#define PLL_DIV_80MHZ 5
|
||||
rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, PLL_DIV_80MHZ);
|
||||
periph_clock_enable(RCC_GPIOD);
|
||||
gpio_mode_setup(GPIOD, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4 | GPIO5);
|
||||
|
||||
/* blue LED on board */
|
||||
periph_clock_enable(RCC_GPIOF);
|
||||
gpio_mode_setup(GPIOF, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO2);
|
||||
gpio_set_output_config(GPIOF, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, GPIO2);
|
||||
|
||||
usbd_device *usbd_dev = gadget0_init(&lm4f_usb_driver, "tilm4f120xl");
|
||||
|
||||
ER_DPRINTF("bootup complete\n");
|
||||
while (1) {
|
||||
gpio_set(GPIOF, GPIO2);
|
||||
gadget0_run(usbd_dev);
|
||||
gpio_clear(GPIOF, GPIO2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
10
libopencm3/tests/gadget-zero/openocd.common.cfg
Normal file
10
libopencm3/tests/gadget-zero/openocd.common.cfg
Normal file
@@ -0,0 +1,10 @@
|
||||
# Shared openocd script helpers
|
||||
|
||||
# put things like "hla_serial 'asdfadfa'" in openocd.<board>.local.cfg to support
|
||||
# multiple simultaneously connected boards.
|
||||
proc optional_local { LOCAL_FILE } {
|
||||
if { [ file exists $LOCAL_FILE ] } {
|
||||
puts "Loading custom local settings from $LOCAL_FILE"
|
||||
source $LOCAL_FILE
|
||||
}
|
||||
}
|
||||
14
libopencm3/tests/gadget-zero/openocd.efm32hg309-generic.cfg
Normal file
14
libopencm3/tests/gadget-zero/openocd.efm32hg309-generic.cfg
Normal file
@@ -0,0 +1,14 @@
|
||||
# Generic efm32hg309 on Tomu board, using stm32l053-disco as debugger
|
||||
source [find interface/stlink-v2-1.cfg]
|
||||
transport select hla_swd
|
||||
adapter_khz 1000
|
||||
set CHIPNAME efm32hg309
|
||||
set CPUTAPID 0x0bc11477
|
||||
source [find target/efm32.cfg]
|
||||
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.efm32hg309-generic.local.cfg"
|
||||
|
||||
init
|
||||
targets
|
||||
reset halt
|
||||
14
libopencm3/tests/gadget-zero/openocd.stm32f072disco.cfg
Normal file
14
libopencm3/tests/gadget-zero/openocd.stm32f072disco.cfg
Normal file
@@ -0,0 +1,14 @@
|
||||
source [find interface/stlink-v2.cfg]
|
||||
set WORKAREASIZE 0x4000
|
||||
source [find target/stm32f0x.cfg]
|
||||
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.stm32f072disco.local.cfg"
|
||||
|
||||
# no trace on cm0
|
||||
#tpiu config internal swodump.stm32f4disco.log uart off 168000000
|
||||
|
||||
# Uncomment to reset on connect, for grabbing under WFI et al
|
||||
reset_config srst_only srst_nogate
|
||||
# reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
15
libopencm3/tests/gadget-zero/openocd.stm32f103-generic.cfg
Normal file
15
libopencm3/tests/gadget-zero/openocd.stm32f103-generic.cfg
Normal file
@@ -0,0 +1,15 @@
|
||||
# Unfortunately, with no f103 disco, we're currently
|
||||
# using a separate disco board
|
||||
source [find interface/stlink-v2.cfg]
|
||||
set WORKAREASIZE 0x2000
|
||||
source [find target/stm32f1x.cfg]
|
||||
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.stm32f103-generic.local.cfg"
|
||||
|
||||
tpiu config internal swodump.stm32f103-generic.log uart off 72000000
|
||||
|
||||
# Uncomment to reset on connect, for grabbing under WFI et al
|
||||
reset_config srst_only srst_nogate
|
||||
# reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
14
libopencm3/tests/gadget-zero/openocd.stm32f3-disco.cfg
Normal file
14
libopencm3/tests/gadget-zero/openocd.stm32f3-disco.cfg
Normal file
@@ -0,0 +1,14 @@
|
||||
source [find interface/stlink-v2.cfg]
|
||||
set WORKAREASIZE 0x4000
|
||||
source [find target/stm32f3x.cfg]
|
||||
|
||||
# Include a local serial config file if available
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.stm32f3-disco.local.cfg"
|
||||
|
||||
tpiu config internal swodump.stm32f3-disco.log uart off 72000000
|
||||
|
||||
# Uncomment to reset on connect, for grabbing under WFI et al
|
||||
reset_config srst_only srst_nogate
|
||||
# reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
13
libopencm3/tests/gadget-zero/openocd.stm32f429i-disco.cfg
Normal file
13
libopencm3/tests/gadget-zero/openocd.stm32f429i-disco.cfg
Normal file
@@ -0,0 +1,13 @@
|
||||
source [find interface/stlink-v2.cfg]
|
||||
set WORKAREASIZE 0x4000
|
||||
source [find target/stm32f4x.cfg]
|
||||
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.stm32f429i-disco.local.cfg"
|
||||
|
||||
tpiu config internal swodump.stm32f429i-disco.log uart off 168000000
|
||||
|
||||
# Uncomment to reset on connect, for grabbing under WFI et al
|
||||
reset_config srst_only srst_nogate
|
||||
# reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
13
libopencm3/tests/gadget-zero/openocd.stm32f4disco.cfg
Normal file
13
libopencm3/tests/gadget-zero/openocd.stm32f4disco.cfg
Normal file
@@ -0,0 +1,13 @@
|
||||
source [find interface/stlink-v2.cfg]
|
||||
set WORKAREASIZE 0x4000
|
||||
source [find target/stm32f4x.cfg]
|
||||
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.stm32f4disco.local.cfg"
|
||||
|
||||
tpiu config internal swodump.stm32f4disco.log uart off 168000000
|
||||
|
||||
# Uncomment to reset on connect, for grabbing under WFI et al
|
||||
reset_config srst_only srst_nogate
|
||||
# reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
14
libopencm3/tests/gadget-zero/openocd.stm32l053disco.cfg
Normal file
14
libopencm3/tests/gadget-zero/openocd.stm32l053disco.cfg
Normal file
@@ -0,0 +1,14 @@
|
||||
source [find interface/stlink-v2-1.cfg]
|
||||
set WORKAREASIZE 0x1000
|
||||
source [find target/stm32l0.cfg]
|
||||
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.stm32l053disco.local.cfg"
|
||||
|
||||
# no trace on cm0
|
||||
#tpiu config internal swodump.stm32f4disco.log uart off 168000000
|
||||
|
||||
# Uncomment to reset on connect, for grabbing under WFI et al
|
||||
reset_config srst_only srst_nogate
|
||||
# reset_config srst_only srst_nogate connect_assert_srst
|
||||
|
||||
13
libopencm3/tests/gadget-zero/openocd.stm32l1-generic.cfg
Normal file
13
libopencm3/tests/gadget-zero/openocd.stm32l1-generic.cfg
Normal file
@@ -0,0 +1,13 @@
|
||||
# l1 generic, using a l4 disco board
|
||||
source [find interface/stlink-v2-1.cfg]
|
||||
set WORKAREASIZE 0x2000
|
||||
source [find target/stm32l1.cfg]
|
||||
|
||||
source openocd.common.cfg
|
||||
optional_local "openocd.stm32l1-generic.local.cfg"
|
||||
|
||||
tpiu config internal swodump.stm32l1-generic.log uart off 32000000
|
||||
|
||||
# Uncomment to reset on connect, for grabbing under WFI et al
|
||||
reset_config srst_only srst_nogate
|
||||
# reset_config srst_only srst_nogate connect_assert_srst
|
||||
4
libopencm3/tests/gadget-zero/stub.py
Normal file
4
libopencm3/tests/gadget-zero/stub.py
Normal file
@@ -0,0 +1,4 @@
|
||||
__author__ = 'karlp'
|
||||
|
||||
def config_switch():
|
||||
pass
|
||||
545
libopencm3/tests/gadget-zero/test_gadget0.py
Normal file
545
libopencm3/tests/gadget-zero/test_gadget0.py
Normal file
@@ -0,0 +1,545 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Tests for the libopencm3 USB stack. Uses pyusb to make a variety of transfers, both legal and illegal to
|
||||
exercise as many paths of the stack as possible for consistency and functionality.
|
||||
|
||||
By default, will attempt to run the test suite against any detected compatible firmware, based on a fixed
|
||||
VID:PID pair defined in the firmware. Can also be told to test just a single device
|
||||
|
||||
Requires pyusb. unittest-xml-reporting also required for xUnit reports
|
||||
"""
|
||||
import argparse
|
||||
import array
|
||||
import datetime
|
||||
import random
|
||||
import usb.core
|
||||
import usb.util as uu
|
||||
import random
|
||||
import sys
|
||||
|
||||
import unittest
|
||||
|
||||
VENDOR_ID=0xcafe
|
||||
PRODUCT_ID=0xcafe
|
||||
|
||||
# you only need to worry about these if you are trying to explicitly test
|
||||
# a single target. Normally, the test will autofind the attached target
|
||||
DUT_SERIAL=None
|
||||
#DUT_SERIAL = "stm32f429i-disco"
|
||||
#DUT_SERIAL = "stm32f4disco"
|
||||
#DUT_SERIAL = "stm32f103-generic"
|
||||
#DUT_SERIAL = "stm32l1-generic"
|
||||
#DUT_SERIAL = "stm32f072disco"
|
||||
#DUT_SERIAL = "stm32l053disco"
|
||||
|
||||
GZ_REQ_SET_PATTERN=1
|
||||
GZ_REQ_PRODUCE=2
|
||||
GZ_REQ_SET_ALIGNED=3
|
||||
GZ_REQ_SET_UNALIGNED=4
|
||||
GZ_REQ_WRITE_LOOPBACK_BUFFER=10
|
||||
GZ_REQ_READ_LOOPBACK_BUFFER=11
|
||||
GZ_REQ_INTEL_WRITE=0x5b
|
||||
GZ_REQ_INTEL_READ=0x5c
|
||||
|
||||
class find_by_serial(object):
|
||||
def __init__(self, serial):
|
||||
self._serial = serial
|
||||
|
||||
def __call__(self, device):
|
||||
return usb.util.get_string(device, device.iSerialNumber)
|
||||
|
||||
|
||||
class TestGadget0(unittest.TestCase):
|
||||
# TODO - parameterize this with serial numbers so we can find
|
||||
# gadget 0 code for different devices. (or use different PIDs?)
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
self.longMessage = True
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def test_sanity(self):
|
||||
self.assertEqual(2, self.dev.bNumConfigurations, "Should have 2 configs")
|
||||
|
||||
def test_config_switch_2(self):
|
||||
"""
|
||||
Uses the API if you're interested in the cfg block
|
||||
"""
|
||||
cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(cfg)
|
||||
|
||||
def test_config_switch_3(self):
|
||||
"""
|
||||
Uses the simple API
|
||||
"""
|
||||
self.dev.set_configuration(3)
|
||||
|
||||
def test_config_zero_addressed(self):
|
||||
self.dev.set_configuration(0)
|
||||
x = self.dev.ctrl_transfer(0x80, 0x08, 0, 0, 1)
|
||||
self.assertEqual(0, x[0], "Should be configuration 0 before configuration is set")
|
||||
|
||||
|
||||
def test_fetch_config(self):
|
||||
self.dev.set_configuration(3)
|
||||
# FIXME - find a way to get the defines for these from pyusb
|
||||
x = self.dev.ctrl_transfer(0x80, 0x08, 0, 0, 1)
|
||||
self.assertEqual(3, x[0], "Should get the actual bConfigurationValue back")
|
||||
|
||||
def test_invalid_config(self):
|
||||
try:
|
||||
# FIXME - find a way to get the defines for these from pyusb
|
||||
self.dev.ctrl_transfer(0x00, 0x09, 99)
|
||||
self.fail("Request of invalid cfg should have failed")
|
||||
except usb.core.USBError as e:
|
||||
# Note, this might not be as portable as we'd like.
|
||||
self.assertIn("Pipe", e.strerror)
|
||||
|
||||
class TestIntelCompliance(unittest.TestCase):
|
||||
"""
|
||||
Part of intel's usb 2.0 compliance is writing and reading back control transfers
|
||||
"""
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(self.cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(self.cfg)
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def inner_t(self, mylen):
|
||||
data = [random.randrange(255) for x in range(mylen)]
|
||||
written = self.dev.ctrl_transfer(uu.CTRL_OUT | uu.CTRL_RECIPIENT_INTERFACE | uu.CTRL_TYPE_VENDOR, GZ_REQ_INTEL_WRITE, 0, 0, data)
|
||||
self.assertEqual(written, len(data), "Should have written all bytes plz")
|
||||
# now. in _theory_ I should be able to make a bulk transfer here and have it not "interfere"
|
||||
# fixme - try this out?
|
||||
read = self.dev.ctrl_transfer(uu.CTRL_IN | uu.CTRL_RECIPIENT_INTERFACE | uu.CTRL_TYPE_VENDOR, GZ_REQ_INTEL_READ, 0, 0, mylen)
|
||||
self.assertEqual(mylen, len(read))
|
||||
expected = array.array('B', [x for x in data])
|
||||
self.assertEqual(expected, read, "should have read back what we wrote")
|
||||
|
||||
def test_ctrl_loopbacks(self):
|
||||
self.inner_t(0)
|
||||
self.inner_t(10)
|
||||
self.inner_t(63)
|
||||
self.inner_t(64)
|
||||
self.inner_t(65)
|
||||
self.inner_t(140)
|
||||
self.inner_t(183)
|
||||
|
||||
|
||||
class TestConfigSourceSink(unittest.TestCase):
|
||||
"""
|
||||
We could inherit, but it doesn't save much, and this saves me from remembering how to call super.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(self.cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(self.cfg)
|
||||
self.intf = self.cfg[(0, 0)]
|
||||
# heh, kinda gross...
|
||||
self.ep_out = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_OUT][0]
|
||||
self.ep_in = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_IN][0]
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def test_write_simple(self):
|
||||
"""
|
||||
here we go, start off with just a simple write of < bMaxPacketSize and just make sure it's accepted
|
||||
:return:
|
||||
"""
|
||||
data = [x for x in range(int(self.ep_out.wMaxPacketSize / 2))]
|
||||
written = self.dev.write(self.ep_out, data)
|
||||
self.assertEqual(written, len(data), "Should have written all bytes plz")
|
||||
|
||||
def test_write_zlp(self):
|
||||
written = self.ep_out.write([])
|
||||
self.assertEqual(0, written, "should have written zero for a zero length write y0")
|
||||
|
||||
def test_write_batch(self):
|
||||
"""
|
||||
Write 50 max sized packets. Should not stall. Will stall if firmware isn't consuming data properly
|
||||
:return:
|
||||
"""
|
||||
for i in range(50):
|
||||
data = [x for x in range(int(self.ep_out.wMaxPacketSize))]
|
||||
written = self.dev.write(self.ep_out, data)
|
||||
self.assertEqual(written, len(data), "Should have written all bytes plz")
|
||||
|
||||
def test_write_mixed(self):
|
||||
for i in range(int(self.ep_out.wMaxPacketSize / 4), self.ep_out.wMaxPacketSize * 10, 11):
|
||||
data = [x & 0xff for x in range(i)]
|
||||
written = self.ep_out.write(data)
|
||||
self.assertEqual(written, len(data), "should have written all bytes plz")
|
||||
|
||||
def test_read_zeros(self):
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, GZ_REQ_SET_PATTERN, 0)
|
||||
self.ep_in.read(self.ep_in.wMaxPacketSize) # Clear out any prior pattern data
|
||||
# unless, you know _exactly_ how much will be written by the device, always read
|
||||
# an integer multiple of max packet size, to avoid overflows.
|
||||
# the returned data will have the actual length.
|
||||
# You can't just magically read out less than the device wrote.
|
||||
read_size = self.ep_in.wMaxPacketSize * 10
|
||||
data = self.dev.read(self.ep_in, read_size)
|
||||
self.assertEqual(len(data), read_size, "Should have read as much as we asked for")
|
||||
expected = array.array('B', [0 for x in range(read_size)])
|
||||
self.assertEqual(data, expected, "In pattern 0, all source data should be zeros: ")
|
||||
|
||||
def test_read_sequence(self):
|
||||
# switching to the mod63 pattern requires resynching carefully to read out any zero frames already
|
||||
# queued, but still make sure we start the sequence at zero.
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, GZ_REQ_SET_PATTERN, 1)
|
||||
self.ep_in.read(self.ep_in.wMaxPacketSize) # Potentially queued zeros, or would have been safe.
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, GZ_REQ_SET_PATTERN, 1)
|
||||
self.ep_in.read(self.ep_in.wMaxPacketSize) # definitely right pattern now, but need to restart at zero.
|
||||
read_size = self.ep_in.wMaxPacketSize * 3
|
||||
data = self.dev.read(self.ep_in, read_size)
|
||||
self.assertEqual(len(data), read_size, "Should have read as much as we asked for")
|
||||
expected = array.array('B', [x % 63 for x in range(read_size)])
|
||||
self.assertEqual(data, expected, "In pattern 1, Should be % 63")
|
||||
|
||||
def test_read_write_interleaved(self):
|
||||
for i in range(1, 20):
|
||||
ii = self.ep_in.read(self.ep_in.wMaxPacketSize * i)
|
||||
dd = [x & 0xff for x in range(i * 20 + 3)]
|
||||
oo = self.ep_out.write(dd)
|
||||
self.assertEqual(len(ii), self.ep_in.wMaxPacketSize * i, "should have read full packet")
|
||||
self.assertEqual(oo, len(dd), "should have written full packet")
|
||||
|
||||
def test_control_known(self):
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, GZ_REQ_SET_PATTERN, 0)
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, GZ_REQ_SET_PATTERN, 1)
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, GZ_REQ_SET_PATTERN, 99)
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, GZ_REQ_SET_PATTERN, 0)
|
||||
|
||||
def test_control_unknown(self):
|
||||
try:
|
||||
self.dev.ctrl_transfer(uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE, 42, 69)
|
||||
self.fail("Should have got a stall")
|
||||
except usb.core.USBError as e:
|
||||
# Note, this might not be as portable as we'd like.
|
||||
self.assertIn("Pipe", e.strerror)
|
||||
|
||||
|
||||
class TestConfigLoopBack(unittest.TestCase):
|
||||
"""
|
||||
We could inherit, but it doesn't save much, and this saves me from remembering how to call super.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=3)
|
||||
self.assertIsNotNone(self.cfg, "Config 3 should exist")
|
||||
self.dev.set_configuration(self.cfg)
|
||||
self.intf = self.cfg[(0, 0)]
|
||||
# heh, kinda gross...
|
||||
self.eps_out = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_OUT]
|
||||
self.eps_in = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_IN]
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def _inner_basic(self, ep_out, ep_in, data):
|
||||
written = self.dev.write(ep_out, data)
|
||||
self.assertEqual(written, len(data), "Should have written all bytes plz")
|
||||
read = self.dev.read(ep_in, len(data))
|
||||
self.assertEqual(len(data), len(read))
|
||||
expected = array.array('B', [x for x in data])
|
||||
self.assertEqual(expected, read, "should have read back what we wrote")
|
||||
|
||||
|
||||
def test_simple_loop(self):
|
||||
"""Plain simple loopback, does it work at all"""
|
||||
eout = self.eps_out[0]
|
||||
ein = self.eps_in[0]
|
||||
data = [random.randrange(255) for _ in range(eout.wMaxPacketSize)]
|
||||
self._inner_basic(eout, ein, data)
|
||||
|
||||
def test_dual_loop(self):
|
||||
"""Testing that we don't mix our data up, just plain and simple"""
|
||||
dlen = self.eps_out[0].wMaxPacketSize
|
||||
data = [
|
||||
[0xaa for _ in range(dlen)],
|
||||
[0xbb for _ in range(dlen)],
|
||||
]
|
||||
for epo, epi, data in zip(self.eps_out, self.eps_in, data):
|
||||
self._inner_basic(epo, epi, data)
|
||||
|
||||
def test_dual_loop_back_to_back(self):
|
||||
"""
|
||||
write to both, _before_ we read back...
|
||||
This can expose problems with buffer management
|
||||
"""
|
||||
dlen = self.eps_out[0].wMaxPacketSize
|
||||
data = [
|
||||
[0xaa for _ in range(dlen)],
|
||||
[0xbb for _ in range(dlen)],
|
||||
]
|
||||
written = [
|
||||
self.dev.write(self.eps_out[0], data[0]),
|
||||
self.dev.write(self.eps_out[1], data[1]),
|
||||
]
|
||||
read = [
|
||||
self.dev.read(self.eps_in[0], dlen),
|
||||
self.dev.read(self.eps_in[1], dlen),
|
||||
]
|
||||
|
||||
for w, r, dat in zip(written, read, data):
|
||||
self.assertEqual(w, len(dat), "Should have written all bytes plz")
|
||||
self.assertEqual(len(dat), len(r), "Should have read back same size")
|
||||
expected = array.array('B', [x for x in dat])
|
||||
self.assertEqual(expected, r, "should have read back what we wrote")
|
||||
|
||||
|
||||
@unittest.skip("Perf tests only on demand (comment this line!)")
|
||||
class TestConfigSourceSinkPerformance(unittest.TestCase):
|
||||
"""
|
||||
Read/write throughput, roughly
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(self.cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(self.cfg)
|
||||
self.intf = self.cfg[(0, 0)]
|
||||
# heh, kinda gross...
|
||||
self.ep_out = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_OUT][0]
|
||||
self.ep_in = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_IN][0]
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def tput(self, xc, te):
|
||||
return (xc / 1024 / max(1, te.seconds + te.microseconds /
|
||||
1000000.0))
|
||||
|
||||
def test_read_perf(self):
|
||||
# I get around 990kps here...
|
||||
ts = datetime.datetime.now()
|
||||
rxc = 0
|
||||
while rxc < 5 * 1024 * 1024:
|
||||
desired = 100 * 1024
|
||||
data = self.ep_in.read(desired, timeout=0)
|
||||
self.assertEqual(desired, len(data), "Should have read all bytes plz")
|
||||
rxc += len(data)
|
||||
te = datetime.datetime.now() - ts
|
||||
print("read %s bytes in %s for %s kps" % (rxc, te, self.tput(rxc, te)))
|
||||
|
||||
def test_write_perf(self):
|
||||
# caps out around 420kps?
|
||||
ts = datetime.datetime.now()
|
||||
txc = 0
|
||||
data = [x & 0xff for x in range(100 * 1024)]
|
||||
while txc < 5 * 1024 * 1024:
|
||||
w = self.ep_out.write(data, timeout=0)
|
||||
self.assertEqual(w, len(data), "Should have written all bytes plz")
|
||||
txc += w
|
||||
te = datetime.datetime.now() - ts
|
||||
print("wrote %s bytes in %s for %s kps" % (txc, te, self.tput(txc, te)))
|
||||
|
||||
|
||||
class TestControlTransfer_Reads(unittest.TestCase):
|
||||
"""
|
||||
https://github.com/libopencm3/libopencm3/pull/194
|
||||
and
|
||||
https://github.com/libopencm3/libopencm3/pull/505
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(self.cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(self.cfg)
|
||||
self.req = uu.CTRL_IN | uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE
|
||||
|
||||
def inner_t(self, wVal, read_len):
|
||||
wVal = int(wVal)
|
||||
read_len = int(read_len)
|
||||
q = self.dev.ctrl_transfer(self.req, GZ_REQ_PRODUCE, wVal, 0, read_len)
|
||||
self.assertEqual(len(q), wVal, "Should have read as much as we asked for?")
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def test_basic(self):
|
||||
x = self.dev.ctrl_transfer(self.req, GZ_REQ_PRODUCE, 32, 0, 32)
|
||||
self.assertEqual(32, len(x))
|
||||
|
||||
def test_matching_sizes(self):
|
||||
"""
|
||||
Can we request x control in when we tell the device to produce x?
|
||||
:return:
|
||||
"""
|
||||
def inner(x):
|
||||
x = int(x)
|
||||
q = self.dev.ctrl_transfer(self.req, GZ_REQ_PRODUCE, x, 0, x)
|
||||
self.assertEqual(len(q), x, "Should have read as much as we asked for")
|
||||
|
||||
ep0_size = self.dev.bMaxPacketSize0
|
||||
inner(ep0_size)
|
||||
inner(ep0_size * 3)
|
||||
inner(ep0_size / 3)
|
||||
inner(ep0_size - 7)
|
||||
inner(ep0_size + 11)
|
||||
inner(ep0_size * 4 + 11)
|
||||
|
||||
def test_waytoobig(self):
|
||||
"""
|
||||
monster reads should fail, but not fatally.
|
||||
(Don't make them too, big, or libusb will reject you outright, see MAX_CTRL_BUFFER_LENGTH in libusb sources)
|
||||
"""
|
||||
try:
|
||||
self.dev.ctrl_transfer(self.req, GZ_REQ_PRODUCE, 10 * self.dev.bMaxPacketSize0, 0, 10 * self.dev.bMaxPacketSize0)
|
||||
self.fail("Should have got a stall")
|
||||
except usb.core.USBError as e:
|
||||
# Note, this might not be as portable as we'd like.
|
||||
self.assertIn("Pipe", e.strerror)
|
||||
|
||||
def test_read_longer(self):
|
||||
"""
|
||||
Attempt to read more than the device replied with.
|
||||
This is explicitly allowed by spec:
|
||||
"On an input request, a device must never return more data than is indicated
|
||||
by the wLength value; it may return less"
|
||||
"""
|
||||
|
||||
ep0_size = self.dev.bMaxPacketSize0
|
||||
self.inner_t(ep0_size / 2, ep0_size)
|
||||
self.inner_t(ep0_size / 2, ep0_size * 2)
|
||||
self.inner_t(ep0_size + 31, ep0_size * 5)
|
||||
|
||||
def test_read_needs_zlp(self):
|
||||
ep0_size = self.dev.bMaxPacketSize0
|
||||
self.inner_t(ep0_size, ep0_size + 10)
|
||||
self.inner_t(ep0_size * 2, ep0_size * 5)
|
||||
|
||||
def test_read_zero(self):
|
||||
"""
|
||||
try and read > 0, but have the device only produce 0
|
||||
"""
|
||||
self.inner_t(0, self.dev.bMaxPacketSize0)
|
||||
self.inner_t(0, 200)
|
||||
|
||||
def test_read_nothing(self):
|
||||
"""
|
||||
Don't read anything, don't create anything (no data stage)
|
||||
"""
|
||||
self.inner_t(0, 0)
|
||||
|
||||
def test_mean_limits(self):
|
||||
"""
|
||||
tell the device to produce more than we ask for.
|
||||
Note, this doesn't test the usb stack, it tests the application code behaves.
|
||||
"""
|
||||
q = self.dev.ctrl_transfer(self.req, GZ_REQ_PRODUCE, 100, 0, 10)
|
||||
self.assertEqual(len(q), 10, "In this case, should have gotten wLen back")
|
||||
|
||||
|
||||
class TestUnaligned(unittest.TestCase):
|
||||
"""
|
||||
M0 and M0+ cores don't support unaligned memory accesses. These test
|
||||
how the stack behaves with aligned vs unaligned buffers.
|
||||
https://github.com/libopencm3/libopencm3/issues/401
|
||||
https://github.com/libopencm3/libopencm3/issues/461
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(self.cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(self.cfg);
|
||||
self.req = uu.CTRL_OUT | uu.CTRL_TYPE_VENDOR | uu.CTRL_RECIPIENT_INTERFACE
|
||||
self.intf = self.cfg[(0, 0)]
|
||||
# heh, kinda gross...
|
||||
self.ep_out = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_OUT][0]
|
||||
self.ep_in = [ep for ep in self.intf if uu.endpoint_direction(ep.bEndpointAddress) == uu.ENDPOINT_IN][0]
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def set_unaligned(self):
|
||||
# GZ_REQ_SET_UNALIGNED
|
||||
self.dev.ctrl_transfer(self.req, GZ_REQ_SET_UNALIGNED, 0, 0)
|
||||
|
||||
def set_aligned(self):
|
||||
# GZ_REQ_SET_ALIGNED
|
||||
self.dev.ctrl_transfer(self.req, GZ_REQ_SET_ALIGNED, 0, 0)
|
||||
|
||||
def do_readwrite(self):
|
||||
"""
|
||||
transfer garbage data to/from bulk EP; alignment issues will hardfault the target
|
||||
"""
|
||||
data = [x for x in range(int(self.ep_out.wMaxPacketSize / 2))]
|
||||
written = self.dev.write(self.ep_out, data)
|
||||
self.assertEqual(written, len(data), "Should have written all bytes plz")
|
||||
|
||||
read_size = self.ep_in.wMaxPacketSize * 10
|
||||
data = self.dev.read(self.ep_in, read_size)
|
||||
self.assertEqual(len(data), read_size, "Should have read as much as we asked for")
|
||||
|
||||
def test_aligned(self):
|
||||
self.set_aligned()
|
||||
self.do_readwrite()
|
||||
|
||||
def test_unaligned(self):
|
||||
self.set_unaligned()
|
||||
self.do_readwrite()
|
||||
|
||||
|
||||
def run_ci_test(dut):
|
||||
# Avoids the import for non-CI users!
|
||||
import xmlrunner
|
||||
print("Running (CI) tests for DUT: ", dut)
|
||||
#with open("TEST-%s.xml" % dut, 'wb') as output:
|
||||
unittest.main(exit=False, argv=[__file__], testRunner=xmlrunner.XMLTestRunner(output="tests/test-%s" % dut))
|
||||
|
||||
def run_user_test(dut):
|
||||
print("Running (user) tests for DUT: ", dut)
|
||||
unittest.main(exit=False, argv=[__file__])
|
||||
|
||||
def get_parser():
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument("-d", "--dut", help="Specify a particular DUT serial to test")
|
||||
parser.add_argument("-X", "--xunit", help="Write xml 'junit' style outputs, intended for CI use", action="store_true")
|
||||
parser.add_argument("-l", "--list", help="List all detected matching devices, but don't run any tests", action="store_true")
|
||||
return parser
|
||||
|
||||
if __name__ == "__main__":
|
||||
p = get_parser()
|
||||
opts = p.parse_args()
|
||||
runner = run_user_test
|
||||
if opts.xunit:
|
||||
runner = run_ci_test
|
||||
|
||||
if opts.dut:
|
||||
runner(opts.dut)
|
||||
else:
|
||||
# scan for available and try them all!
|
||||
devs = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, find_all=True)
|
||||
for dev in devs:
|
||||
DUT_SERIAL = dev.serial_number
|
||||
if opts.list:
|
||||
print("Detected %s on bus:port-address: %s:%s-%s" % (DUT_SERIAL, dev.bus, '.'.join(map(str,dev.port_numbers)), dev.address))
|
||||
else:
|
||||
runner(DUT_SERIAL)
|
||||
|
||||
409
libopencm3/tests/gadget-zero/usb-gadget0.c
Normal file
409
libopencm3/tests/gadget-zero/usb-gadget0.c
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements linux's "Gadget zero" functionality, both the
|
||||
* "source sink" functional interface, and the "loopback" interface.
|
||||
* It _only_ uses usb includes, do _not_ include any target specific code here!
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
|
||||
#include "trace.h"
|
||||
#include "delay.h"
|
||||
#include "usb-gadget0.h"
|
||||
|
||||
#define ER_DEBUG
|
||||
#ifdef ER_DEBUG
|
||||
#include <stdio.h>
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { printf(fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define ER_DPRINTF(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* USB Vendor:Interface control requests.
|
||||
*/
|
||||
#define GZ_REQ_SET_PATTERN 1
|
||||
#define GZ_REQ_PRODUCE 2
|
||||
#define GZ_REQ_SET_ALIGNED 3
|
||||
#define GZ_REQ_SET_UNALIGNED 4
|
||||
#define INTEL_COMPLIANCE_WRITE 0x5b
|
||||
#define INTEL_COMPLIANCE_READ 0x5c
|
||||
|
||||
/* USB configurations */
|
||||
#define GZ_CFG_SOURCESINK 2
|
||||
#define GZ_CFG_LOOPBACK 3
|
||||
|
||||
#define BULK_EP_MAXPACKET 64
|
||||
|
||||
static const struct usb_device_descriptor dev = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = USB_CLASS_VENDOR,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = BULK_EP_MAXPACKET,
|
||||
|
||||
/* when we're compatible with gadget 0
|
||||
* #define DRIVER_VENDOR_NUM 0x0525
|
||||
* #define DRIVER_PRODUCT_NUM 0xa4a0
|
||||
*/
|
||||
.idVendor = 0xcafe,
|
||||
.idProduct = 0xcafe,
|
||||
.bcdDevice = 0x0001,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.bNumConfigurations = 2,
|
||||
};
|
||||
|
||||
static const struct usb_endpoint_descriptor endp_bulk[] = {
|
||||
{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x01,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = BULK_EP_MAXPACKET,
|
||||
.bInterval = 1,
|
||||
},
|
||||
{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x81,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = BULK_EP_MAXPACKET,
|
||||
.bInterval = 1,
|
||||
},
|
||||
{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x2,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = BULK_EP_MAXPACKET,
|
||||
.bInterval = 1,
|
||||
},
|
||||
{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = BULK_EP_MAXPACKET,
|
||||
.bInterval = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb_interface_descriptor iface_sourcesink[] = {
|
||||
{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_VENDOR,
|
||||
.iInterface = 0,
|
||||
.endpoint = endp_bulk,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_interface_descriptor iface_loopback[] = {
|
||||
{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0, /* still 0, as it's a different config...? */
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 4,
|
||||
.bInterfaceClass = USB_CLASS_VENDOR,
|
||||
.iInterface = 0,
|
||||
.endpoint = endp_bulk,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_interface ifaces_sourcesink[] = {
|
||||
{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = iface_sourcesink,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_interface ifaces_loopback[] = {
|
||||
{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = iface_loopback,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct usb_config_descriptor config[] = {
|
||||
{
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = 0,
|
||||
.bNumInterfaces = 1,
|
||||
.bConfigurationValue = GZ_CFG_SOURCESINK,
|
||||
.iConfiguration = 4, /* string index */
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32,
|
||||
.interface = ifaces_sourcesink,
|
||||
},
|
||||
{
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = 0,
|
||||
.bNumInterfaces = 1,
|
||||
.bConfigurationValue = GZ_CFG_LOOPBACK,
|
||||
.iConfiguration = 5, /* string index */
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32,
|
||||
.interface = ifaces_loopback,
|
||||
}
|
||||
};
|
||||
|
||||
static char serial[] = "0123456789.0123456789.0123456789";
|
||||
static const char *usb_strings[] = {
|
||||
"libopencm3",
|
||||
"Gadget-Zero",
|
||||
serial,
|
||||
"source and sink data",
|
||||
"loop input to output"
|
||||
};
|
||||
|
||||
/* Buffer to be used for control requests. */
|
||||
static uint8_t usbd_control_buffer[5*BULK_EP_MAXPACKET];
|
||||
static usbd_device *our_dev;
|
||||
|
||||
/* Private global for state */
|
||||
static struct {
|
||||
uint8_t pattern;
|
||||
int pattern_counter;
|
||||
int test_unaligned; /* If 0 (default), use 16-bit aligned buffers. This should not be declared as bool */
|
||||
} state = {
|
||||
.pattern = 0,
|
||||
.pattern_counter = 0,
|
||||
.test_unaligned = 0,
|
||||
};
|
||||
|
||||
static void gadget0_ss_out_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
(void) ep;
|
||||
uint16_t x;
|
||||
/* TODO - if you're really keen, perf test this. tiva implies it matters */
|
||||
/* char buf[64] __attribute__ ((aligned(4))); */
|
||||
uint8_t buf[BULK_EP_MAXPACKET + 1] __attribute__ ((aligned(2)));
|
||||
uint8_t *dest;
|
||||
|
||||
trace_send_blocking8(0, 'O');
|
||||
if (state.test_unaligned) {
|
||||
dest = buf + 1;
|
||||
} else {
|
||||
dest = buf;
|
||||
}
|
||||
x = usbd_ep_read_packet(usbd_dev, ep, dest, BULK_EP_MAXPACKET);
|
||||
trace_send_blocking8(1, x);
|
||||
}
|
||||
|
||||
static void gadget0_ss_in_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
(void) usbd_dev;
|
||||
uint8_t buf[BULK_EP_MAXPACKET + 1] __attribute__ ((aligned(2)));
|
||||
uint8_t *src;
|
||||
|
||||
trace_send_blocking8(0, 'I');
|
||||
if (state.test_unaligned) {
|
||||
src = buf + 1;
|
||||
} else {
|
||||
src = buf;
|
||||
}
|
||||
|
||||
switch (state.pattern) {
|
||||
case 0:
|
||||
memset(src, 0, BULK_EP_MAXPACKET);
|
||||
break;
|
||||
case 1:
|
||||
for (unsigned i = 0; i < BULK_EP_MAXPACKET; i++) {
|
||||
src[i] = state.pattern_counter++ % 63;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t x = usbd_ep_write_packet(usbd_dev, ep, src, BULK_EP_MAXPACKET);
|
||||
/* As we are calling write in the callback, this should never fail */
|
||||
trace_send_blocking8(2, x);
|
||||
if (x != BULK_EP_MAXPACKET) {
|
||||
ER_DPRINTF("failed to write?: %d\n", x);
|
||||
}
|
||||
/*assert(x == sizeof(buf));*/
|
||||
}
|
||||
|
||||
static void gadget0_in_cb_loopback(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
(void) usbd_dev;
|
||||
ER_DPRINTF("loop IN %x\n", ep);
|
||||
/* Nothing to do here, basically just indicates they read us. */
|
||||
}
|
||||
|
||||
static void gadget0_out_cb_loopback(usbd_device *usbd_dev, uint8_t ep)
|
||||
{
|
||||
uint8_t buf[BULK_EP_MAXPACKET];
|
||||
/* Copy data we received on OUT ep back to the paired IN ep */
|
||||
int x = usbd_ep_read_packet(usbd_dev, ep, buf, BULK_EP_MAXPACKET);
|
||||
int y = usbd_ep_write_packet(usbd_dev, 0x80 | ep, buf, x);
|
||||
ER_DPRINTF("loop OUT %x got %d => %d\n", ep, x, y);
|
||||
}
|
||||
|
||||
static enum usbd_request_return_codes gadget0_control_request(usbd_device *usbd_dev,
|
||||
struct usb_setup_data *req,
|
||||
uint8_t **buf,
|
||||
uint16_t *len,
|
||||
usbd_control_complete_callback *complete)
|
||||
{
|
||||
(void) usbd_dev;
|
||||
(void) complete;
|
||||
(void) buf;
|
||||
ER_DPRINTF("ctrl breq: %x, bmRT: %x, windex :%x, wlen: %x, wval :%x\n",
|
||||
req->bRequest, req->bmRequestType, req->wIndex, req->wLength,
|
||||
req->wValue);
|
||||
|
||||
/* TODO - what do the return values mean again? */
|
||||
switch (req->bRequest) {
|
||||
case GZ_REQ_SET_PATTERN:
|
||||
state.pattern_counter = 0;
|
||||
state.pattern = req->wValue;
|
||||
return USBD_REQ_HANDLED;
|
||||
case INTEL_COMPLIANCE_WRITE:
|
||||
/* accept correctly formed ctrl writes */
|
||||
if (req->bmRequestType != (USB_REQ_TYPE_VENDOR|USB_REQ_TYPE_INTERFACE)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wValue || req->wIndex) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wLength > sizeof(usbd_control_buffer)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
/* ok, mark it as accepted. */
|
||||
return USBD_REQ_HANDLED;
|
||||
case INTEL_COMPLIANCE_READ:
|
||||
if (req->bmRequestType != (USB_REQ_TYPE_IN|USB_REQ_TYPE_VENDOR|USB_REQ_TYPE_INTERFACE)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wValue || req->wIndex) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wLength > sizeof(usbd_control_buffer)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
/* ok, return what they left there earlier */
|
||||
*len = req->wLength;
|
||||
return USBD_REQ_HANDLED;
|
||||
case GZ_REQ_SET_UNALIGNED:
|
||||
state.test_unaligned = 1;
|
||||
return USBD_REQ_HANDLED;
|
||||
case GZ_REQ_SET_ALIGNED:
|
||||
state.test_unaligned = 0;
|
||||
return USBD_REQ_HANDLED;
|
||||
case GZ_REQ_PRODUCE:
|
||||
ER_DPRINTF("fake loopback of %d\n", req->wValue);
|
||||
if (req->wValue > sizeof(usbd_control_buffer)) {
|
||||
ER_DPRINTF("Can't write more than out control buffer! %d > %d\n",
|
||||
req->wValue, sizeof(usbd_control_buffer));
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
/* Don't produce more than asked for! */
|
||||
if (req->wValue > req->wLength) {
|
||||
ER_DPRINTF("Truncating reply to match wLen\n");
|
||||
*len = req->wLength;
|
||||
} else {
|
||||
*len = req->wValue;
|
||||
}
|
||||
return USBD_REQ_HANDLED;
|
||||
default:
|
||||
ER_DPRINTF("Unhandled request!\n");
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
return USBD_REQ_NEXT_CALLBACK;
|
||||
}
|
||||
|
||||
static void gadget0_set_config(usbd_device *usbd_dev, uint16_t wValue)
|
||||
{
|
||||
ER_DPRINTF("set cfg %d\n", wValue);
|
||||
switch (wValue) {
|
||||
case GZ_CFG_SOURCESINK:
|
||||
state.test_unaligned = 0;
|
||||
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
gadget0_ss_out_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
gadget0_ss_in_cb);
|
||||
usbd_register_control_callback(
|
||||
usbd_dev,
|
||||
USB_REQ_TYPE_VENDOR | USB_REQ_TYPE_INTERFACE,
|
||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
||||
gadget0_control_request);
|
||||
/* Prime source for IN data. */
|
||||
gadget0_ss_in_cb(usbd_dev, 0x81);
|
||||
break;
|
||||
case GZ_CFG_LOOPBACK:
|
||||
/*
|
||||
* The ordering here is important, as it defines the addresses
|
||||
* locality. We want to have both out endpoints in sequentially,
|
||||
* so we can test for overrunning our memory space, if that's a
|
||||
* concern on the usb peripheral.
|
||||
*/
|
||||
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
gadget0_out_cb_loopback);
|
||||
usbd_ep_setup(usbd_dev, 0x02, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
gadget0_out_cb_loopback);
|
||||
usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
gadget0_in_cb_loopback);
|
||||
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, BULK_EP_MAXPACKET,
|
||||
gadget0_in_cb_loopback);
|
||||
break;
|
||||
default:
|
||||
ER_DPRINTF("set configuration unknown: %d\n", wValue);
|
||||
}
|
||||
}
|
||||
|
||||
usbd_device *gadget0_init(const usbd_driver *driver, const char *userserial)
|
||||
{
|
||||
#ifdef ER_DEBUG
|
||||
setbuf(stdout, NULL);
|
||||
#endif
|
||||
if (userserial) {
|
||||
usb_strings[2] = userserial;
|
||||
}
|
||||
our_dev = usbd_init(driver, &dev, config,
|
||||
usb_strings, 5,
|
||||
usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||
|
||||
usbd_register_set_config_callback(our_dev, gadget0_set_config);
|
||||
delay_setup();
|
||||
|
||||
return our_dev;
|
||||
}
|
||||
|
||||
void gadget0_run(usbd_device *usbd_dev)
|
||||
{
|
||||
usbd_poll(usbd_dev);
|
||||
/* This should be more than allowable! */
|
||||
delay_us(100);
|
||||
}
|
||||
42
libopencm3/tests/gadget-zero/usb-gadget0.h
Normal file
42
libopencm3/tests/gadget-zero/usb-gadget0.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef USB_GADGET0_H
|
||||
#define USB_GADGET0_H
|
||||
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
|
||||
/**
|
||||
* Start up the gadget0 framework.
|
||||
* @param driver which usbd hardware driver to use.
|
||||
* @param userserial if non-null, will become the serial number.
|
||||
* You should provide this to help the test code find something particular
|
||||
* to the hardware.
|
||||
* @return the usbd_device created.
|
||||
*/
|
||||
usbd_device *gadget0_init(const usbd_driver *driver, const char *userserial);
|
||||
|
||||
/**
|
||||
* Call this forever.
|
||||
* @param usbd_dev the object returned in _init.
|
||||
* @sa gadget0_init
|
||||
*/
|
||||
void gadget0_run(usbd_device *usbd_dev);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user