Switch to cmake build system
* use tinyprintf * ability to configure project via ccmake Signed-off-by: Amir Hammad <amir.hammad@hotmail.com>
This commit is contained in:
parent
28ccd32608
commit
ed70a1efa3
19 changed files with 1001 additions and 370 deletions
94
CMakeLists.txt
Normal file
94
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
# initialize compiler
|
||||
include (cmake/toolchain.cmake)
|
||||
|
||||
# initialize flashing
|
||||
include (cmake/openocd_flash.cmake)
|
||||
|
||||
# initilize doc
|
||||
include (cmake/doc.cmake)
|
||||
|
||||
project (libusbhost C)
|
||||
|
||||
# Declare cached variables
|
||||
|
||||
set (USE_STM32F4_FS TRUE CACHE BOOL "Use USB full speed (FS) host periphery")
|
||||
set (USE_STM32F4_HS TRUE CACHE BOOL "Use USB high speed (HS) host periphery")
|
||||
set (USE_USART_DEBUG TRUE CACHE BOOL "Use debug uart output")
|
||||
|
||||
# Set compiler and linker flags
|
||||
|
||||
set (FP_FLAGS
|
||||
"-mfloat-abi=hard -mfpu=fpv4-sp-d16 -mfp16-format=alternative"
|
||||
)
|
||||
|
||||
set (ARCH_FLAGS
|
||||
"-mthumb -mcpu=cortex-m4 ${FP_FLAGS}"
|
||||
)
|
||||
set (COMMON_FLAGS
|
||||
"-O2 -g -Wextra -Wshadow -Wredundant-decls -fno-common -ffunction-sections -fdata-sections"
|
||||
)
|
||||
|
||||
set (CMAKE_C_FLAGS
|
||||
"${COMMON_FLAGS} ${ARCH_FLAGS} -Wstrict-prototypes -Wmissing-prototypes -Wimplicit-function-declaration"
|
||||
)
|
||||
|
||||
set (CMAKE_CXX_FLAGS
|
||||
"${COMMON_FLAGS} ${ARCH_FLAGS} -Weffc++"
|
||||
)
|
||||
|
||||
# C preprocessor flags
|
||||
set (CPP_FLAGS
|
||||
" -MD -Wall -Wundef"
|
||||
)
|
||||
|
||||
add_definitions (${CPP_FLAGS})
|
||||
|
||||
# set platform
|
||||
add_definitions (-DSTM32F4)
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS
|
||||
"--static -nostartfiles -T${CMAKE_SOURCE_DIR}/libusbhost_stm32f4.ld -Wl,-Map=FIXME_ONE.map -Wl,--gc-sections -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group"
|
||||
)
|
||||
|
||||
include_directories (${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
function (init_libopencm3)
|
||||
include_directories (${CMAKE_SOURCE_DIR}/libopencm3/include)
|
||||
link_directories (${CMAKE_SOURCE_DIR}/libopencm3/lib)
|
||||
set (LIBOPENCM3_LIB opencm3_stm32f4 PARENT_SCOPE)
|
||||
execute_process (
|
||||
COMMAND sh "${CMAKE_SOURCE_DIR}/initRepo.sh"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_QUIET
|
||||
)
|
||||
endfunction (init_libopencm3)
|
||||
|
||||
message (STATUS "Initializing repository")
|
||||
init_libopencm3 ()
|
||||
message (STATUS "Repository initialized")
|
||||
|
||||
# Process cached varibles
|
||||
message (STATUS "Setuping build")
|
||||
if (USE_STM32F4_FS)
|
||||
message (STATUS "... Using USB full speed (FS) host periphery")
|
||||
add_definitions (-DUSE_STM32F4_USBH_DRIVER_FS)
|
||||
endif (USE_STM32F4_FS)
|
||||
|
||||
if (USE_STM32F4_HS)
|
||||
message (STATUS "... Using USB high speed (HS) host periphery")
|
||||
add_definitions (-DUSE_STM32F4_USBH_DRIVER_HS)
|
||||
endif (USE_STM32F4_HS)
|
||||
|
||||
if (USE_USART_DEBUG)
|
||||
message (STATUS "... Using debug uart output")
|
||||
add_definitions (-DUSART_DEBUG)
|
||||
endif (USE_USART_DEBUG)
|
||||
message (STATUS "Setup done")
|
||||
|
||||
add_custom_target (README.md
|
||||
SOURCES README.md
|
||||
)
|
||||
|
||||
add_subdirectory (src)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
TODO
|
||||
|
||||
See usbh_driver*.c in src directory for example of device drivers.
|
||||
267
Makefile
267
Makefile
|
|
@ -1,267 +0,0 @@
|
|||
##
|
||||
## This file is part of the libusbhost project.
|
||||
## Imported and adopted from libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
## Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
## Copyright (C) 2014 Amir Hammad <amir.hammad@hotmail.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/>.
|
||||
##
|
||||
|
||||
BINARY = demo
|
||||
BINARY := $(addprefix build/, demo)
|
||||
LIBUSBHOSTNAME = usbhost
|
||||
|
||||
LIBUSBHOST := $(addprefix build/lib, $(LIBUSBHOSTNAME))
|
||||
LIBNAME = opencm3_stm32f4
|
||||
DEFS = -DSTM32F4
|
||||
|
||||
# load user config
|
||||
include config.mk
|
||||
DEFS += $(USER_CONFIG)
|
||||
|
||||
ifdef USART_DEBUG
|
||||
DEFS += -DUSART_DEBUG
|
||||
endif
|
||||
|
||||
DEFS += -Iinclude
|
||||
LDSCRIPT = lib$(LIBNAME).ld
|
||||
|
||||
SRCDIR = src
|
||||
OPENCM3_DIR ?= ./libopencm3
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mfp16-format=alternative
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS)
|
||||
|
||||
################################################################################
|
||||
# OpenOCD specific variables
|
||||
|
||||
OOCD ?= openocd
|
||||
OOCD_INTERFACE ?= stlink-v2
|
||||
OOCD_BOARD ?= stm32f4discovery
|
||||
|
||||
################################################################################
|
||||
# Black Magic Probe specific variables
|
||||
# Set the BMP_PORT to a serial port and then BMP is used for flashing
|
||||
BMP_PORT ?=
|
||||
|
||||
################################################################################
|
||||
# texane/stlink specific variables
|
||||
#STLINK_PORT ?= :4242
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
NULL := 2>/dev/null
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
|
||||
PREFIX ?= arm-none-eabi
|
||||
|
||||
CC := $(PREFIX)-gcc
|
||||
CXX := $(PREFIX)-g++
|
||||
LD := $(PREFIX)-gcc
|
||||
AR := $(PREFIX)-ar
|
||||
AS := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
STFLASH = $(shell which st-flash)
|
||||
STYLECHECK := /checkpatch.pl
|
||||
STYLECHECKFLAGS := --no-tree -f --terse --mailback
|
||||
STYLECHECKFILES := $(shell find . -name '*.[ch]')
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Source files
|
||||
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
|
||||
|
||||
SRCS := $(sort $(notdir $(wildcard $(SRCDIR)/*.c)))
|
||||
OBJSDEMO := $(patsubst %.c, build/%.o ,$(SRCS))
|
||||
SRCS := $(sort $(notdir $(wildcard $(SRCDIR)/*.cpp)))
|
||||
OBJSDEMO += $(patsubst %.cpp, build/%.o ,$(SRCS))
|
||||
OBJS = $(filter-out $(BINARY).o, $(OBJSDEMO))
|
||||
|
||||
ifndef USART_DEBUG
|
||||
OBJS := $(filter-out build/usart_helpers.o, $(OBJS))
|
||||
OBJSDEMO := $(filter-out build/usart_helpers.o, $(OBJSDEMO))
|
||||
else
|
||||
$(info compiling with DEBUG functions)
|
||||
endif
|
||||
|
||||
|
||||
INCLUDE_DIR = $(OPENCM3_DIR)/include
|
||||
LIB_DIR = $(OPENCM3_DIR)/lib
|
||||
SCRIPT_DIR = $(OPENCM3_DIR)/scripts
|
||||
|
||||
###############################################################################
|
||||
# C flags
|
||||
|
||||
CFLAGS += -Ofast -g
|
||||
CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration
|
||||
CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
###############################################################################
|
||||
# C++ flags
|
||||
|
||||
CXXFLAGS += -Ofast -g
|
||||
CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++
|
||||
CXXFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
###############################################################################
|
||||
# C & C++ preprocessor common flags
|
||||
|
||||
CPPFLAGS += -MD
|
||||
CPPFLAGS += -Wall -Wundef
|
||||
CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
|
||||
|
||||
###############################################################################
|
||||
# Linker flags
|
||||
|
||||
LDFLAGS += --static -nostartfiles
|
||||
LDFLAGS += -L$(LIB_DIR)
|
||||
LDFLAGS += -T$(LDSCRIPT)
|
||||
LDFLAGS += -Wl,-Map=build/$*.map
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
ifeq ($(V),99)
|
||||
LDFLAGS += -Wl,--print-gc-sections
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Used libraries
|
||||
|
||||
LDLIBS += -l$(LIBNAME)
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
|
||||
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
||||
.SUFFIXES: .elf .bin .hex .srec .list .map .images
|
||||
.SECONDEXPANSION:
|
||||
.SECONDARY:
|
||||
|
||||
|
||||
all: elf bin lib
|
||||
doc:
|
||||
doxygen
|
||||
|
||||
elf: $(BINARY).elf
|
||||
bin: $(BINARY).bin
|
||||
hex: $(BINARY).hex
|
||||
srec: $(BINARY).srec
|
||||
list: $(BINARY).list
|
||||
lib: $(LIBUSBHOST).a
|
||||
images: $(BINARY).images
|
||||
flash: $(BINARY).flash
|
||||
|
||||
%.images: %.bin %.hex %.srec %.list %.map
|
||||
@#printf "*** $* images generated ***\n"
|
||||
|
||||
%.bin: %.elf
|
||||
@printf " OBJCOPY $(*).bin\n"
|
||||
$(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
|
||||
|
||||
%.hex: %.elf
|
||||
@#printf " OBJCOPY $(*).hex\n"
|
||||
$(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex
|
||||
|
||||
%.srec: %.elf
|
||||
@#printf " OBJCOPY $(*).srec\n"
|
||||
$(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec
|
||||
|
||||
%.list: %.elf
|
||||
@#printf " OBJDUMP $(*).list\n"
|
||||
$(Q)$(OBJDUMP) -S $(*).elf > $(*).list
|
||||
|
||||
-include $(OBJSDEMO:.o=.d)
|
||||
build/%.elf build/%.map: $(OBJSDEMO) $(LDSCRIPT)
|
||||
@printf " LD $(*).elf\n"
|
||||
$(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJSDEMO) $(LDLIBS) -o build/$*.elf
|
||||
|
||||
build/%.o:$(SRCDIR)/%.c
|
||||
@printf " CC $(*).c\n"
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $@ -c $(SRCDIR)/$*.c
|
||||
|
||||
build/%.o: $(SRCDIR)/%.cxx
|
||||
@printf " CXX $(*).cxx\n"
|
||||
$(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $@ -c $(SRCDIR)/$(*).cxx
|
||||
|
||||
build/%.o: $(SRCDIR)/%.cpp
|
||||
@printf " CXX $(*).cpp\n"
|
||||
$(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $@ -c $(SRCDIR)/$(*).cpp
|
||||
$(LIB_DIR)/lib$(LIBNAME).a:
|
||||
|
||||
clean:
|
||||
@#printf " CLEAN\n"
|
||||
@rm -f build/*
|
||||
|
||||
|
||||
%.stlink-flash: %.bin
|
||||
@printf " FLASH $<\n"
|
||||
$(Q)$(STFLASH) write $(*).bin 0x8000000
|
||||
|
||||
ifeq ($(STLINK_PORT),)
|
||||
ifeq ($(BMP_PORT),)
|
||||
ifeq ($(OOCD_SERIAL),)
|
||||
%.flash: %.hex
|
||||
@printf " FLASH $<\n"
|
||||
@# IMPORTANT: Don't use "resume", only "reset" will work correctly!
|
||||
$(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
|
||||
-f board/$(OOCD_BOARD).cfg \
|
||||
-c "init" -c "reset init" \
|
||||
-c "flash write_image erase $(*).hex" \
|
||||
-c "reset" \
|
||||
-c "shutdown" $(NULL)
|
||||
else
|
||||
%.flash: %.hex
|
||||
@printf " FLASH $<\n"
|
||||
@# IMPORTANT: Don't use "resume", only "reset" will work correctly!
|
||||
$(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
|
||||
-f board/$(OOCD_BOARD).cfg \
|
||||
-c "ft2232_serial $(OOCD_SERIAL)" \
|
||||
-c "init" -c "reset init" \
|
||||
-c "flash write_image erase $(*).hex" \
|
||||
-c "reset" \
|
||||
-c "shutdown" $(NULL)
|
||||
endif
|
||||
else
|
||||
%.flash: %.elf
|
||||
@printf " GDB $(*).elf (flash)\n"
|
||||
$(Q)$(GDB) --batch \
|
||||
-ex 'target extended-remote $(BMP_PORT)' \
|
||||
-x $(SCRIPT_DIR)/black_magic_probe_flash.scr \
|
||||
$(*).elf
|
||||
endif
|
||||
else
|
||||
%.flash: %.elf
|
||||
@printf " GDB $(*).elf (flash)\n"
|
||||
$(Q)$(GDB) --batch \
|
||||
-ex 'target extended-remote $(STLINK_PORT)' \
|
||||
-x $(SCRIPT_DIR)/stlink_flash.scr \
|
||||
$(*).elf
|
||||
endif
|
||||
|
||||
.PHONY: images clean stylecheck styleclean elf bin hex srec list testing doc
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
build/lib$(LIBUSBHOSTNAME).a: $(OBJS)
|
||||
@printf " LIB $@\n"
|
||||
$(Q)$(AR) rcs $@ $(OBJS)
|
||||
137
README.md
137
README.md
|
|
@ -1,83 +1,104 @@
|
|||
###General Information
|
||||
##General Information
|
||||
|
||||
[Link to the official repository](http://github.com/libusbhost/libusbhost)
|
||||
|
||||
**This library is in an active development.**
|
||||
**WARNING**: None of its features are considered stable !
|
||||
###Objectives
|
||||
|
||||
This library implement usb host driver allowing users use
|
||||
or write device drivers, which functionality
|
||||
is abstracted of low level implementation.
|
||||
|
||||
Main objectives are:
|
||||
- provide open-source(Lesser GPL3) usb host library for embedded devices
|
||||
- execution speed: This library doesn't use blocking sleep,
|
||||
- execution speed. This library doesn't use blocking sleep,
|
||||
making low overhead on runtime performance
|
||||
- uses static allocation for all its buffers,
|
||||
so no allocation and reallocation is affecting performance
|
||||
(possibility of memory fragmentation. execution time indeterminism),
|
||||
so no malloc(), realloc(), free().
|
||||
- written in C, with the support to use it with C++.
|
||||
- does not depend on any Operating System. Library libopencm3 is used for testing purposes and to get proper defines.
|
||||
So no runtime dependency is on this library.
|
||||
- use static allocation for all of its buffers.
|
||||
This means no allocation and reallocation is affecting performance
|
||||
(possibility of memory fragmentation. execution time indeterminism). No malloc(), realloc(), free()
|
||||
- do not depend on any operating system
|
||||
|
||||
### Supported hardware
|
||||
|
||||
- stm32f4discovery
|
||||
|
||||
Currently supported devices (yet tested) are:
|
||||
* stm32f407 (stm32f4 Discovery)
|
||||
### Supported device drivers
|
||||
|
||||
Native device drivers (mostly for demonstration purposes):
|
||||
- HUB
|
||||
- Gamepad - XBox compatible Controller
|
||||
- mouse (draft: only displays raw data)
|
||||
- USB MIDI devices (raw data + note on/off)
|
||||
|
||||
###Practical info
|
||||
## Steps to compile library and demo
|
||||
### Prerequisities
|
||||
Make sure the following prerequisities are installed to be able to compile this library
|
||||
- **git** for libopencm3 submodule fetch
|
||||
- **gcc-arm-none-eabi** toolchain for cross compilation
|
||||
- **cmake**
|
||||
- **ccmake** (optional)
|
||||
- **openocd** (optional)
|
||||
|
||||
!!! Do not forget to invoke "make clean" before new build when defines change(_TODO: remove this warning and fix the Makefile_)
|
||||
### Basic setup
|
||||
1. go to build directory located in the root of the project
|
||||
> cd build
|
||||
|
||||
2. compile demo and the library with the default options set
|
||||
> cmake .. && make
|
||||
|
||||
**How to initialize repository**
|
||||
Executable demo is placed into `build/demo.hex`.
|
||||
Library is placed into `build/src/libusbhost.a`.
|
||||
|
||||
> ./initRepo.sh
|
||||
### Advanced setup
|
||||
*cmake* initial cache variables
|
||||
<table>
|
||||
<tr>
|
||||
<th>Cache variable</th><th>Value</th><th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>USE_STM32F4_FS</td><td>TRUE</td><td>Enable STM32F4 Full Speed USB host peripheral</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>USE_STM32F4_HS</td><td>TRUE</td><td>Enable STM32F4 High Speed USB host peripheral</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>USE_USART_DEBUG</td><td>TRUE</td><td>Enable writing of the debug information to USART6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OOCD_INTERFACE</td><td>"stlink-v2"</td><td>Interface configuration file used by the openocd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OOCD_BOARD</td><td>"stm32f4discovery"</td><td>Board configuration file used by the openocd</td>
|
||||
</tr>
|
||||
</table>
|
||||
You can alter these by issuing the following commands in the build directory
|
||||
|
||||
fetch libopencm3 submodule and compile needed libraries
|
||||
- Graphical user interface
|
||||
> ccmake ..
|
||||
|
||||
**How to generate documentation**
|
||||
- Command line interface
|
||||
> cmake .. -D{VARIABLE}={VALUE}
|
||||
|
||||
> make doc
|
||||
### Flashing
|
||||
If the *openocd* is installed, `make flash` executed in the build directory
|
||||
flashes the `build/demo.hex` to the stm32f4discovery board.
|
||||
|
||||
**How to compile demo**
|
||||
### Reading debug output
|
||||
The following table represents the configuration of the debug output
|
||||
<table>
|
||||
<tr>
|
||||
<th>GPIO</th><td>GPIOC6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>USART periphery</th><td>USART6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Function</th><td>UART TX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Baud rate</th><td>921600</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Uart mode</th><td>8N1</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Edit usbh_config.h to configure the library (By default Full speed OTG periphery on stm32f4 is supported)
|
||||
## License
|
||||
|
||||
The libusbhost code is released under the terms of the GNU Lesser General
|
||||
Public License (LGPL), version 3 or later.
|
||||
|
||||
> ./compileDemo.sh
|
||||
|
||||
compiles demo, that can be flashed into stm32f4 Discovery platform and debug by USART
|
||||
|
||||
|
||||
**How to upload firmware (FLASH) to stm32f4 Discovery**
|
||||
|
||||
> sudo make flash
|
||||
|
||||
|
||||
**How to view debug data**
|
||||
|
||||
connect uart to USART6 pins on gpios: GPIOC6(TX - data), GPIOC7(RX - not used)
|
||||
configure uart baud on PC side to 921600 with 1 stop bit, no parity, 8bit data, no handshake
|
||||
|
||||
|
||||
**How to compile library only**
|
||||
|
||||
> make lib
|
||||
|
||||
**libusbhost.a** is built without usart debug support
|
||||
(check compileDemo.sh for hint on how to compile with debug)
|
||||
|
||||
|
||||
###Contact
|
||||
Amir Hammad - *amir.hammad@hotmail.com*
|
||||
|
||||
**Library is maintained there**
|
||||
> http://github.com/libusbhost/libusbhost
|
||||
|
||||
See COPYING.GPL3 and COPYING.LGPL3 for details.
|
||||
|
|
|
|||
1
build/.gitignore
vendored
1
build/.gitignore
vendored
|
|
@ -0,0 +1 @@
|
|||
*
|
||||
6
cmake/doc.cmake
Normal file
6
cmake/doc.cmake
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
add_custom_target (doc
|
||||
COMMAND doxygen
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "output is generted in the ${CMAKE_SOURCE_DIR}/doc"
|
||||
SOURCES Doxyfile
|
||||
)
|
||||
18
cmake/openocd_flash.cmake
Normal file
18
cmake/openocd_flash.cmake
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
find_program (OOCD openocd DOC "openocd executable")
|
||||
|
||||
set (OOCD_INTERFACE stlink-v2 CACHE STRING "interface config file used for openocd flashing")
|
||||
set (OOCD_BOARD stm32f4discovery CACHE STRING "board config file used for openocd flashing")
|
||||
if (OOCD)
|
||||
message (STATUS "OpenOCD found: ${OOCD}")
|
||||
message (STATUS "... interface: ${OOCD_INTERFACE}")
|
||||
message (STATUS "... board: ${OOCD_BOARD}")
|
||||
add_custom_target (flash
|
||||
COMMAND sh -c '${OOCD} -f interface/${OOCD_INTERFACE}.cfg
|
||||
-f board/${OOCD_BOARD}.cfg
|
||||
-c "init" -c "reset init"
|
||||
-c "flash write_image erase $<TARGET_FILE:demo>"
|
||||
-c "reset"
|
||||
-c "shutdown" '
|
||||
DEPENDS demo
|
||||
)
|
||||
endif (OOCD)
|
||||
15
cmake/toolchain.cmake
Normal file
15
cmake/toolchain.cmake
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
set (_CMAKE_TOOLCHAIN_PREFIX "arm-none-eabi-" CACHE STRING "toolchain prefix")
|
||||
set (_CMAKE_TOOLCHAIN_LOCATION "" CACHE STRING "toolchain location hint")
|
||||
|
||||
set (CMAKE_SYSTEM_NAME Generic)
|
||||
set (CMAKE_C_COMPILER_WORKS 1)
|
||||
set (CMAKE_CXX_COMPILER_WORKS 1)
|
||||
set (CMAKE_C_FLAGS "")
|
||||
set (CMAKE_CXX_FLAGS "")
|
||||
set (BUILD_SHARED_LIBS OFF)
|
||||
find_program (CMAKE_C_COMPILER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}gcc HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
|
||||
find_program (CMAKE_C_COMPILER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}g++ HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
|
||||
find_program (CMAKE_OBJCOPY NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objcopy HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
|
||||
find_program (CMAKE_SIZE NAMES ${_CMAKE_TOOLCHAIN_PREFIX}size HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
|
||||
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/sh
|
||||
USART_DEBUG=1 OPENCM3_DIR=libopencm3 make all
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
|
||||
USER_CONFIG =
|
||||
|
||||
|
|
@ -240,7 +240,6 @@ void device_xfer_control_read(void *data, uint16_t datalen, usbh_packet_callback
|
|||
void device_xfer_control_write_setup(const void *data, uint16_t datalen, usbh_packet_callback_t callback, usbh_device_t *dev);
|
||||
void device_xfer_control_write_data(const void *data, uint16_t datalen, usbh_packet_callback_t callback, usbh_device_t *dev);
|
||||
|
||||
|
||||
END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -59,10 +59,4 @@
|
|||
#error USBH_MAX_DEVICES > 127
|
||||
#endif
|
||||
|
||||
// Uncomment to enable OTG_HS support - low level driver
|
||||
// #define USE_STM32F4_USBH_DRIVER_HS
|
||||
|
||||
// Uncomment to enable OTG_FS support - low level driver
|
||||
#define USE_STM32F4_USBH_DRIVER_FS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ MEMORY
|
|||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE ./libopencm3/lib/libopencm3_stm32f4.ld
|
||||
INCLUDE libopencm3_stm32f4.ld
|
||||
|
||||
61
src/CMakeLists.txt
Normal file
61
src/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
if (USE_USART_DEBUG)
|
||||
set (USART_HELPERS
|
||||
usart_helpers.c
|
||||
tinyprintf.c
|
||||
)
|
||||
else (USE_USART_DEBUG)
|
||||
set (USART_HELPERS "")
|
||||
endif (USE_USART_DEBUG)
|
||||
|
||||
set (inc ${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
add_library (usbhost
|
||||
${USART_HELPERS}
|
||||
${inc}/usbh_core.h
|
||||
${inc}/usbh_driver_ac_midi.h
|
||||
${inc}/usbh_driver_gp_xbox.h
|
||||
${inc}/usbh_driver_hid_mouse.h
|
||||
${inc}/usbh_driver_hub.h
|
||||
${inc}/usbh_lld_stm32f4.h
|
||||
${inc}/driver/usbh_device_driver.h
|
||||
|
||||
usbh_core.c
|
||||
usbh_driver_ac_midi.c
|
||||
usbh_driver_ac_midi_private.h
|
||||
usbh_driver_gp_xbox.c
|
||||
usbh_driver_hid_mouse.c
|
||||
usbh_driver_hub.c
|
||||
usbh_driver_hub_private.h
|
||||
usbh_lld_stm32f4.c
|
||||
)
|
||||
|
||||
target_link_libraries (usbhost
|
||||
${LIBOPENCM3_LIB}
|
||||
)
|
||||
|
||||
add_executable (demo
|
||||
demo.c
|
||||
)
|
||||
|
||||
target_link_libraries (demo
|
||||
usbhost
|
||||
)
|
||||
|
||||
add_custom_command (TARGET demo
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:demo> ${CMAKE_BINARY_DIR}/demo.hex
|
||||
COMMENT "Generating output files: ${CMAKE_BINARY_DIR}/demo.hex"
|
||||
)
|
||||
|
||||
add_custom_command (TARGET demo
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:demo>
|
||||
COMMENT "Calculating size of the binary"
|
||||
)
|
||||
|
||||
add_custom_command (TARGET usbhost
|
||||
POST_BUILD
|
||||
COMMENT "Calculating size of the library"
|
||||
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:usbhost>
|
||||
)
|
||||
|
||||
|
|
@ -215,8 +215,13 @@ int main(void)
|
|||
* Pass array of supported device drivers
|
||||
*/
|
||||
const void *lld_drivers[] = {
|
||||
#ifdef USE_STM32F4_USBH_DRIVER_FS
|
||||
usbh_lld_stm32f4_driver_fs, // Make sure USE_STM32F4_USBH_DRIVER_FS is defined in usbh_config.h
|
||||
// usbh_lld_stm32f4_driver_hs, // Make sure USE_STM32F4_USBH_DRIVER_HS is defined in usbh_config.h
|
||||
#endif
|
||||
|
||||
#ifdef USE_STM32F4_USBH_DRIVER_HS
|
||||
usbh_lld_stm32f4_driver_hs, // Make sure USE_STM32F4_USBH_DRIVER_HS is defined in usbh_config.h
|
||||
#endif
|
||||
0
|
||||
};
|
||||
usbh_init(lld_drivers, device_drivers);
|
||||
|
|
|
|||
521
src/tinyprintf.c
Normal file
521
src/tinyprintf.c
Normal file
|
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
File: tinyprintf.c
|
||||
|
||||
Copyright (C) 2004 Kustaa Nyholm
|
||||
|
||||
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 2.1 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "tinyprintf.h"
|
||||
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
|
||||
/* Enable long int support */
|
||||
#define PRINTF_LONG_SUPPORT
|
||||
|
||||
/* Enable long long int support (implies long int support) */
|
||||
#define PRINTF_LONG_LONG_SUPPORT
|
||||
|
||||
/* Enable %z (size_t) support */
|
||||
#define PRINTF_SIZE_T_SUPPORT
|
||||
|
||||
/*
|
||||
* Configuration adjustments
|
||||
*/
|
||||
#ifdef PRINTF_SIZE_T_SUPPORT
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef PRINTF_LONG_LONG_SUPPORT
|
||||
# define PRINTF_LONG_SUPPORT
|
||||
#endif
|
||||
|
||||
/* __SIZEOF_<type>__ defined at least by gcc */
|
||||
#ifdef __SIZEOF_POINTER__
|
||||
# define SIZEOF_POINTER __SIZEOF_POINTER__
|
||||
#endif
|
||||
#ifdef __SIZEOF_LONG_LONG__
|
||||
# define SIZEOF_LONG_LONG __SIZEOF_LONG_LONG__
|
||||
#endif
|
||||
#ifdef __SIZEOF_LONG__
|
||||
# define SIZEOF_LONG __SIZEOF_LONG__
|
||||
#endif
|
||||
#ifdef __SIZEOF_INT__
|
||||
# define SIZEOF_INT __SIZEOF_INT__
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define _TFP_GCC_NO_INLINE_ __attribute__ ((noinline))
|
||||
#else
|
||||
# define _TFP_GCC_NO_INLINE_
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Implementation
|
||||
*/
|
||||
struct param {
|
||||
char lz:1; /**< Leading zeros */
|
||||
char alt:1; /**< alternate form */
|
||||
char uc:1; /**< Upper case (for base16 only) */
|
||||
char align_left:1; /**< 0 == align right (default), 1 == align left */
|
||||
unsigned int width; /**< field width */
|
||||
char sign; /**< The sign to display (if any) */
|
||||
unsigned int base; /**< number base (e.g.: 8, 10, 16) */
|
||||
char *bf; /**< Buffer to output */
|
||||
};
|
||||
|
||||
|
||||
#ifdef PRINTF_LONG_LONG_SUPPORT
|
||||
static void _TFP_GCC_NO_INLINE_ ulli2a(
|
||||
unsigned long long int num, struct param *p)
|
||||
{
|
||||
int n = 0;
|
||||
unsigned long long int d = 1;
|
||||
char *bf = p->bf;
|
||||
while (num / d >= p->base)
|
||||
d *= p->base;
|
||||
while (d != 0) {
|
||||
int dgt = num / d;
|
||||
num %= d;
|
||||
d /= p->base;
|
||||
if (n || dgt > 0 || d == 0) {
|
||||
*bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
*bf = 0;
|
||||
}
|
||||
|
||||
static void lli2a(long long int num, struct param *p)
|
||||
{
|
||||
if (num < 0) {
|
||||
num = -num;
|
||||
p->sign = '-';
|
||||
}
|
||||
ulli2a(num, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
static void uli2a(unsigned long int num, struct param *p)
|
||||
{
|
||||
int n = 0;
|
||||
unsigned long int d = 1;
|
||||
char *bf = p->bf;
|
||||
while (num / d >= p->base)
|
||||
d *= p->base;
|
||||
while (d != 0) {
|
||||
int dgt = num / d;
|
||||
num %= d;
|
||||
d /= p->base;
|
||||
if (n || dgt > 0 || d == 0) {
|
||||
*bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
*bf = 0;
|
||||
}
|
||||
|
||||
static void li2a(long num, struct param *p)
|
||||
{
|
||||
if (num < 0) {
|
||||
num = -num;
|
||||
p->sign = '-';
|
||||
}
|
||||
uli2a(num, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ui2a(unsigned int num, struct param *p)
|
||||
{
|
||||
int n = 0;
|
||||
unsigned int d = 1;
|
||||
char *bf = p->bf;
|
||||
while (num / d >= p->base)
|
||||
d *= p->base;
|
||||
while (d != 0) {
|
||||
int dgt = num / d;
|
||||
num %= d;
|
||||
d /= p->base;
|
||||
if (n || dgt > 0 || d == 0) {
|
||||
*bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
*bf = 0;
|
||||
}
|
||||
|
||||
static void i2a(int num, struct param *p)
|
||||
{
|
||||
if (num < 0) {
|
||||
num = -num;
|
||||
p->sign = '-';
|
||||
}
|
||||
ui2a(num, p);
|
||||
}
|
||||
|
||||
static int a2d(char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
return ch - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char a2u(char ch, const char **src, int base, unsigned int *nump)
|
||||
{
|
||||
const char *p = *src;
|
||||
unsigned int num = 0;
|
||||
int digit;
|
||||
while ((digit = a2d(ch)) >= 0) {
|
||||
if (digit > base)
|
||||
break;
|
||||
num = num * base + digit;
|
||||
ch = *p++;
|
||||
}
|
||||
*src = p;
|
||||
*nump = num;
|
||||
return ch;
|
||||
}
|
||||
|
||||
static void putchw(void *putp, putcf putf, struct param *p)
|
||||
{
|
||||
char ch;
|
||||
int n = p->width;
|
||||
char *bf = p->bf;
|
||||
|
||||
/* Number of filling characters */
|
||||
while (*bf++ && n > 0)
|
||||
n--;
|
||||
if (p->sign)
|
||||
n--;
|
||||
if (p->alt && p->base == 16)
|
||||
n -= 2;
|
||||
else if (p->alt && p->base == 8)
|
||||
n--;
|
||||
|
||||
/* Fill with space to align to the right, before alternate or sign */
|
||||
if (!p->lz && !p->align_left) {
|
||||
while (n-- > 0)
|
||||
putf(putp, ' ');
|
||||
}
|
||||
|
||||
/* print sign */
|
||||
if (p->sign)
|
||||
putf(putp, p->sign);
|
||||
|
||||
/* Alternate */
|
||||
if (p->alt && p->base == 16) {
|
||||
putf(putp, '0');
|
||||
putf(putp, (p->uc ? 'X' : 'x'));
|
||||
} else if (p->alt && p->base == 8) {
|
||||
putf(putp, '0');
|
||||
}
|
||||
|
||||
/* Fill with zeros, after alternate or sign */
|
||||
if (p->lz) {
|
||||
while (n-- > 0)
|
||||
putf(putp, '0');
|
||||
}
|
||||
|
||||
/* Put actual buffer */
|
||||
bf = p->bf;
|
||||
while ((ch = *bf++))
|
||||
putf(putp, ch);
|
||||
|
||||
/* Fill with space to align to the left, after string */
|
||||
if (!p->lz && p->align_left) {
|
||||
while (n-- > 0)
|
||||
putf(putp, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
void tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
|
||||
{
|
||||
struct param p;
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
char bf[23]; /* long = 64b on some architectures */
|
||||
#else
|
||||
char bf[12]; /* int = 32b on some architectures */
|
||||
#endif
|
||||
char ch;
|
||||
p.bf = bf;
|
||||
|
||||
while ((ch = *(fmt++))) {
|
||||
if (ch != '%') {
|
||||
putf(putp, ch);
|
||||
} else {
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
char lng = 0; /* 1 for long, 2 for long long */
|
||||
#endif
|
||||
/* Init parameter struct */
|
||||
p.lz = 0;
|
||||
p.alt = 0;
|
||||
p.width = 0;
|
||||
p.align_left = 0;
|
||||
p.sign = 0;
|
||||
|
||||
/* Flags */
|
||||
while ((ch = *(fmt++))) {
|
||||
switch (ch) {
|
||||
case '-':
|
||||
p.align_left = 1;
|
||||
continue;
|
||||
case '0':
|
||||
p.lz = 1;
|
||||
continue;
|
||||
case '#':
|
||||
p.alt = 1;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Width */
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
ch = a2u(ch, &fmt, 10, &(p.width));
|
||||
}
|
||||
|
||||
/* We accept 'x.y' format but don't support it completely:
|
||||
* we ignore the 'y' digit => this ignores 0-fill
|
||||
* size and makes it == width (ie. 'x') */
|
||||
if (ch == '.') {
|
||||
p.lz = 1; /* zero-padding */
|
||||
/* ignore actual 0-fill size: */
|
||||
do {
|
||||
ch = *(fmt++);
|
||||
} while ((ch >= '0') && (ch <= '9'));
|
||||
}
|
||||
|
||||
#ifdef PRINTF_SIZE_T_SUPPORT
|
||||
# ifdef PRINTF_LONG_SUPPORT
|
||||
if (ch == 'z') {
|
||||
ch = *(fmt++);
|
||||
if (sizeof(size_t) == sizeof(unsigned long int))
|
||||
lng = 1;
|
||||
# ifdef PRINTF_LONG_LONG_SUPPORT
|
||||
else if (sizeof(size_t) == sizeof(unsigned long long int))
|
||||
lng = 2;
|
||||
# endif
|
||||
} else
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
if (ch == 'l') {
|
||||
ch = *(fmt++);
|
||||
lng = 1;
|
||||
#ifdef PRINTF_LONG_LONG_SUPPORT
|
||||
if (ch == 'l') {
|
||||
ch = *(fmt++);
|
||||
lng = 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
switch (ch) {
|
||||
case 0:
|
||||
goto abort;
|
||||
case 'u':
|
||||
p.base = 10;
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
#ifdef PRINTF_LONG_LONG_SUPPORT
|
||||
if (2 == lng)
|
||||
ulli2a(va_arg(va, unsigned long long int), &p);
|
||||
else
|
||||
#endif
|
||||
if (1 == lng)
|
||||
uli2a(va_arg(va, unsigned long int), &p);
|
||||
else
|
||||
#endif
|
||||
ui2a(va_arg(va, unsigned int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
p.base = 10;
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
#ifdef PRINTF_LONG_LONG_SUPPORT
|
||||
if (2 == lng)
|
||||
lli2a(va_arg(va, long long int), &p);
|
||||
else
|
||||
#endif
|
||||
if (1 == lng)
|
||||
li2a(va_arg(va, long int), &p);
|
||||
else
|
||||
#endif
|
||||
i2a(va_arg(va, int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
#ifdef SIZEOF_POINTER
|
||||
case 'p':
|
||||
p.alt = 1;
|
||||
# if defined(SIZEOF_INT) && SIZEOF_POINTER <= SIZEOF_INT
|
||||
lng = 0;
|
||||
# elif defined(SIZEOF_LONG) && SIZEOF_POINTER <= SIZEOF_LONG
|
||||
lng = 1;
|
||||
# elif defined(SIZEOF_LONG_LONG) && SIZEOF_POINTER <= SIZEOF_LONG_LONG
|
||||
lng = 2;
|
||||
# endif
|
||||
#endif
|
||||
case 'x':
|
||||
case 'X':
|
||||
p.base = 16;
|
||||
p.uc = (ch == 'X')?1:0;
|
||||
#ifdef PRINTF_LONG_SUPPORT
|
||||
#ifdef PRINTF_LONG_LONG_SUPPORT
|
||||
if (2 == lng)
|
||||
ulli2a(va_arg(va, unsigned long long int), &p);
|
||||
else
|
||||
#endif
|
||||
if (1 == lng)
|
||||
uli2a(va_arg(va, unsigned long int), &p);
|
||||
else
|
||||
#endif
|
||||
ui2a(va_arg(va, unsigned int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
case 'o':
|
||||
p.base = 8;
|
||||
ui2a(va_arg(va, unsigned int), &p);
|
||||
putchw(putp, putf, &p);
|
||||
break;
|
||||
case 'c':
|
||||
putf(putp, (char)(va_arg(va, int)));
|
||||
break;
|
||||
case 's':
|
||||
p.bf = va_arg(va, char *);
|
||||
putchw(putp, putf, &p);
|
||||
p.bf = bf;
|
||||
break;
|
||||
case '%':
|
||||
putf(putp, ch);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
abort:;
|
||||
}
|
||||
|
||||
#if TINYPRINTF_DEFINE_TFP_PRINTF
|
||||
static putcf stdout_putf;
|
||||
static void *stdout_putp;
|
||||
|
||||
void init_printf(void *putp, putcf putf)
|
||||
{
|
||||
stdout_putf = putf;
|
||||
stdout_putp = putp;
|
||||
}
|
||||
|
||||
void tfp_printf(char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
tfp_format(stdout_putp, stdout_putf, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TINYPRINTF_DEFINE_TFP_SPRINTF
|
||||
struct _vsnprintf_putcf_data
|
||||
{
|
||||
size_t dest_capacity;
|
||||
char *dest;
|
||||
size_t num_chars;
|
||||
};
|
||||
|
||||
static void _vsnprintf_putcf(void *p, char c)
|
||||
{
|
||||
struct _vsnprintf_putcf_data *data = (struct _vsnprintf_putcf_data*)p;
|
||||
if (data->num_chars < data->dest_capacity)
|
||||
data->dest[data->num_chars] = c;
|
||||
data->num_chars ++;
|
||||
}
|
||||
|
||||
int tfp_vsnprintf(char *str, size_t size, const char *format, va_list ap)
|
||||
{
|
||||
struct _vsnprintf_putcf_data data;
|
||||
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
data.dest = str;
|
||||
data.dest_capacity = size-1;
|
||||
data.num_chars = 0;
|
||||
tfp_format(&data, _vsnprintf_putcf, format, ap);
|
||||
|
||||
if (data.num_chars < data.dest_capacity)
|
||||
data.dest[data.num_chars] = '\0';
|
||||
else
|
||||
data.dest[data.dest_capacity] = '\0';
|
||||
|
||||
return data.num_chars;
|
||||
}
|
||||
|
||||
int tfp_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
|
||||
va_start(ap, format);
|
||||
retval = tfp_vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
struct _vsprintf_putcf_data
|
||||
{
|
||||
char *dest;
|
||||
size_t num_chars;
|
||||
};
|
||||
|
||||
static void _vsprintf_putcf(void *p, char c)
|
||||
{
|
||||
struct _vsprintf_putcf_data *data = (struct _vsprintf_putcf_data*)p;
|
||||
data->dest[data->num_chars++] = c;
|
||||
}
|
||||
|
||||
int tfp_vsprintf(char *str, const char *format, va_list ap)
|
||||
{
|
||||
struct _vsprintf_putcf_data data;
|
||||
data.dest = str;
|
||||
data.num_chars = 0;
|
||||
tfp_format(&data, _vsprintf_putcf, format, ap);
|
||||
data.dest[data.num_chars] = '\0';
|
||||
return data.num_chars;
|
||||
}
|
||||
|
||||
int tfp_sprintf(char *str, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
|
||||
va_start(ap, format);
|
||||
retval = tfp_vsprintf(str, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
186
src/tinyprintf.h
Normal file
186
src/tinyprintf.h
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
File: tinyprintf.h
|
||||
|
||||
Copyright (C) 2004 Kustaa Nyholm
|
||||
|
||||
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 2.1 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
This library is really just two files: 'tinyprintf.h' and 'tinyprintf.c'.
|
||||
|
||||
They provide a simple and small (+400 loc) printf functionality to
|
||||
be used in embedded systems.
|
||||
|
||||
I've found them so useful in debugging that I do not bother with a
|
||||
debugger at all.
|
||||
|
||||
They are distributed in source form, so to use them, just compile them
|
||||
into your project.
|
||||
|
||||
Two printf variants are provided: printf and the 'sprintf' family of
|
||||
functions ('snprintf', 'sprintf', 'vsnprintf', 'vsprintf').
|
||||
|
||||
The formats supported by this implementation are:
|
||||
'c' 'd' 'i' 'o' 'p' 'u' 's' 'x' 'X'.
|
||||
|
||||
Zero padding and field width are also supported.
|
||||
|
||||
If the library is compiled with 'PRINTF_SUPPORT_LONG' defined, then
|
||||
the long specifier is also supported. Note that this will pull in some
|
||||
long math routines (pun intended!) and thus make your executable
|
||||
noticeably longer. Likewise with 'PRINTF_LONG_LONG_SUPPORT' for the
|
||||
long long specifier, and with 'PRINTF_SIZE_T_SUPPORT' for the size_t
|
||||
specifier.
|
||||
|
||||
The memory footprint of course depends on the target CPU, compiler and
|
||||
compiler options, but a rough guesstimate (based on a H8S target) is about
|
||||
1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
|
||||
Not too bad. Your mileage may vary. By hacking the source code you can
|
||||
get rid of some hundred bytes, I'm sure, but personally I feel the balance of
|
||||
functionality and flexibility versus code size is close to optimal for
|
||||
many embedded systems.
|
||||
|
||||
To use the printf, you need to supply your own character output function,
|
||||
something like :
|
||||
|
||||
void putc ( void* p, char c)
|
||||
{
|
||||
while (!SERIAL_PORT_EMPTY) ;
|
||||
SERIAL_PORT_TX_REGISTER = c;
|
||||
}
|
||||
|
||||
Before you can call printf, you need to initialize it to use your
|
||||
character output function with something like:
|
||||
|
||||
init_printf(NULL,putc);
|
||||
|
||||
Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
|
||||
the NULL (or any pointer) you pass into the 'init_printf' will eventually be
|
||||
passed to your 'putc' routine. This allows you to pass some storage space (or
|
||||
anything really) to the character output function, if necessary.
|
||||
This is not often needed but it was implemented like that because it made
|
||||
implementing the sprintf function so neat (look at the source code).
|
||||
|
||||
The code is re-entrant, except for the 'init_printf' function, so it is safe
|
||||
to call it from interrupts too, although this may result in mixed output.
|
||||
If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
|
||||
|
||||
The printf and sprintf functions are actually macros that translate to
|
||||
'tfp_printf' and 'tfp_sprintf' when 'TINYPRINTF_OVERRIDE_LIBC' is set
|
||||
(default). Setting it to 0 makes it possible to use them along with
|
||||
'stdio.h' printf's in a single source file. When
|
||||
'TINYPRINTF_OVERRIDE_LIBC' is set, please note that printf/sprintf are
|
||||
not function-like macros, so if you have variables or struct members
|
||||
with these names, things will explode in your face. Without variadic
|
||||
macros this is the best we can do to wrap these function. If it is a
|
||||
problem, just give up the macros and use the functions directly, or
|
||||
rename them.
|
||||
|
||||
It is also possible to avoid defining tfp_printf and/or tfp_sprintf by
|
||||
clearing 'TINYPRINTF_DEFINE_TFP_PRINTF' and/or
|
||||
'TINYPRINTF_DEFINE_TFP_SPRINTF' to 0. This allows for example to
|
||||
export only tfp_format, which is at the core of all the other
|
||||
functions.
|
||||
|
||||
For further details see source code.
|
||||
|
||||
regs Kusti, 23.10.2004
|
||||
*/
|
||||
|
||||
#ifndef __TFP_PRINTF__
|
||||
#define __TFP_PRINTF__
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Global configuration */
|
||||
|
||||
/* Set this to 0 if you do not want to provide tfp_printf */
|
||||
#ifndef TINYPRINTF_DEFINE_TFP_PRINTF
|
||||
# define TINYPRINTF_DEFINE_TFP_PRINTF 1
|
||||
#endif
|
||||
|
||||
/* Set this to 0 if you do not want to provide
|
||||
tfp_sprintf/snprintf/vsprintf/vsnprintf */
|
||||
#ifndef TINYPRINTF_DEFINE_TFP_SPRINTF
|
||||
# define TINYPRINTF_DEFINE_TFP_SPRINTF 1
|
||||
#endif
|
||||
|
||||
/* Set this to 0 if you do not want tfp_printf and
|
||||
tfp_{vsn,sn,vs,s}printf to be also available as
|
||||
printf/{vsn,sn,vs,s}printf */
|
||||
#ifndef TINYPRINTF_OVERRIDE_LIBC
|
||||
# define TINYPRINTF_OVERRIDE_LIBC 1
|
||||
#endif
|
||||
|
||||
/* Optional external types dependencies */
|
||||
|
||||
#if TINYPRINTF_DEFINE_TFP_SPRINTF
|
||||
# include <sys/types.h> /* size_t */
|
||||
#endif
|
||||
|
||||
/* Declarations */
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define _TFP_SPECIFY_PRINTF_FMT(fmt_idx,arg1_idx) \
|
||||
__attribute__((format (printf, fmt_idx, arg1_idx)))
|
||||
#else
|
||||
# define _TFP_SPECIFY_PRINTF_FMT(fmt_idx,arg1_idx)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*putcf) (void *, char);
|
||||
|
||||
/*
|
||||
'tfp_format' really is the central function for all tinyprintf. For
|
||||
each output character after formatting, the 'putf' callback is
|
||||
called with 2 args:
|
||||
- an arbitrary void* 'putp' param defined by the user and
|
||||
passed unmodified from 'tfp_format',
|
||||
- the character.
|
||||
The 'tfp_printf' and 'tfp_sprintf' functions simply define their own
|
||||
callback and pass to it the right 'putp' it is expecting.
|
||||
*/
|
||||
void tfp_format(void *putp, putcf putf, const char *fmt, va_list va);
|
||||
|
||||
#if TINYPRINTF_DEFINE_TFP_SPRINTF
|
||||
int tfp_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
|
||||
int tfp_snprintf(char *str, size_t size, const char *fmt, ...) \
|
||||
_TFP_SPECIFY_PRINTF_FMT(3, 4);
|
||||
int tfp_vsprintf(char *str, const char *fmt, va_list ap);
|
||||
int tfp_sprintf(char *str, const char *fmt, ...) \
|
||||
_TFP_SPECIFY_PRINTF_FMT(2, 3);
|
||||
# if TINYPRINTF_OVERRIDE_LIBC
|
||||
# define vsnprintf tfp_vsnprintf
|
||||
# define snprintf tfp_snprintf
|
||||
# define vsprintf tfp_vsprintf
|
||||
# define sprintf tfp_sprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if TINYPRINTF_DEFINE_TFP_PRINTF
|
||||
void init_printf(void *putp, putcf putf);
|
||||
void tfp_printf(char *fmt, ...) _TFP_SPECIFY_PRINTF_FMT(1, 2);
|
||||
# if TINYPRINTF_OVERRIDE_LIBC
|
||||
# define printf tfp_printf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -22,14 +22,15 @@
|
|||
|
||||
|
||||
#include "usart_helpers.h"
|
||||
#define TINYPRINTF_OVERRIDE_LIBC 0
|
||||
#define TINYPRINTF_DEFINE_TFP_SPRINTF 0
|
||||
#include "tinyprintf.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
|
||||
|
||||
#define USART_FIFO_OUT_SIZE (4096)
|
||||
uint8_t usart_fifo_out_data[USART_FIFO_OUT_SIZE];
|
||||
|
|
@ -103,35 +104,22 @@ static void usart_fifo_in_push(uint8_t aData)
|
|||
usart_fifo_in_len++;
|
||||
}
|
||||
|
||||
|
||||
static void usart_write(const char * data, uint32_t len)
|
||||
static void putf(void *arg, char c)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
usart_fifo_push(data[i]);
|
||||
}
|
||||
//unused argument
|
||||
(void)arg;
|
||||
|
||||
usart_fifo_push(c);
|
||||
}
|
||||
|
||||
void usart_printf(const char *str, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, str);
|
||||
usart_vprintf(str, va);
|
||||
tfp_format(NULL, putf, str, va);
|
||||
va_end(va);
|
||||
|
||||
}
|
||||
|
||||
void usart_vprintf(const char *str, va_list va)
|
||||
{
|
||||
char databuffer[128];
|
||||
int i = vsnprintf(databuffer, 128, str, va);
|
||||
if (i > 0) {
|
||||
usart_write(databuffer, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usart_init(uint32_t arg_usart, uint32_t baudrate)
|
||||
{
|
||||
usart_set_baudrate(arg_usart, baudrate);
|
||||
|
|
@ -145,6 +133,7 @@ void usart_init(uint32_t arg_usart, uint32_t baudrate)
|
|||
usart_enable(arg_usart);
|
||||
usart = arg_usart;
|
||||
}
|
||||
|
||||
void usart_interrupt(void)
|
||||
{
|
||||
if (usart_get_interrupt_source(usart, USART_SR_RXNE)) {
|
||||
|
|
@ -230,9 +219,7 @@ void usart_call_cmd(struct usart_commands * commands)
|
|||
LOG_PRINTF("#2");
|
||||
return;
|
||||
}
|
||||
//~ for (i = 0; i < command_len; i++) {
|
||||
//~ LOG_PRINTF("%c", command[i]);
|
||||
//~ }
|
||||
|
||||
i=0;
|
||||
while(commands[i].cmd != NULL) {
|
||||
if (!strcmp((char*)command, (char*)commands[i].cmd)) {
|
||||
|
|
@ -243,7 +230,7 @@ void usart_call_cmd(struct usart_commands * commands)
|
|||
commands[i].callback(&command[command_argindex]);
|
||||
}
|
||||
}
|
||||
usart_write("\n>>",4);
|
||||
LOG_PRINTF("\n>>");
|
||||
command_len = 0;
|
||||
command_argindex = 0;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ struct usart_commands{
|
|||
#ifdef USART_DEBUG
|
||||
void usart_init(uint32_t usart, uint32_t baudrate);
|
||||
void usart_printf(const char *str, ...);
|
||||
void usart_vprintf(const char *str, va_list va);
|
||||
void usart_fifo_send(void);
|
||||
|
||||
void usart_call_cmd(struct usart_commands * commands);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue