9
0
Fork 0

Add QE support to STM32F4Discovery; add a test of the quadrature encoder driver

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4395 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-02-15 17:51:30 +00:00
parent b8fb066f9f
commit b6cfbef366
24 changed files with 1107 additions and 181 deletions

View File

@ -188,3 +188,5 @@
dump the system log if CONFIG_SYSLOG is selected.
6.16 2012-xx-xx Gregory Nutt <gnutt@nuttx.org>
* apps/examples/qencoder: Add a quadrature driver test.

View File

@ -39,9 +39,9 @@
SUBDIRS = adc buttons can composite dhcpd ftpc ftpd hello helloxx hidkbd \
igmp lcdrw mm mount nettest nsh null nx nxffs nxflat nxhello nximage \
nxlines nxtext ostest pashello pipe poll pwm rgmp romfs sendmail \
nxlines nxtext ostest pashello pipe poll pwm qencoder rgmp romfs \
serloop telnetd thttpd tiff touchscreen udp uip usbserial \
usbstorage usbterm wget wlan
sendmail usbstorage usbterm wget wlan
# Sub-directories that might need context setup. Directories may need
# context setup for a variety of reasons, but the most common is because
@ -56,7 +56,7 @@ SUBDIRS = adc buttons can composite dhcpd ftpc ftpd hello helloxx hidkbd \
CNTXTDIRS = pwm
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
CNTXTDIRS += adc can composite ftpd dhcpd nettest telnetd
CNTXTDIRS += adc can composite ftpd dhcpd nettest qencoder telnetd
endif
ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y)

View File

@ -906,6 +906,33 @@ examples/pwm
only available if CONFIG_PWM_PULSECOUNT is defined. Default: 0 (i.e., use
the duration, not the count).
examples/qencoder
^^^^^^^^^^^^^^^^^
This example is a simple test of a Quadrature Encoder driver. It simply reads
positional data from the encoder and prints it.,
This test depends on these specific QE/NSH configurations settings (your
specific PWM settings might require additional settings).
CONFIG_QENCODER - Enables quadrature encoder support (upper-half driver).
CONFIG_NSH_BUILTIN_APPS - Build the QE test as an NSH built-in function.
Default: Built as a standalone progrem.
Additional configuration options will mostly likely be required for the board-
specific lower-half driver. See the README.txt file in your board configuration
directory.
Specific configuration options for this example include:
CONFIG_EXAMPLES_QENCODER_DEVPATH - The path to the QE device. Default:
/dev/qe0
CONFIG_EXAMPLES_QENCODER_NSAMPLES - If CONFIG_NSH_BUILTIN_APPS
is defined, then the number of samples is provided on the command line
and this value is ignored. Otherwise, this number of samples is
collected and the program terminates. Default: Samples are collected
indefinitely.
examples/rgmp
^^^^^^^^^^^^^

View File

@ -0,0 +1,105 @@
############################################################################
# apps/examples/qe/Makefile
#
# Copyright (C) 2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
-include $(TOPDIR)/.config
-include $(TOPDIR)/Make.defs
include $(APPDIR)/Make.defs
# NuttX NX Graphics Example.
ASRCS =
CSRCS = qe_main.c
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
ifeq ($(WINTOOL),y)
BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}"
else
BIN = "$(APPDIR)/libapps$(LIBEXT)"
endif
ROOTDEPPATH = --dep-path .
# Quadrature Encoder built-in application info
APPNAME = qe
PRIORITY = SCHED_PRIORITY_DEFAULT
STACKSIZE = 2048
# Common build
VPATH =
all: .built
.PHONY: context clean depend distclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
$(COBJS): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
.built: $(OBJS)
@( for obj in $(OBJS) ; do \
$(call ARCHIVE, $(BIN), $${obj}); \
done ; )
@touch .built
.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
@touch $@
endif
context: .context
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
@touch $@
depend: .depend
clean:
@rm -f *.o *~ .*.swp .built
$(call CLEAN)
distclean: clean
@rm -f Make.dep .depend
-include Make.dep

123
apps/examples/qencoder/qe.h Normal file
View File

@ -0,0 +1,123 @@
/****************************************************************************
* examples/examples/qe/qe.h
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __APPS_EXAMPLES_QENCODER_QE_H
#define __APPS_EXAMPLES_QENCODER_QE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* CONFIG_NSH_BUILTIN_APPS - Build the QE test as an NSH built-in function.
* Default: Built as a standalone problem
* CONFIG_EXAMPLES_QENCODER_DEVPATH - The path to the QE device. Default:
* /dev/qe0
* CONFIG_EXAMPLES_QENCODER_NSAMPLES - If CONFIG_NSH_BUILTIN_APPS
* is defined, then the number of samples is provided on the command line
* and this value is ignored. Otherwise, this number of samples is
* collected and the program terminates. Default: Samples are collected
* indefinitely.
*/
#ifndef CONFIG_QENCODER
# error "QE device support is not enabled (CONFIG_QENCODER)"
#endif
#ifndef CONFIG_EXAMPLES_QENCODER_DEVPATH
# define CONFIG_EXAMPLES_QENCODER_DEVPATH "/dev/qe0"
#endif
/* Debug ********************************************************************/
#ifdef CONFIG_CPP_HAVE_VARARGS
# ifdef CONFIG_DEBUG
# define message(...) lib_rawprintf(__VA_ARGS__)
# define msgflush()
# else
# define message(...) printf(__VA_ARGS__)
# define msgflush() fflush(stdout)
# endif
#else
# ifdef CONFIG_DEBUG
# define message lib_rawprintf
# define msgflush()
# else
# define message printf
# define msgflush() fflush(stdout)
# endif
#endif
/****************************************************************************
* Public Types
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
struct qe_example_s
{
bool reset;
int nloops;
};
#endif
/****************************************************************************
* Public Variables
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
extern struct qe_example_s g_qeexample;
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: qe_devinit()
*
* Description:
* Perform architecuture-specific initialization of the QE hardware. This
* interface must be provided by all configurations using apps/examples/qe
*
****************************************************************************/
int qe_devinit(void);
#endif /* __APPS_EXAMPLES_QENCODER_QE_H */

View File

@ -0,0 +1,310 @@
/****************************************************************************
* examples/qe/qe_main.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/sensors/qencoder.h>
#include "qe.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
# define MAIN_NAME qe_main
# define MAIN_STRING "qe_main: "
#else
# define MAIN_NAME user_start
# define MAIN_STRING "user_start: "
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
struct qe_example_s g_qeexample;
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: qe_help
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
static void qe_help(void)
{
message("\nUsage: qe [OPTIONS]\n\n");
message("OPTIONS include:\n");
message(" [-n samples] number of samples\n");
message(" [-r] reset the count\n");
message(" [-h] shows this message and exits\n\n");
}
#endif
/****************************************************************************
* Name: arg_string
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
int arg_string(FAR char **arg, FAR char **value)
{
FAR char *ptr = *arg;
if (ptr[2] == '\0')
{
*value = arg[1];
return 2;
}
else
{
*value = &ptr[2];
return 1;
}
}
#endif
/****************************************************************************
* Name: arg_decimal
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
int arg_decimal(FAR char **arg, FAR long *value)
{
FAR char *string;
int ret;
ret = arg_string(arg, &string);
*value = strtol(string, NULL, 10);
return ret;
}
#endif
/****************************************************************************
* Name: parse_args
****************************************************************************/
#ifdef CONFIG_NSH_BUILTIN_APPS
void parse_args(int argc, FAR char **argv)
{
FAR char *ptr;
long value;
int index;
int nargs;
g_qeexample.reset = false;
g_qeexample.nloops = 1;
for (index = 1; index < argc; )
{
ptr = argv[index];
if (ptr[0] != '-')
{
message("Invalid options format: %s\n", ptr);
exit(0);
}
switch (ptr[1])
{
case 'n':
nargs = arg_decimal(&argv[index], &value);
if (value < 0 || value > INT_MAX)
{
message("Sample count out of range: %ld\n", value);
exit(1);
}
g_qeexample.nloops = (int)value;
index += nargs;
break;
case 'r':
g_qeexample.reset = true;
index++;
break;
case 'h':
qe_help();
exit(EXIT_SUCCESS);
default:
message("Unsupported option: %s\n", ptr);
qe_help();
exit(EXIT_FAILURE);
}
}
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: user_start/qe_main
****************************************************************************/
int MAIN_NAME(int argc, char *argv[])
{
int32_t position;
int fd;
int exitval = EXIT_SUCCESS;
int ret;
#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_QENCODER_NSAMPLES)
int nloops;
#endif
/* Parse command line arguments */
#ifdef CONFIG_NSH_BUILTIN_APPS
parse_args(argc, argv);
#endif
/* Initialization of the encoder hardware is performed by logic external to
* this test.
*/
message(MAIN_STRING "Initializing external encoder\n");
ret = qe_devinit();
if (ret != OK)
{
message(MAIN_STRING "qe_devinit failed: %d\n", ret);
exitval = EXIT_FAILURE;
goto errout;
}
/* Open the encoder device for reading */
message(MAIN_STRING "Hardware initialized. Opening the encoder device\n");
fd = open(CONFIG_EXAMPLES_QENCODER_DEVPATH, O_RDONLY);
if (fd < 0)
{
message(MAIN_STRING "open %s failed: %d\n",
CONFIG_EXAMPLES_QENCODER_DEVPATH, errno);
exitval = EXIT_FAILURE;
goto errout_with_dev;
}
/* Reset the count if so requested */
if (g_qeexample.reset)
{
message(MAIN_STRING "Resetting the count...\n");
ret = ioctl(fd, QEIOC_RESET, 0);
if (ret < 0)
{
message(MAIN_STRING "ioctl(QEIOC_RESET) failed: %d\n", errno);
exitval = EXIT_FAILURE;
goto errout_with_dev;
}
}
/* Now loop the appropriate number of times, displaying the collected
* encoder samples.
*/
#if defined(CONFIG_NSH_BUILTIN_APPS)
message(MAIN_STRING "Number of samples: %d\n", g_qeexample.nloops);
for (nloops = 0; nloops < g_qeexample.nloops; nloops++)
#elif defined(CONFIG_EXAMPLES_QENCODER_NSAMPLES)
message(MAIN_STRING "Number of samples: %d\n", CONFIG_EXAMPLES_QENCODER_NSAMPLES);
for (nloops = 0; nloops < CONFIG_EXAMPLES_QENCODER_NSAMPLES; nloops++)
#else
for (;;)
#endif
{
/* Flush any output before the loop entered or from the previous pass
* through the loop.
*/
msgflush();
/* Get the positions data using the ioctl */
ret = ioctl(fd, QEIOC_POSITION, (unsigned long)((uintptr_t)&position));
if (ret < 0)
{
message(MAIN_STRING "ioctl(QEIOC_POSITION) failed: %d\n", errno);
exitval = EXIT_FAILURE;
goto errout_with_dev;
}
/* Print the sample data on successful return */
else
{
message(MAIN_STRING " %d\n", position);
}
}
errout_with_dev:
close(fd);
errout:
message("Terminating!\n");
msgflush();
return exitval;
}

View File

@ -455,122 +455,122 @@
#define GPIO_TIM1_CH1N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM1_CH1N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN13)
#define GPIO_TIM1_CH1N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN8)
#define GPIO_TIM1_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN8)
#define GPIO_TIM1_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN9)
#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN8)
#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN9)
#define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8)
#define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN9)
#define GPIO_TIM1_CH2N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN0)
#define GPIO_TIM1_CH2N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN14)
#define GPIO_TIM1_CH2N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN10)
#define GPIO_TIM1_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN9)
#define GPIO_TIM1_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN11)
#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN9)
#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN11)
#define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9)
#define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11)
#define GPIO_TIM1_CH3N_1 (GPIO_ALT|GPIO_AF1|GPIO_PORTB|GPIO_PIN1)
#define GPIO_TIM1_CH3N_2 (GPIO_ALT|GPIO_AF1|GPIO_PORTC|GPIO_PIN15)
#define GPIO_TIM1_CH3N_3 (GPIO_ALT|GPIO_AF1|GPIO_PORTE|GPIO_PIN12)
#define GPIO_TIM1_CH3IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN10)
#define GPIO_TIM1_CH3IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN13)
#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN10)
#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN13)
#define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10)
#define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13)
#define GPIO_TIM1_CH4IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN11)
#define GPIO_TIM1_CH4IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN14)
#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN11)
#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN14)
#define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11)
#define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14)
#define GPIO_TIM1_ETR_1 (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12)
#define GPIO_TIM1_ETR_2 (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN7)
#define GPIO_TIM1_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN12)
#define GPIO_TIM1_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN7)
#define GPIO_TIM2_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM2_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN15)
#define GPIO_TIM2_CH1IN_3 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN5)
#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN15)
#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN5)
#define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15)
#define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5)
#define GPIO_TIM2_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN1)
#define GPIO_TIM2_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN3)
#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN1)
#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN3)
#define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
#define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3)
#define GPIO_TIM2_CH3IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM2_CH3IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN10)
#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN10)
#define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10)
#define GPIO_TIM2_CH4IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM2_CH4IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN11)
#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN11)
#define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11)
#define GPIO_TIM2_ETR_1 (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM2_ETR_2 (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15)
#define GPIO_TIM2_ETR_3 (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5)
#define GPIO_TIM2_ETR_1 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM2_ETR_2 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15)
#define GPIO_TIM2_ETR_3 (GPIO_ALT|GPIO_AF1|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5)
#define GPIO_TIM3_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN6)
#define GPIO_TIM3_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN4)
#define GPIO_TIM3_CH1IN_3 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN6)
#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN6)
#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN4)
#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN6)
#define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6)
#define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4)
#define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
#define GPIO_TIM3_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM3_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN5)
#define GPIO_TIM3_CH2IN_3 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN7)
#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN5)
#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN7)
#define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5)
#define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
#define GPIO_TIM3_CH3IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN0)
#define GPIO_TIM3_CH3IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN8)
#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN0)
#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN8)
#define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0)
#define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
#define GPIO_TIM3_CH4IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN1)
#define GPIO_TIM3_CH4IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN9)
#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN1)
#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN9)
#define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1)
#define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
#define GPIO_TIM3_ETR (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN2)
#define GPIO_TIM3_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN2)
#define GPIO_TIM4_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN6)
#define GPIO_TIM4_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN12)
#define GPIO_TIM4_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN6)
#define GPIO_TIM4_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN12)
#define GPIO_TIM4_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6)
#define GPIO_TIM4_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN12)
#define GPIO_TIM4_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN7)
#define GPIO_TIM4_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN13)
#define GPIO_TIM4_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN7)
#define GPIO_TIM4_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN13)
#define GPIO_TIM4_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7)
#define GPIO_TIM4_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN13)
#define GPIO_TIM4_CH3IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN8)
#define GPIO_TIM4_CH3IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN14)
#define GPIO_TIM4_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN8)
#define GPIO_TIM4_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN14)
#define GPIO_TIM4_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
#define GPIO_TIM4_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN14)
#define GPIO_TIM4_CH4IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN9)
#define GPIO_TIM4_CH4IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN15)
#define GPIO_TIM4_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN9)
#define GPIO_TIM4_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTD|GPIO_PIN15)
#define GPIO_TIM4_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
#define GPIO_TIM4_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN15)
#define GPIO_TIM4_ETR (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN0)
#define GPIO_TIM4_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN0)
#define GPIO_TIM5_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM5_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN10)
#define GPIO_TIM5_CH1IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM5_CH1IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN10)
#define GPIO_TIM5_CH1OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM5_CH1OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN10)
#define GPIO_TIM5_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN1)
#define GPIO_TIM5_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN11)
#define GPIO_TIM5_CH2IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN1)
#define GPIO_TIM5_CH2IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN11)
#define GPIO_TIM5_CH2OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1)
#define GPIO_TIM5_CH2OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN11)
#define GPIO_TIM5_CH3IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM5_CH3IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN12)
#define GPIO_TIM5_CH3IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM5_CH3IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN12)
#define GPIO_TIM5_CH3OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM5_CH3OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN12)
#define GPIO_TIM5_CH4IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM5_CH4IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN0)
#define GPIO_TIM5_CH4IN_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM5_CH4IN_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN0)
#define GPIO_TIM5_CH4OUT_1 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM5_CH4OUT_2 (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN0)
#define GPIO_TIM5_ETR (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10)
#define GPIO_TIM5_ETR (GPIO_ALT|GPIO_AF2|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTH|GPIO_PIN10)
#define GPIO_TIM8_BKIN_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN6)
#define GPIO_TIM8_BKIN_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTI|GPIO_PIN4)
#define GPIO_TIM8_CH1N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN5)
#define GPIO_TIM8_CH1N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM8_CH1N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN13)
#define GPIO_TIM8_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN6)
#define GPIO_TIM8_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN5)
#define GPIO_TIM8_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN6)
#define GPIO_TIM8_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN5)
#define GPIO_TIM8_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6)
#define GPIO_TIM8_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN5)
#define GPIO_TIM8_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN7)
#define GPIO_TIM8_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN6)
#define GPIO_TIM8_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN7)
#define GPIO_TIM8_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN6)
#define GPIO_TIM8_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7)
#define GPIO_TIM8_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN6)
#define GPIO_TIM8_CH2N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN0)
@ -579,52 +579,52 @@
#define GPIO_TIM8_CH3N_1 (GPIO_ALT|GPIO_AF3|GPIO_PORTB|GPIO_PIN1)
#define GPIO_TIM8_CH3N_2 (GPIO_ALT|GPIO_AF3|GPIO_PORTC|GPIO_PIN15)
#define GPIO_TIM8_CH3N_3 (GPIO_ALT|GPIO_AF3|GPIO_PORTH|GPIO_PIN15)
#define GPIO_TIM8_CH3IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN8)
#define GPIO_TIM8_CH3IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN7)
#define GPIO_TIM8_CH3IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN8)
#define GPIO_TIM8_CH3IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN7)
#define GPIO_TIM8_CH3OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
#define GPIO_TIM8_CH3OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN7)
#define GPIO_TIM8_CH4IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN9)
#define GPIO_TIM8_CH4IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN2)
#define GPIO_TIM8_CH4IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN9)
#define GPIO_TIM8_CH4IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTI|GPIO_PIN2)
#define GPIO_TIM8_CH4OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9)
#define GPIO_TIM8_CH4OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTI|GPIO_PIN2)
#define GPIO_TIM8_ETR_1 (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM8_ETR_2 (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN3)
#define GPIO_TIM8_ETR_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0)
#define GPIO_TIM8_ETR_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTI|GPIO_PIN3)
#define GPIO_TIM9_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM9_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN5)
#define GPIO_TIM9_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM9_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN5)
#define GPIO_TIM9_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2)
#define GPIO_TIM9_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5)
#define GPIO_TIM9_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM9_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN6)
#define GPIO_TIM9_CH2IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM9_CH2IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTE|GPIO_PIN6)
#define GPIO_TIM9_CH2OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3)
#define GPIO_TIM9_CH2OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6)
#define GPIO_TIM10_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN8)
#define GPIO_TIM10_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN6)
#define GPIO_TIM10_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN8)
#define GPIO_TIM10_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN6)
#define GPIO_TIM10_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8)
#define GPIO_TIM10_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN6)
#define GPIO_TIM11_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN9)
#define GPIO_TIM11_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN7)
#define GPIO_TIM11_CH1IN_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN9)
#define GPIO_TIM11_CH1IN_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN7)
#define GPIO_TIM11_CH1OUT_1 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9)
#define GPIO_TIM11_CH1OUT_2 (GPIO_ALT|GPIO_AF3|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN7)
#define GPIO_TIM12_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN6)
#define GPIO_TIM12_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN14)
#define GPIO_TIM12_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN6)
#define GPIO_TIM12_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTB|GPIO_PIN14)
#define GPIO_TIM12_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN6)
#define GPIO_TIM12_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN14)
#define GPIO_TIM12_CH2IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN15)
#define GPIO_TIM12_CH2IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN9)
#define GPIO_TIM12_CH2IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTC|GPIO_PIN15)
#define GPIO_TIM12_CH2IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTH|GPIO_PIN9)
#define GPIO_TIM12_CH2OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN15)
#define GPIO_TIM12_CH2OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTH|GPIO_PIN9)
#define GPIO_TIM13_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN6)
#define GPIO_TIM13_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN8)
#define GPIO_TIM13_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN6)
#define GPIO_TIM13_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN8)
#define GPIO_TIM13_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6)
#define GPIO_TIM13_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN8)
#define GPIO_TIM14_CH1IN_1 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM14_CH1IN_2 (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN9)
#define GPIO_TIM14_CH1IN_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM14_CH1IN_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PULLUP|GPIO_PORTF|GPIO_PIN9)
#define GPIO_TIM14_CH1OUT_1 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7)
#define GPIO_TIM14_CH1OUT_2 (GPIO_ALT|GPIO_AF9|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN9)

View File

@ -65,7 +65,7 @@
* Pre-processor Definitions
************************************************************************************/
/* Debug ****************************************************************************/
/* Non-standard debug that may be enabled just for testing QENCODER */
/* Non-standard debug that may be enabled just for testing the quadrature encoder */
#ifndef CONFIG_DEBUG
# undef CONFIG_DEBUG_QENCODER
@ -647,17 +647,13 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
stm32_configgpio(priv->config->ti1cfg);
stm32_configgpio(priv->config->ti2cfg);
/* Set the encoder Mode 3*/
/* Set the encoder Mode 3 */
#warning REVISIT
smcr = stm32_getreg16(priv, STM32_GTIM_SMCR_OFFSET);
smcr &= ~GTIM_SMCR_SMS_MASK;
smcr |= GTIM_SMCR_ENCMD3;
stm32_putreg16(priv, STM32_GTIM_SMCR_OFFSET, smcr);
/* Write to TIM CCER */
stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
/* TI1 Channel Configuration */
/* Disable the Channel 1: Reset the CC1E Bit */
@ -988,11 +984,11 @@ static int stm32_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long
*
* Description:
* Initialize a quadrature encoder interface. This function must be called from
* board-specific logic after input pins have been configured.
* board-specific logic.
*
* Input Parameters:
* devpath - The full path to the driver to register. E.g., "/dev/qe0"
* tim - The timer number to used. time must be an element of {1,2,3,4,5,8}
* tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8}
*
* Returned Values:
* Zero on success; A negated errno value is returned on failure.
@ -1007,8 +1003,9 @@ int stm32_qeinitialize(FAR const char *devpath, int tim)
/* Find the pre-allocated timer state structure corresponding to this timer */
priv = stm32_tim2lower(tim);
if (priv)
if (!priv)
{
qedbg("TIM%d support not configured\n", tim);
return -ENXIO;
}
@ -1016,6 +1013,7 @@ int stm32_qeinitialize(FAR const char *devpath, int tim)
if (priv->inuse)
{
qedbg("TIM%d is in-used\n", tim);
return -EBUSY;
}
@ -1024,6 +1022,7 @@ int stm32_qeinitialize(FAR const char *devpath, int tim)
ret = qe_register(devpath, (FAR struct qe_lowerhalf_s *)priv);
if (ret < 0)
{
qedbg("qe_register failed: %d\n", ret);
return ret;
}

View File

@ -96,11 +96,11 @@
*
* Description:
* Initialize a quadrature encoder interface. This function must be called from
* board-specific logic after input pins have been configured.
* board-specific logic..
*
* Input Parameters:
* devpath - The full path to the driver to register. E.g., "/dev/qe0"
* tim - The timer number to used. time must be an element of {1,2,3,4,5,8}
* tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8}
*
* Returned Values:
* Zero on success; A negated errno value is returned on failure.

View File

@ -11,9 +11,11 @@ Contents
- GNU Toolchain Options
- IDEs
- NuttX buildroot Toolchain
- stm32f4discovery-specific Configuration Options
- LEDs
- PWM
- UARTs
- Timer Inputs/Outputs
- STM32F4Discovery-specific Configuration Options
- Configurations
Development Environment
@ -139,7 +141,7 @@ NuttX buildroot Toolchain
1. You must have already configured Nuttx in <some-dir>/nuttx.
cd tools
./configure.sh stm32f4discovery/<sub-dir>
./configure.sh STM32F4Discovery/<sub-dir>
2. Download the latest buildroot package into <some-dir>
@ -165,10 +167,10 @@ NuttX buildroot Toolchain
LEDs
====
The stm32f4discovery board has four LEDs; green, organge, red and blue on the
The STM32F4Discovery board has four LEDs; green, organge, red and blue on the
board.. These LEDs are not used by the board port unless CONFIG_ARCH_LEDS is
defined. In that case, the usage by the board port is defined in
include/board.h and src/up_leds.c. The LEDs are used to encode OS-related\
include/board.h and src/up_leds.c. The LEDs are used to encode OS-related
events as follows:
SYMBOL Meaning LED1* LED2 LED3 LED4
@ -194,12 +196,120 @@ events as follows:
PWM
===
The stm32f4discovery has no real on-board PWM devices, but the board can be
The STM32F4Discovery has no real on-board PWM devices, but the board can be
configured to output a pulse train using TIM4 CH2 on PD3. This pin is
available next to the audio jack.
stm32f4discovery-specific Configuration Options
============================================
UART
====
UART/USART PINS
---------------
USART1
CK PA8
CTS PA11*
RTS PA12*
RX PA10*, PB7
TX PA9*, PB6*
USART2
CK PA4*, PD7
CTS PA0*, PD3
RTS PA1, PD4*
RX PA3, PD6
TX PA2, PD5*
USART3
CK PB12, PC12*, PD10
CTS PB13, PD11
RTS PB14, PD12*
RX PB11, PC11, PD9
TX PB10*, PC10*, PD8
UART4
RX PA1, PC11
TX PA0*, PC10*
UART5
RX PD2
TX PC12*
USART6
CK PC8, PG7**
CTS PG13**, PG15**
RTS PG12**, PG8**
RX PC7*, PG9**
TX PC6, PG14**
* Indicates pins that have other on-board functins and should be used only
with care (See table 5 in the STM32F4Discovery User Guide). The rest are
free I/O pins.
** Port G pins are not supported by the MCU
Default USART/UART Configuration
--------------------------------
USART2 is enabled in all configurations (see */defconfig). RX and TX are
configured on pins PA3 and PA2, respectively (see include/board.h).
Timer Inputs/Outputs
====================
TIM1
CH1 PA8, PE9
CH2 PA9*, PE11
CH3 PA10*, PE13
CH4 PA11*, PE14
TIM2
CH1 PA0*, PA15, PA5*
CH2 PA1, PB3*
CH3 PA2, PB10*
CH4 PA3, PB11
TIM3
CH1 PA6*, PB4, PC6
CH2 PA7*, PB5, PC7*
CH3 PB0, PC8
CH4 PB1, PC9
TIM4
CH1 PB6*, PD12*
CH2 PB7, PD13*
CH3 PB8, PD14*
CH4 PB9*, PD15*
TIM5
CH1 PA0*, PH10**
CH2 PA1, PH11**
CH3 PA2, PH12**
CH4 PA3, PI0
TIM8
CH1 PC6, PI5
CH2 PC7*, PI6
CH3 PC8, PI7
CH4 PC9, PI2
TIM9
CH1 PA2, PE5
CH2 PA3, PE6
TIM10
CH1 PB8, PF6
TIM11
CH1 PB9*, PF7
TIM12
CH1 PH6**, PB14
CH2 PC15, PH9**
TIM13
CH1 PA6*, PF8
TIM14
CH1 PA7*, PF9
* Indicates pins that have other on-board functins and should be used only
with care (See table 5 in the STM32F4Discovery User Guide). The rest are
free I/O pins.
** Port H pins are not supported by the MCU
Quadrature Encode Timer Inputs
------------------------------
If enabled (by setting CONFIG_QENCODER=y), then quadrature encoder will
user TIM2 (see nsh/defconfig) and input pins PA15, and PA1 for CH1 and
CH2, respectively (see include board.h).
STM32F4Discovery-specific Configuration Options
===============================================
CONFIG_ARCH - Identifies the arch/ subdirectory. This should
be set to:
@ -231,7 +341,7 @@ stm32f4discovery-specific Configuration Options
CONFIG_ARCH_BOARD - Identifies the configs subdirectory and
hence, the board that supports the particular chip or SoC.
CONFIG_ARCH_BOARD=stm32f4discovery (for the stm32f4discovery development board)
CONFIG_ARCH_BOARD=STM32F4Discovery (for the STM32F4Discovery development board)
CONFIG_ARCH_BOARD_name - For use in C code
@ -438,11 +548,11 @@ stm32f4discovery-specific Configuration Options
Configurations
==============
Each stm32f4discovery configuration is maintained in a sudirectory and
Each STM32F4Discovery configuration is maintained in a sudirectory and
can be selected as follow:
cd tools
./configure.sh stm32f4discovery/<subdir>
./configure.sh STM32F4Discovery/<subdir>
cd -
. ./setenv.sh
@ -461,13 +571,14 @@ Where <subdir> is one of the following:
Configures the NuttShell (nsh) located at apps/examples/nsh. The
Configuration enables both the serial and telnet NSH interfaces.
CONFIG_STM32_CODESOURCERYL=y : CodeSourcery under Linux / Mac OS X
CONFIG_STM32_CODESOURCERYL=y : CodeSourcery under Linux / Mac OS X
NOTES:
1. This example supports the PWM test (apps/examples/pwm) but this must
be manually enabled by selecting:
CONFIG_PWM=y : Enable the generic PWM infrastructure
CONFIG_STM32_TIM4=y : Enable TIM4
CONFIG_STM32_TIM4_PWM=y : Use TIM4 to generate PWM output
See also apps/examples/README.txt
@ -476,3 +587,15 @@ Where <subdir> is one of the following:
CONFIG_DEBUG_PWM
1. This example supports the Quadrature Encode test (apps/examples/qencoder)
but this must be manually enabled by selecting:
CONFIG_QENCODER=y : Enable the generic Quadrature Encoder infrastructure
CONFIG_STM32_TIM2=y : Enable TIM2
CONFIG_STM32_TIM2_QE=y : Use TIM2 as the quadrature encoder
See also apps/examples/README.txt
Special PWM-only debug options:
CONFIG_DEBUG_QENCODER

View File

@ -208,6 +208,7 @@
*
* The STM32F4 Discovery has no on-board serial devices, but the console is
* brought out to PA2 (TX) and PA3 (RX) for connection to an external serial device.
* (See the README.txt file for other options)
*/
#define GPIO_USART2_RX GPIO_USART2_RX_1
@ -227,6 +228,11 @@
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1
#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1
/* Timer Inputs/Outputs (see the README.txt file for options) */
#define GPIO_TIM2_CH1IN GPIO_TIM2_CH1IN_2
#define GPIO_TIM2_CH2IN GPIO_TIM2_CH2IN_1
/************************************************************************************
* Public Data
************************************************************************************/

View File

@ -51,3 +51,7 @@ endif
ifeq ($(CONFIG_PWM),y)
CONFIGURED_APPS += examples/pwm
endif
ifeq ($(CONFIG_QENCODER),y)
CONFIGURED_APPS += examples/qencoder
endif

View File

@ -1,7 +1,7 @@
############################################################################
# configs/stm32f4discovery/nsh/defconfig
#
# Copyright (C) 2011 Gregory Nutt. All rights reserved.
# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@ -313,18 +313,25 @@ CONFIG_STM32_PHYSR_FULLDUPLEX=0x0004
CONFIG_STM32_ETH_PTP=n
CONFIG_STM32_ETHMAC_REGDEBUG=n
#
# PWM configuration
#
# The stm32f4discovery has no real on-board PWM devices, but the board can be configured to output
# a pulse train using TIM4 CH2.
# a pulse train using TIM4 CH2. (Don't forget to set CONFIG_STM32_TIM4=y above)
#
CONFIG_PWM=n
CONFIG_STM32_TIM4=y
CONFIG_STM32_TIM4_PWM=y
CONFIG_STM32_TIM4_CHANNEL=2
#
# Quadrature Encoder configuration.
#
# Uses TIM2 (CONFIG_STM32_TIM2=y above)
#
#
CONFIG_QENCODER=n
CONFIG_STM32_TIM2_QE=y
#
# General build options
#
@ -452,6 +459,7 @@ CONFIG_DEBUG_RTC=n
CONFIG_DEBUG_ANALOG=n
CONFIG_DEBUG_PWM=n
CONFIG_DEBUG_CAN=n
CONFIG_DEBUG_QENCODER=n
CONFIG_HAVE_CXX=y
CONFIG_MM_REGIONS=2
CONFIG_ARCH_LOWPUTC=y

View File

@ -56,6 +56,10 @@ ifeq ($(CONFIG_PWM),y)
CSRCS += up_pwm.c
endif
ifeq ($(CONFIG_QENCODER),y)
CSRCS += up_qencoder.c
endif
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)

View File

@ -2,7 +2,7 @@
* configs/stm3240g_eval/src/stm3240g_internal.h
* arch/arm/src/board/stm3240g_internal.n
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without

View File

@ -2,7 +2,7 @@
* configs/stm3240g_eval/src/up_autoleds.c
* arch/arm/src/board/up_autoleds.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,7 +1,7 @@
/****************************************************************************
* configs/stm32f4discovery/src/up_buttons.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without

View File

@ -0,0 +1,144 @@
/************************************************************************************
* configs/stm32f4discovery/src/up_qencoder.c
* arch/arm/src/board/up_qencoder.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
/************************************************************************************
* Included Files
************************************************************************************/
#include <nuttx/config.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/sensors/qencoder.h>
#include <arch/board/board.h>
#include "chip.h"
#include "up_arch.h"
#include "stm32_qencoder.h"
#include "stm32f4discovery-internal.h"
/************************************************************************************
* Definitions
************************************************************************************/
/* Configuration *******************************************************************/
/* The following checks assum that the quadrature encoder is on TIM2. Make the
* appropriate changes if your configuration differes.
*/
#define HAVE_QENCODER 1
#ifndef CONFIG_QENCODER
# undef HAVE_QENCODER
#endif
#ifndef CONFIG_STM32_TIM2
# undef HAVE_QENCODER
#endif
#ifndef CONFIG_STM32_TIM2_QE
# undef HAVE_QENCODER
#endif
#ifdef HAVE_QENCODER
/* Debug ***************************************************************************/
/* Non-standard debug that may be enabled just for testing the quadrature encoder */
#ifndef CONFIG_DEBUG
# undef CONFIG_DEBUG_QENCODER
#endif
#ifdef CONFIG_DEBUG_QENCODER
# define qedbg dbg
# define qelldbg lldbg
# ifdef CONFIG_DEBUG_VERBOSE
# define qevdbg vdbg
# define qellvdbg llvdbg
# else
# define qelldbg(x...)
# define qellvdbg(x...)
# endif
#else
# define qedbg(x...)
# define qelldbg(x...)
# define qevdbg(x...)
# define qellvdbg(x...)
#endif
/************************************************************************************
* Private Functions
************************************************************************************/
/************************************************************************************
* Public Functions
************************************************************************************/
/************************************************************************************
* Name: qe_devinit
*
* Description:
* All STM32 architectures must provide the following interface to work with
* examples/qencoder.
*
************************************************************************************/
int qe_devinit(void)
{
static initialized = false;
int ret;
/* Check if we are already initialized */
if (!initialized)
{
/* Initialize a quadrature encoder interface. */
qevdbg("Initializing the quadrature encoder\n");
ret = stm32_qeinitialize("/dev/qe0", 2);
if (ret < 0)
{
qedbg("stm32_qeinitialize failed: %d\n", ret);
return ret;
}
initialized = true;
}
return OK;
}
#endif /* HAVE_QENCODER */

View File

@ -365,7 +365,13 @@ static int qe_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
* lower - An instance of the lower half interface
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
* Zero (OK) on success; a negated errno value on failure. The following
* possible error values may be returned (most are returned by
* register_driver()):
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
****************************************************************************/

View File

@ -1,8 +1,8 @@
/****************************************************************************
* fs/fs_registerreserve.c
*
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -39,6 +39,7 @@
#include <nuttx/config.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
@ -66,7 +67,7 @@
* Name: inode_namelen
****************************************************************************/
static int inode_namelen(const char *name)
static int inode_namelen(FAR const char *name)
{
const char *tmp = name;
while(*tmp && *tmp != '/') tmp++;
@ -87,7 +88,7 @@ static void inode_namecpy(char *dest, const char *src)
* Name: inode_alloc
****************************************************************************/
static FAR struct inode *inode_alloc(const char *name)
static FAR struct inode *inode_alloc(FAR const char *name)
{
int namelen = inode_namelen(name);
FAR struct inode *node = (FAR struct inode*)kzalloc(FSNODE_SIZE(namelen));
@ -142,27 +143,50 @@ static void inode_insert(FAR struct inode *node,
/****************************************************************************
* Name: inode_reserve
*
* NOTE: Caller must hold the inode semaphore
* Description:
* Reserve an (initialized) inode the pseudo file system.
*
* NOTE: Caller must hold the inode semaphore
*
* Input parameters:
* path - The path to the inode to create
* inode - The location to return the inode pointer
*
* Returned Value:
* Zero on success (with the inode point in 'inode'); A negated errno
* value is returned on failure:
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
****************************************************************************/
FAR struct inode *inode_reserve(const char *path)
int inode_reserve(FAR const char *path, FAR struct inode **inode)
{
const char *name = path;
FAR struct inode *left;
FAR struct inode *parent;
/* Assume failure */
DEBUGASSERT(path && inode);
*inode = NULL;
/* Handle paths that are interpreted as the root directory */
if (!*path || path[0] != '/')
{
return NULL;
return -EINVAL;
}
/* Find the location to insert the new subtree */
if (inode_search(&name, &left, &parent, (const char **)NULL) != NULL)
if (inode_search(&name, &left, &parent, (FAR const char **)NULL) != NULL)
{
/* Is is an error if the node already exists in the tree */
/* It is an error if the node already exists in the tree */
return NULL;
return -EEXIST;
}
/* Now we now where to insert the subtree */
@ -176,7 +200,7 @@ FAR struct inode *inode_reserve(const char *path)
* by looking at the next name.
*/
const char *next_name = inode_nextname(name);
FAR const char *next_name = inode_nextname(name);
if (*next_name)
{
/* Insert an operationless node */
@ -200,11 +224,13 @@ FAR struct inode *inode_reserve(const char *path)
if (node)
{
inode_insert(node, left, parent);
return node;
*inode = node;
return OK;
}
}
/* We get here on failures to allocate node memory */
return NULL;
return -ENOMEM;
}
}

View File

@ -1,8 +1,8 @@
/****************************************************************************
* fs/fs_internal.h
*
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -111,19 +111,19 @@ EXTERN FAR struct inode *inode_search(FAR const char **path,
FAR struct inode **parent,
FAR const char **relpath);
EXTERN void inode_free(FAR struct inode *node);
EXTERN const char *inode_nextname(const char *name);
EXTERN const char *inode_nextname(FAR const char *name);
/* fs_inodereserver.c ********************************************************/
EXTERN FAR struct inode *inode_reserve(const char *path);
EXTERN int inode_reserve(FAR const char *path, FAR struct inode **inode);
/* fs_inoderemove.c **********************************************************/
EXTERN int inode_remove(const char *path);
EXTERN int inode_remove(FAR const char *path);
/* fs_inodefind.c ************************************************************/
EXTERN FAR struct inode *inode_find(const char *path, const char **relpath);
EXTERN FAR struct inode *inode_find(FAR const char *path, const char **relpath);
/* fs_inodeaddref.c **********************************************************/

View File

@ -1,8 +1,8 @@
/****************************************************************************
* fs/fs_mount.c
*
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -193,9 +193,9 @@ mount_findfs(FAR const struct fsmap_t *fstab, FAR const char *filesystemtype)
*
****************************************************************************/
int mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data)
int mount(FAR const char *source, FAR const char *target,
FAR const char *filesystemtype, unsigned long mountflags,
FAR const void *data)
{
#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT)
#ifdef BDFS_SUPPORT
@ -205,7 +205,7 @@ int mount(const char *source, const char *target,
FAR const struct mountpt_operations *mops;
void *fshandle;
int errcode;
int status;
int ret;
/* Verify required pointer arguments */
@ -222,11 +222,11 @@ int mount(const char *source, const char *target,
/* Find the block driver */
status = find_blockdriver(source, mountflags, &blkdrvr_inode);
if (status < 0)
ret = find_blockdriver(source, mountflags, &blkdrvr_inode);
if (ret < 0)
{
fdbg("Failed to find block driver %s\n", source);
errcode = -status;
errcode = -ret;
goto errout;
}
}
@ -244,20 +244,24 @@ int mount(const char *source, const char *target,
goto errout;
}
/* Insert a dummy node -- we need to hold the inode semaphore
/* Insert a dummy node -- we need to hold the inode semaphore
* to do this because we will have a momentarily bad structure.
*/
inode_semtake();
mountpt_inode = inode_reserve(target);
if (!mountpt_inode)
ret = inode_reserve(target, &mountpt_inode);
if (ret < 0)
{
/* inode_reserve can fail for a couple of reasons, but the most likely
* one is that the inode already exists.
* one is that the inode already exists. inode_reserve may return:
*
* -EINVAL - 'path' is invalid for this operation
* -EEXIST - An inode already exists at 'path'
* -ENOMEM - Failed to allocate in-memory resources for the operation
*/
fdbg("Failed to reserve inode\n");
errcode = EBUSY;
errcode = -ret;
goto errout_with_semaphore;
}
@ -289,18 +293,18 @@ int mount(const char *source, const char *target,
/* On failure, the bind method returns -errorcode */
#ifdef BDFS_SUPPORT
status = mops->bind(blkdrvr_inode, data, &fshandle);
ret = mops->bind(blkdrvr_inode, data, &fshandle);
#else
status = mops->bind(NULL, data, &fshandle);
ret = mops->bind(NULL, data, &fshandle);
#endif
if (status != 0)
if (ret != 0)
{
/* The inode is unhappy with the blkdrvr for some reason. Back out
* the count for the reference we failed to pass and exit with an
* error.
*/
fdbg("Bind method failed: %d\n", status);
fdbg("Bind method failed: %d\n", ret);
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
if (blkdrvr_inode)
@ -309,7 +313,7 @@ int mount(const char *source, const char *target,
blkdrvr_inode->i_crefs--;
}
#endif
errcode = -status;
errcode = -ret;
goto errout_with_mountpt;
}

View File

@ -1,8 +1,8 @@
/****************************************************************************
* fs/fs_registerblockdriver.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -65,27 +65,45 @@
/****************************************************************************
* Name: register_driver
*
* Description:
* Register a block driver inode the pseudo file system.
*
* Input parameters:
* path - The path to the inode to create
* bops - The block driver operations structure
* mode - inmode priviledges (not used)
* priv - Private, user data that will be associated with the inode.
*
* Returned Value:
* Zero on success (with the inode point in 'inode'); A negated errno
* value is returned on a failure (all error values returned by
* inode_reserve):
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
****************************************************************************/
int register_blockdriver(const char *path,
const struct block_operations *bops,
mode_t mode, void *priv)
int register_blockdriver(FAR const char *path,
FAR const struct block_operations *bops,
mode_t mode, FAR void *priv)
{
struct inode *node;
int ret = -ENOMEM;
FAR struct inode *node;
int ret;
/* Insert an inode for the device driver -- we need to hold the inode semaphore
* to prevent access to the tree while we this. This is because we will have a
* momentarily bad true until we populate the inode with valid data.
/* Insert an inode for the device driver -- we need to hold the inode
* semaphore to prevent access to the tree while we this. This is because
* we will have a momentarily bad true until we populate the inode with
* valid data.
*/
inode_semtake();
node = inode_reserve(path);
if (node != NULL)
ret = inode_reserve(path, &node);
if (ret >= 0)
{
/* We have it, now populate it with block driver specific
* information.
*/
/* We have it, now populate it with block driver specific information. */
INODE_SET_BLOCK(node);

View File

@ -1,8 +1,8 @@
/****************************************************************************
* fs/fs_registerdriver.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -65,34 +65,51 @@
/****************************************************************************
* Name: register_driver
*
* Description:
* Register a character driver inode the pseudo file system.
*
* Input parameters:
* path - The path to the inode to create
* fops - The file operations structure
* mode - inmode priviledges (not used)
* priv - Private, user data that will be associated with the inode.
*
* Returned Value:
* Zero on success (with the inode point in 'inode'); A negated errno
* value is returned on a failure (all error values returned by
* inode_reserve):
*
* EINVAL - 'path' is invalid for this operation
* EEXIST - An inode already exists at 'path'
* ENOMEM - Failed to allocate in-memory resources for the operation
*
****************************************************************************/
int register_driver(const char *path, const struct file_operations *fops,
mode_t mode, void *priv)
int register_driver(FAR const char *path, FAR const struct file_operations *fops,
mode_t mode, FAR void *priv)
{
struct inode *node;
int ret = ERROR;
FAR struct inode *node;
int ret;
/* Insert a dummy node -- we need to hold the inode semaphore
* to do this because we will have a momentarily bad structure.
/* Insert a dummy node -- we need to hold the inode semaphore because we
* will have a momentarily bad structure.
*/
inode_semtake();
node = inode_reserve(path);
if (node != NULL)
ret = inode_reserve(path, &node);
if (ret >= 0)
{
/* We have it, now populate it with driver specific
* information.
*/
/* We have it, now populate it with driver specific information. */
INODE_SET_DRIVER(node);
INODE_SET_DRIVER(node);
node->u.i_ops = fops;
node->u.i_ops = fops;
#ifdef CONFIG_FILE_MODE
node->i_mode = mode;
node->i_mode = mode;
#endif
node->i_private = priv;
ret = OK;
node->i_private = priv;
ret = OK;
}
inode_semgive();