diff options
Diffstat (limited to 'apps/examples')
100 files changed, 18188 insertions, 0 deletions
diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig new file mode 100644 index 000000000..a20f7c2e7 --- /dev/null +++ b/apps/examples/Kconfig @@ -0,0 +1,200 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +menu "ADC example" +source "$APPSDIR/examples/adc/Kconfig" +endmenu + +menu "Buttons example" +source "$APPSDIR/examples/buttons/Kconfig" +endmenu + +menu "CAN example" +source "$APPSDIR/examples/can/Kconfig" +endmenu + +menu "USB CDC/ACM class driver example" +source "$APPSDIR/examples/cdcacm/Kconfig" +endmenu + +menu "USB composite class driver example" +source "$APPSDIR/examples/composite/Kconfig" +endmenu + +menu "DHCP server example" +source "$APPSDIR/examples/dhcpd/Kconfig" +endmenu + +menu "FTP client example" +source "$APPSDIR/examples/ftpc/Kconfig" +endmenu + +menu "FTP server example" +source "$APPSDIR/examples/ftpd/Kconfig" +endmenu + +menu "\"Hello, World!\" example" +source "$APPSDIR/examples/hello/Kconfig" +endmenu + +menu "\"Hello, World!\" C++ example" +source "$APPSDIR/examples/helloxx/Kconfig" +endmenu + +menu "USB HID keyboard example" +source "$APPSDIR/examples/hidkbd/Kconfig" +endmenu + +menu "IGMP example" +source "$APPSDIR/examples/igmp/Kconfig" +endmenu + +menu "LCD read/write example" +source "$APPSDIR/examples/lcdrw/Kconfig" +endmenu + +menu "Memory management example" +source "$APPSDIR/examples/mm/Kconfig" +endmenu + +menu "File system mount example" +source "$APPSDIR/examples/mount/Kconfig" +endmenu + +menu "FreeModBus example" +source "$APPSDIR/examples/modbus/Kconfig" +endmenu + +menu "Network test example" +source "$APPSDIR/examples/nettest/Kconfig" +endmenu + +menu "NuttShell (NSH) example" +source "$APPSDIR/examples/nsh/Kconfig" +endmenu + +menu "NULL example" +source "$APPSDIR/examples/null/Kconfig" +endmenu + +menu "NX graphics example" +source "$APPSDIR/examples/nx/Kconfig" +endmenu + +menu "NxConsole example" +source "$APPSDIR/examples/nxconsole/Kconfig" +endmenu + +menu "NXFFS file system example" +source "$APPSDIR/examples/nxffs/Kconfig" +endmenu + +menu "NXFLAT example" +source "$APPSDIR/examples/nxflat/Kconfig" +endmenu + +menu "NX graphics \"Hello, World!\" example" +source "$APPSDIR/examples/nxhello/Kconfig" +endmenu + +menu "NX graphics image example" +source "$APPSDIR/examples/nximage/Kconfig" +endmenu + +menu "NX graphics lines example" +source "$APPSDIR/examples/nxlines/Kconfig" +endmenu + +menu "NX graphics text example" +source "$APPSDIR/examples/nxtext/Kconfig" +endmenu + +menu "OS test example" +source "$APPSDIR/examples/ostest/Kconfig" +endmenu + +menu "Pascal \"Hello, World!\"example" +source "$APPSDIR/examples/pashello/Kconfig" +endmenu + +menu "Pipe example" +source "$APPSDIR/examples/pipe/Kconfig" +endmenu + +menu "Poll example" +source "$APPSDIR/examples/poll/Kconfig" +endmenu + +menu "Pulse width modulation (PWM) example" +source "$APPSDIR/examples/pwm/Kconfig" +endmenu + +menu "Quadrature encoder example" +source "$APPSDIR/examples/qencoder/Kconfig" +endmenu + +menu "RGMP example" +source "$APPSDIR/examples/rgmp/Kconfig" +endmenu + +menu "ROMFS example" +source "$APPSDIR/examples/romfs/Kconfig" +endmenu + +menu "sendmail example" +source "$APPSDIR/examples/sendmail/Kconfig" +endmenu + +menu "Serial loopback example" +source "$APPSDIR/examples/serloop/Kconfig" +endmenu + +menu "Telnet daemon example" +source "$APPSDIR/examples/telnetd/Kconfig" +endmenu + +menu "THTTPD web server example" +source "$APPSDIR/examples/thttpd/Kconfig" +endmenu + +menu "TIFF generation example" +source "$APPSDIR/examples/tiff/Kconfig" +endmenu + +menu "Touchscreen example" +source "$APPSDIR/examples/touchscreen/Kconfig" +endmenu + +menu "UDP example" +source "$APPSDIR/examples/udp/Kconfig" +endmenu + +menu "uIP web server example" +source "$APPSDIR/examples/uip/Kconfig" +endmenu + +menu "USB serial test example" +source "$APPSDIR/examples/usbserial/Kconfig" +endmenu + +menu "USB mass storage class example" +source "$APPSDIR/examples/usbstorage/Kconfig" +endmenu + +menu "USB serial terminal example" +source "$APPSDIR/examples/usbterm/Kconfig" +endmenu + +menu "Watchdog timer example" +source "$APPSDIR/examples/watchdog/Kconfig" +endmenu + +menu "wget example" +source "$APPSDIR/examples/wget/Kconfig" +endmenu + +menu "WLAN example" +source "$APPSDIR/examples/wlan/Kconfig" +endmenu diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs new file mode 100644 index 000000000..aa8d83733 --- /dev/null +++ b/apps/examples/Make.defs @@ -0,0 +1,223 @@ +############################################################################ +# apps/examples/Make.defs +# Adds selected applications to apps/ build +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_EXAMPLES_ADC),y) +CONFIGURED_APPS += examples/adc +endif + +ifeq ($(CONFIG_EXAMPLES_BUTTONS),y) +CONFIGURED_APPS += examples/buttons +endif + +ifeq ($(CONFIG_EXAMPLES_CAN),y) +CONFIGURED_APPS += examples/can +endif + +ifeq ($(CONFIG_EXAMPLES_CDCACM),y) +CONFIGURED_APPS += examples/cdcacm +endif + +ifeq ($(CONFIG_EXAMPLES_COMPOSITE),y) +CONFIGURED_APPS += examples/composite +endif + +ifeq ($(CONFIG_EXAMPLES_DHCPD),y) +CONFIGURED_APPS += examples/dhcpd +endif + +ifeq ($(CONFIG_EXAMPLES_FTPC),y) +CONFIGURED_APPS += examples/ftpc +endif + +ifeq ($(CONFIG_EXAMPLES_FTPD),y) +CONFIGURED_APPS += examples/ftpd +endif + +ifeq ($(CONFIG_EXAMPLES_HELLO),y) +CONFIGURED_APPS += examples/hello +endif + +ifeq ($(CONFIG_EXAMPLES_HELLOXX),y) +CONFIGURED_APPS += examples/helloxx +endif + +ifeq ($(CONFIG_EXAMPLES_HIDKBD),y) +CONFIGURED_APPS += examples/hidkbd +endif + +ifeq ($(CONFIG_EXAMPLES_IGMP),y) +CONFIGURED_APPS += examples/igmp +endif + +ifeq ($(CONFIG_EXAMPLES_LCDRW),y) +CONFIGURED_APPS += examples/lcdrw +endif + +ifeq ($(CONFIG_EXAMPLES_MM),y) +CONFIGURED_APPS += examples/mm +endif + +ifeq ($(CONFIG_EXAMPLES_MOUNT),y) +CONFIGURED_APPS += examples/mount +endif + +ifeq ($(CONFIG_EXAMPLES_NETTEST),y) +CONFIGURED_APPS += examples/nettest +endif + +ifeq ($(CONFIG_EXAMPLES_NSH),y) +CONFIGURED_APPS += examples/nsh +endif + +ifeq ($(CONFIG_EXAMPLES_NULL),y) +CONFIGURED_APPS += examples/null +endif + +ifeq ($(CONFIG_EXAMPLES_NX),y) +CONFIGURED_APPS += examples/nx +endif + +ifeq ($(CONFIG_EXAMPLES_NXCONSOLE),y) +CONFIGURED_APPS += examples/nxconsole +endif + +ifeq ($(CONFIG_EXAMPLES_NXFFS),y) +CONFIGURED_APPS += examples/nxffs +endif + +ifeq ($(CONFIG_EXAMPLES_NXFLAT),y) +CONFIGURED_APPS += examples/nxflat +endif + +ifeq ($(CONFIG_EXAMPLES_NXHELLO),y) +CONFIGURED_APPS += examples/nxhello +endif + +ifeq ($(CONFIG_EXAMPLES_NXIMAGE),y) +CONFIGURED_APPS += examples/nximage +endif + +ifeq ($(CONFIG_EXAMPLES_NXLINES),y) +CONFIGURED_APPS += examples/nxlines +endif + +ifeq ($(CONFIG_EXAMPLES_NXTEXT),y) +CONFIGURED_APPS += examples/nxtext +endif + +ifeq ($(CONFIG_EXAMPLES_OSTEST),y) +CONFIGURED_APPS += examples/ostest +endif + +ifeq ($(CONFIG_EXAMPLES_PASHELLO),y) +CONFIGURED_APPS += examples/pashello +endif + +ifeq ($(CONFIG_EXAMPLES_PIPE),y) +CONFIGURED_APPS += examples/pipe +endif + +ifeq ($(CONFIG_EXAMPLES_POLL),y) +CONFIGURED_APPS += examples/poll +endif + +ifeq ($(CONFIG_EXAMPLES_PWM),y) +CONFIGURED_APPS += examples/pwm +endif + +ifeq ($(CONFIG_EXAMPLES_QENCODER),y) +CONFIGURED_APPS += examples/qencoder +endif + +ifeq ($(CONFIG_EXAMPLES_RGMP),y) +CONFIGURED_APPS += examples/rgmp +endif + +ifeq ($(CONFIG_EXAMPLES_ROMFS),y) +CONFIGURED_APPS += examples/romfs +endif + +ifeq ($(CONFIG_EXAMPLES_SENDMAIL),y) +CONFIGURED_APPS += examples/sendmail +endif + +ifeq ($(CONFIG_EXAMPLES_SERLOOP),y) +CONFIGURED_APPS += examples/serloop +endif + +ifeq ($(CONFIG_EXAMPLES_TELNETD),y) +CONFIGURED_APPS += examples/telnetd +endif + +ifeq ($(CONFIG_EXAMPLES_THTTPD),y) +CONFIGURED_APPS += examples/thttpd +endif + +ifeq ($(CONFIG_EXAMPLES_TIFF),y) +CONFIGURED_APPS += examples/tiff +endif + +ifeq ($(CONFIG_EXAMPLES_TOUCHSCREEN),y) +CONFIGURED_APPS += examples/touchscreen +endif + +ifeq ($(CONFIG_EXAMPLES_UDP),y) +CONFIGURED_APPS += examples/udp +endif + +ifeq ($(CONFIG_EXAMPLES_UIP),y) +CONFIGURED_APPS += examples/uip +endif + +ifeq ($(CONFIG_EXAMPLES_USBSERIAL),y) +CONFIGURED_APPS += examples/usbserial +endif + +ifeq ($(CONFIG_EXAMPLES_USBMSC),y) +CONFIGURED_APPS += examples/usbmsc +endif + +ifeq ($(CONFIG_EXAMPLES_USBTERM),y) +CONFIGURED_APPS += examples/usbterm +endif + +ifeq ($(CONFIG_EXAMPLES_WGET),y) +CONFIGURED_APPS += examples/wget +endif + +ifeq ($(CONFIG_EXAMPLES_WLAN),y) +CONFIGURED_APPS += examples/wlan +endif diff --git a/apps/examples/Makefile b/apps/examples/Makefile new file mode 100644 index 000000000..ad5be6497 --- /dev/null +++ b/apps/examples/Makefile @@ -0,0 +1,129 @@ +############################################################################ +# apps/examples/Makefile +# +# 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 +# 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 # Current configuration + +# Sub-directories + +SUBDIRS = adc buttons can cdcacm composite dhcpd ftpc ftpd hello helloxx \ + hidkbd igmp lcdrw mm modbus mount nettest nsh null nx nxconsole nxffs \ + nxflat nxhello nximage nxlines nxtext ostest pashello pipe poll pwm \ + qencoder rgmp romfs serloop telnetd thttpd tiff touchscreen udp uip \ + usbserial sendmail usbstorage usbterm watchdog 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 +# the example may be built as an NSH built-in function. +# +# Directories that may be built as NSH built-in functions may have their +# own configuration setting (like CONFIG_EXAMPLES_HELLOXX_BUILTIN), but +# many only depend on the generic CONFIG_NSH_BUILTIN_APPS setting. And +# there a few which an ONLY be built as NSH built-in applications; these +# are included in the list unconditionally. + +CNTXTDIRS = pwm + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +CNTXTDIRS += adc can cdcacm composite ftpd dhcpd modbus nettest qencoder telnetd watchdog +endif + +ifeq ($(CONFIG_EXAMPLES_HELLO_BUILTIN),y) +CNTXTDIRS += hello +endif +ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y) +CNTXTDIRS += helloxx +endif +ifeq ($(CONFIG_EXAMPLES_LCDRW_BUILTIN),y) +CNTXTDIRS += lcdrw +endif +ifeq ($(CONFIG_EXAMPLES_NX_BUILTIN),y) +CNTXTDIRS += nx +endif +ifeq ($(CONFIG_EXAMPLES_NXHELLO_BUILTIN),y) +CNTXTDIRS += nxhello +endif +ifeq ($(CONFIG_EXAMPLES_NXIMAGE_BUILTIN),y) +CNTXTDIRS += nximage +endif +ifeq ($(CONFIG_EXAMPLES_LINES_BUILTIN),y) +CNTXTDIRS += nxlines +endif +ifeq ($(CONFIG_EXAMPLES_NXTEXT_BUILTIN),y) +CNTXTDIRS += nxtext +endif +ifeq ($(CONFIG_EXAMPLES_OSTEST_BUILTIN),y) +CNTXTDIRS += ostest +endif +ifeq ($(CONFIG_EXAMPLES_TIFF_BUILTIN),y) +CNTXTDIRS += tiff +endif +ifeq ($(CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN),y) +CNTXTDIRS += touchscreen +endif +ifeq ($(CONFIG_EXAMPLES_USBMSC_BUILTIN),y) +CNTXTDIRS += usbstorage +endif +ifeq ($(CONFIG_EXAMPLES_USBTERM_BUILTIN),y) +CNTXTDIRS += usbterm +endif + +all: nothing + +.PHONY: nothing context depend clean distclean + +nothing: + +context: + @for dir in $(CNTXTDIRS) ; do \ + $(MAKE) -C $$dir context TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +depend: + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir depend TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +clean: + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +distclean: clean + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \ + done + +-include Make.dep + diff --git a/apps/examples/README.txt b/apps/examples/README.txt new file mode 100644 index 000000000..7d068f979 --- /dev/null +++ b/apps/examples/README.txt @@ -0,0 +1,1649 @@ +examples +^^^^^^^^ + + appconfig and CONFIG_APPS + + The examples directory contains several sample applications that + can be linked with NuttX. The specific example is selected in the + configs/<board-name>/appconfig file via the CONFIGURED_APPS setting. + This setting provides the path to the directory containing the + application Makefile (this path is a relative to the apps/ top- + level directory). For example, + + CONFIGURE_APPS += examples/ostest + + Selects the examples/ostest example. + + Built-In functions + + Some of the examples may be built as "built-in" functions that + can be executed at run time (rather than as NuttX "main" programs). + These "built-in" examples can be also be executed from the NuttShell + (NSH) command line. In order to configure these built-in NSH + functions, you have to set up the following: + + - CONFIG_NSH_BUILTIN_APPS - Enable support for external registered, + "named" applications that can be executed from the NSH + command line (see apps/README.txt for more information). + - CONFIG_EXAMPLES_XYZ_BUILTIN -- Build the XYZ example as a "built-in" + that can be executed from the NSH command line (where XYZ is + the specific example. See the following for examples that + support this option). + +examples/adc +^^^^^^^^^^^^ + + A mindlessly simple test of an ADC devices. It simply reads from the + ADC device and dumps the data to the console forever. + + This test depends on these specific ADC/NSH configurations settings (your + specific ADC settings might require additional settings). + + CONFIG_ADC - Enabled ADC support + CONFIG_NSH_BUILTIN_APPS - Build the ADC test as an NSH built-in function. + Default: Built as a standalone problem + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_ADC_DEVPATH - The default path to the ADC device. Default: /dev/adc0 + CONFIG_EXAMPLES_ADC_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. + CONFIG_EXAMPLES_ADC_GROUPSIZE - The number of samples to read at once. + Default: 4 + +examples/buttons +^^^^^^^^^^^^^^^^ + + This is a simple configuration that may be used to test the board- + specific button interfaces. Configuration options: + + CONFIG_ARCH_BUTTONS - Must be defined for button support + CONFIG_EXAMPLE_BUTTONS_MIN - Lowest button number (MIN=0) + CONFIG_EXAMPLE_BUTTONS_MAX - Highest button number (MAX=7) + + CONFIG_ARCH_IRQBUTTONS - Must be defined for interrupting button support + CONFIG_EXAMPLE_IRQBUTTONS_MIN - Lowest interrupting button number (MIN=0) + CONFIG_EXAMPLE_IRQBUTTONS_MAX - Highest interrupting button number (MAX=7) + + Name strings for buttons: + + CONFIG_EXAMPLE_BUTTONS_NAME0, CONFIG_EXAMPLE_BUTTONS_NAME1, + CONFIG_EXAMPLE_BUTTONS_NAME2, CONFIG_EXAMPLE_BUTTONS_NAME3, + CONFIG_EXAMPLE_BUTTONS_NAME4, CONFIG_EXAMPLE_BUTTONS_NAME5, + CONFIG_EXAMPLE_BUTTONS_NAME6, CONFIG_EXAMPLE_BUTTONS_NAME7, + + Additional architecture-/board- specific configuration settings may also + be required. + + NOTE: This test exercises internal button driver interfaces. As such, it + relies on internal OS interfaces that are not normally available to a + user-space program. As a result, this example cannot be used if a + NuttX is built as a protected, supervisor kernel (CONFIG_NUTTX_KERNEL). + +examples/can +^^^^^^^^^^^^ + + If the CAN device is configured in loopback mode, then this example can + be used to test the CAN device in loop back mode. It simple sinces a + sequence of CAN messages and verifies that those messages are returned + exactly as sent. + + This test depends on these specific CAN/NSH configurations settings (your + specific CAN settings might require additional settings). + + CONFIG_CAN - Enables CAN support. + CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + mode for testing. The STM32 CAN driver does support loopback mode. + CONFIG_NSH_BUILTIN_APPS - Build the CAN test as an NSH built-in function. + Default: Built as a standalone problem + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_CAN_DEVPATH - The path to the CAN device. Default: /dev/can0 + CONFIG_EXAMPLES_CAN_NMSGS - If CONFIG_NSH_BUILTIN_APPS + is defined, then the number of loops is provided on the command line + and this value is ignored. Otherwise, this number of CAN message is + collected and the program terminates. Default: If built as an NSH + built-in, the default is 32. Otherwise messages are sent and received + indefinitely. + + The default behavior assumes loopback mode. Messages are sent, then read + and verified. The behavior can be altered for other kinds of testing where + the test only sends or received (but does not verify) can messages. + + CONFIG_EXAMPLES_CAN_READONLY - Only receive messages + CONFIG_EXAMPLES_CAN_WRITEONLY - Only send messages + +examples/cdcacm +^^^^^^^^^^^^^^^ + + This very simple example shows how a USB CDC/ACM serial can be dynamically + connected and disconnected from a host. This example can only be used as + an NSH built-int command. If built-in, then two new NSH commands will be + supported: + + 1. sercon - Connect the CDC/ACM serial device + 2. serdis - Disconnect the CDC/ACM serial device + + Configuration prequisites (not complete): + + CONFIG_USBDEV=y : USB device support must be enabled + CONFIG_CDCACM=y : The CDC/ACM driver must be built + CONFIG_NSH_BUILTIN_APPS : NSH built-in application support must be enabled + + Configuration options specific to this example: + + CONFIG_EXAMPLES_CDCACM_DEVMINOR : The minor number of the CDC/ACM device. + : i.e., the 'x' in /dev/ttyACMx + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB, or + CONFIG_USBDEV_TRACE), then the example code will also initialize the USB trace + output. The amount of trace output can be controlled using: + + CONFIG_EXAMPLES_CDCACM_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_CDCACM_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_CDCACM_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_CDCACM_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_CDCACM_TRACEINTERRUPTS + Show interrupt-related events. + + Note: This example is only enables or disable USB CDC/ACM via the NSH + 'sercon' and 'serdis' command. It will enable and disable tracing per + the settings before enabling and after disabling the CDC/ACM device. It + will not, however, monitor buffered trace data in the interim. If + CONFIG_USBDEV_TRACE is defined (and the debug options are not), other + application logic will need to monitor the buffered trace data. + +examples/composite +^^^^^^^^^^^^^^^^^^ + + This example test a USB composite device. The only supported composite is + CDC/ACM serial with a USB mass storage device. + + Required overall configuration: + + CONFIG_USBDEV=y - USB device support + CONFIG_USBDEV_COMPOSITE=y - USB composite device support + CONFIG_COMPOSITE_IAD=y - Interface associate descriptor needed + + CONFIG_CDCACM=y - USB CDC/ACM serial device support + CONFIG_CDCACM_COMPOSITE=y - USB CDC/ACM serial composite device support + CONFIG_CDCACM_IFNOBASE=0 - CDC/ACM interfaces start with number 0 + CONFIG_CDCACM_STRBASE=4 - Base of string numbers (not really needed) + CONFIG_CDCACM_EPINTIN=1 - Endpoint numbers must be unique + CONFIG_CDCACM_EPBULKIN=2 + CONFIG_CDCACM_EPBULKOUT=3 + + CONFIG_USBMSC - USB mass storage device support + CONFIG_USBMSC_COMPOSITE=y - USB mass storage composite device support + CONFIG_USBMSC_IFNOBASE=2 - USB mass storage interfaces start with number 2 + CONFIG_USBMSC_STRBASE=4 - Base of string numbers (needed) + CONFIG_USBMSC_EPBULKOUT=4 - Endpoint numbers must be unique + CONFIG_USBMSC_EPBULKIN=5 + + CONFIG_NSH_BUILTIN_APPS + This example can be built as two NSH "built-in" commands if this option + is selected: 'conn' will connect the USB composite device; 'msdis' + will disconnect the USB composite device. + + Configuration options unique to this example: + + CONFIG_EXAMPLES_COMPOSITE_DEBUGMM + Enables some debug tests to check for memory usage and memory leaks. + + CONFIG_EXAMPLES_COMPOSITE_NLUNS + Defines the number of logical units (LUNs) exported by the USB storage + driver. Each LUN corresponds to one exported block driver (or partition + of a block driver). May be 1, 2, or 3. Default is 1. + CONFIG_EXAMPLES_COMPOSITE_DEVMINOR1 + The minor device number of the block driver for the first LUN. For + example, N in /dev/mmcsdN. Used for registering the block driver. Default + is zero. + CONFIG_EXAMPLES_COMPOSITE_DEVPATH1 + The full path to the registered block driver. Default is "/dev/mmcsd0" + CONFIG_EXAMPLES_COMPOSITE_DEVMINOR2 and CONFIG_EXAMPLES_COMPOSITE_DEVPATH2 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_COMPOSITE_NLUNS + is 2 or 3. No defaults. + CONFIG_EXAMPLES_COMPOSITE_DEVMINOR3 and CONFIG_EXAMPLES_COMPOSITE_DEVPATH2 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_COMPOSITE_NLUNS + is 3. No defaults. + CONFIG_EXAMPLES_COMPOSITE_BUFLEN. Default 256. + + CONFIG_EXAMPLES_COMPOSITE_TTYUSB - The minor number of the USB serial device. + Default is zero (corresponding to /dev/ttyUSB0 or /dev/ttyACM0). Default is zero. + CCONFIG_EXAMPLES_COMPOSITE_SERDEV - The string corresponding to + CONFIG_EXAMPLES_COMPOSITE_TTYUSB. The default is "/dev/ttyUSB0" (for the PL2303 + emulation) or "/dev/ttyACM0" (for the CDC/ACM serial device). + CONFIG_EXAMPLES_COMPOSITE_BUFSIZE - The size of the serial I/O buffer in + bytes. Default 256 bytes. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB), then + the example code will also manage the USB trace output. The amount of trace output + can be controlled using: + + CONFIG_EXAMPLES_COMPOSITE_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_COMPOSITE_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_COMPOSITE_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_COMPOSITE_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_COMPOSITE_TRACEINTERRUPTS + Show interrupt-related events. + +examples/dhcpd +^^^^^^^^^^^^^^ + + This examples builds a tiny DCHP server for the target system. + + NOTE: For test purposes, this example can be built as a + host-based DHCPD server. This can be built as follows: + + cd examples/dhcpd + make -f Makefile.host TOPDIR=<nuttx-directory> + + NuttX configuration settings: + + CONFIG_NET=y - Of course + CONFIG_NSOCKET_DESCRIPTORS - And, of course, you must allocate some + socket descriptors. + CONFIG_NET_UDP=y - UDP support is required for DHCP + (as well as various other UDP-related + configuration settings) + CONFIG_NET_BROADCAST=y - UDP broadcast support is needed. + + CONFIG_EXAMPLE_DHCPD_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_DHCPD_IPADDR - Target IP address + CONFIG_EXAMPLE_DHCPD_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_DHCPD_NETMASK - Network mask + + See also CONFIG_NETUTILS_DHCPD_* settings described elsewhere + and used in netutils/dhcpd/dhcpd.c. These settings are required + to described the behavior of the daemon. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/ftpc +^^^^^^^^^^^^^ + + This is a simple FTP client shell used to exercise the capabilities + of the FTPC library (apps/netutils/ftpc). This example is configured + to that it will only work as a "built-in" program that can be run from + NSH when CONFIG_NSH_BUILTIN_APPS is defined. + + From NSH, the startup command sequence is as follows. This is only + an example, your configration could have different mass storage devices, + mount paths, and FTP directories: + + nsh> mount -t vfat /dev/mmcsd0 /tmp # Mount the SD card at /tmp + nsh> cd /tmp # cd into the /tmp directory + nsh> ftpc xx.xx.xx.xx[:pp] # Start the FTP client + nfc> login <name> <password> # Log into the FTP server + nfc> help # See a list of FTP commands + + where xx.xx.xx.xx is the IP address of the FTP server and pp is an + optional port number. + + NOTE: By default, FTPC uses readline to get data from stdin. So your + appconfig file must have the following build path: + + CONFIGURED_APPS += system/readline + + NOTE: If you use the ftpc task over a telnet NSH connection, then you + should set the following configuration item: + + CONFIG_EXAMPLES_FTPC_FGETS=y + + By default, the FTPC client will use readline() to get characters from + the console. Readline includes and command-line editor and echos + characters received in stdin back through stdout. Neither of these + behaviors are desire-able if Telnet is used. + + You may also want to define the following in your configuration file. + Otherwise, you will have not feeback about what is going on: + + CONFIG_DEBUG=y + CONFIG_DEBUG_VERBOSE=y + CONFIG_DEBUG_FTPC=y + +examples/ftpd +^^^^^^^^^^^^^^ + + This example exercises the FTPD daemon at apps/netuils/ftpd. Below are + configurations specific to the FTPD example (the FTPD daemon itself may + require other configuration options as well). + + CONFIG_EXAMPLES_FTPD_PRIO - Priority of the FTP daemon. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_FTPD_STACKSIZE - Stack size allocated for the + FTP daemon. Default: 2048 + CONFIG_EXAMPLES_FTPD_NONETINIT - Define to suppress configuration of the + network by apps/examples/ftpd. You would need to suppress network + configuration if the network is configuration prior to running the + example. + + NSH always initializes the network so if CONFIG_NSH_BUILTIN_APPS is + defined, so is CONFIG_EXAMPLES_FTPD_NONETINIT (se it does not explicitly + need to be defined in that case): + + CONFIG_NSH_BUILTIN_APPS - Build the FTPD daemon example test as an + NSH built-in function. By default the FTPD daemon will be built + as a standalone application. + + If CONFIG_EXAMPLES_FTPD_NONETINIT is not defined, then the following may + be specified to customized the network configuration: + + CONFIG_EXAMPLE_FTPD_NOMAC - If the hardware has no MAC address of its + own, define this =y to provide a bogus address for testing. + CONFIG_EXAMPLE_FTPD_IPADDR - The target IP address. Default 10.0.0.2 + CONFIG_EXAMPLE_FTPD_DRIPADDR - The default router address. Default + 10.0.0.1 + CONFIG_EXAMPLE_FTPD_NETMASK - The network mask. Default: 255.255.255.0 + + Other required configuration settings: Of course TCP networking support + is required. But here are a couple that are less obvious: + + CONFIG_DISABLE_PTHREAD - pthread support is required + CONFIG_DISABLE_POLL - poll() support is required + + Other FTPD configuration options thay may be of interest: + + CONFIG_FTPD_VENDORID - The vendor name to use in FTP communications. + Default: "NuttX" + CONFIG_FTPD_SERVERID - The server name to use in FTP communications. + Default: "NuttX FTP Server" + CONFIG_FTPD_CMDBUFFERSIZE - The maximum size of one command. Default: + 512 bytes. + CONFIG_FTPD_DATABUFFERSIZE - The size of the I/O buffer for data + transfers. Default: 2048 bytes. + CONFIG_FTPD_WORKERSTACKSIZE - The stacksize to allocate for each + FTP daemon worker thread. Default: 2048 bytes. + + The appconfig file (apps/.config) should include: + + CONFIGURED_APPS += examples/ftpd + CONFIGURED_APPS += netutils/uiplib + CONFIGURED_APPS += netutils/ftpd + +examples/hello +^^^^^^^^^^^^^^ + + This is the mandatory, "Hello, World!!" example. It is little more + than examples/null with a single printf statement. Really useful only + for bringing up new NuttX architectures. + + * CONFIG_EXAMPLES_HELLO_BUILTIN + Build the "Hello, World" example as an NSH built-in application. + +examples/helloxx +^^^^^^^^^^^^^^^^ + + This is C++ version of the "Hello, World!!" example. It is intended + only to verify that the C++ compiler is functional, that basic C++ + library suupport is available, and that class are instantiated + correctly. + + NuttX configuration prerequisites: + + CONFIG_HAVE_CXX -- Enable C++ Support + + Optional NuttX configuration settings: + + CONFIG_HAVE_CXXINITIALIZE -- Enable support for static constructors + (may not be available on all platforms). + + NuttX configuration settings specific to this examp;le: + + CONFIG_EXAMPLES_HELLOXX_BUILTIN -- Build the helloxx example as a + "built-in" that can be executed from the NSH command line. + CONFIG_EXAMPLES_HELLOXX_NOSTACKCONST - Set if the system does not + support construction of objects on the stack. + + Also needed: + + CONFIG_HAVE_CXX=y + + And you may have to tinker with the following to get libxx to compile + properly: + + CONFIG_CXX_NEWLONG=y or =n + + The argument of the 'new' operators should take a type of size_t. But size_t + has an unknown underlying. In the nuttx sys/types.h header file, size_t + is typed as uint32_t (which is determined by architecture-specific logic). + But the C++ compiler may believe that size_t is of a different type resulting + in compilation errors in the operator. Using the underlying integer type + Instead of size_t seems to resolve the compilation issues. + +examples/hidkbd +^^^^^^^^^^^^^^^^ + + This is a simple test to debug/verify the USB host HID keyboard class + driver. + + CONFIG_EXAMPLES_HIDKBD_DEFPRIO - Priority of "waiter" thread. + CONFIG_EXAMPLES_HIDKBD_STACKSIZE - Stacksize of "waiter" thread. + +examples/igmp +^^^^^^^^^^^^^ + + This is a trivial test of the NuttX IGMP capability. It present it + does not do much of value -- Much more is needed in order to verify + the IGMP features! + + * CONFIG_EXAMPLE_IGMP_NOMAC + Set if the hardware has no MAC address; one will be assigned + * CONFIG_EXAMPLE_IGMP_IPADDR + Target board IP address + * CONFIG_EXAMPLE_IGMP_DRIPADDR + Default router address + * CONFIG_EXAMPLE_IGMP_NETMASK + Network mask + * CONFIG_EXAMPLE_IGMP_GRPADDR + Multicast group address + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/lcdrw +^^^^^^^^^^^^^^ + + This example may be used to verify if you can or cannot read data + correctly from an LCD interface. At present, this supports only LCDs + with RGB565 color format. + + * CONFIG_EXAMPLES_LDCRW_DEVNO + LCD device number. Default: 0 + * CONFIG_EXAMPLES_LDCRW_XRES + LCD X resolution. Default: 240 + * CONFIG_EXAMPLES_LDCRW_YRES + LCD Y resolution. Default: 320 + +examples/mm +^^^^^^^^^^^ + + This is a simplified version of the "built-in" memory manager test of + mm/mm_test.c. It is simplified because it does not have access to the + internals of the memory manager as does mm/mm_test.c, but it has the + advantage that it runs in the actual NuttX tasking environment (the + mm/mm_test.c only runs in a PC simulation environment). + +examples/modbus +^^^^^^^^^^^^^^^ + + This is a port of the FreeModbus Linux demo. It derives from the + demos/LINUX directory of the FreeModBus version 1.5.0 (June 6, 2010) + that can be downloaded in its entirety from http://developer.berlios.de/project/showfiles.php?group_id=6120. + + CONFIG_EXAMPLES_MODBUS_PORT, Default 0 (for /dev/ttyS0) + CONFIG_EXAMPLES_MODBUS_BAUD, Default B38400 + CONFIG_EXAMPLES_MODBUS_PARITY, Default MB_PAR_EVEN + + CONFIG_EXAMPLES_MODBUS_REG_INPUT_START, Default 1000 + CONFIG_EXAMPLES_MODBUS_REG_INPUT_NREGS, Default 4 + CONFIG_EXAMPLES_MODBUS_REG_HOLDING_START, Default 2000 + CONFIG_EXAMPLES_MODBUS_REG_HOLDING_NREGS, Default 130 + + The FreeModBus library resides at apps/modbus. See apps/modbus/README.txt + for additional configuration information. + +examples/mount +^^^^^^^^^^^^^^ + + This contains a simple test of filesystem mountpoints. + + * CONFIG_EXAMPLES_MOUNT_DEVNAME + The name of the user-provided block device to mount. + If CONFIG_EXAMPLES_MOUNT_DEVNAME is not provided, then + a RAM disk will be configured. + + * CONFIG_EXAMPLES_MOUNT_NSECTORS + The number of "sectors" in the RAM disk used when + CONFIG_EXAMPLES_MOUNT_DEVNAME is not defined. + + * CONFIG_EXAMPLES_MOUNT_SECTORSIZE + The size of each sectors in the RAM disk used when + CONFIG_EXAMPLES_MOUNT_DEVNAME is not defined. + + * CONFIG_EXAMPLES_MOUNT_RAMDEVNO + The RAM device minor number used to mount the RAM disk used + when CONFIG_EXAMPLES_MOUNT_DEVNAME is not defined. The + default is zero (meaning that "/dev/ram0" will be used). + +examples/netttest +^^^^^^^^^^^^^^^^^ + + This is a simple network test for verifying client- and server- + functionality in a TCP/IP connection. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/nsh +^^^^^^^^^^^^ + + This directory provides an example of how to configure and use + the NuttShell (NSH) application. NSH is a simple shell + application. NSH is described in its own README located at + apps/nshlib/README.txt + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += nshlib + + NOTE: If the NSH serial console is used, then following is also + required to build the readline() library: + + CONFIGURED_APPS += system/readline + + And if networking is included: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += dhcpc + CONFIGURED_APPS += resolv + CONFIGURED_APPS += tftp + CONFIGURED_APPS += webclient + + If the Telnet console is enabled, then the appconfig file (apps/.config) + should also include: + + CONFIGURED_APPS += netutils/telnetd + + Also if the Telnet console is enabled, make sure that you have the + following set in the NuttX configuration file or else the performance + will be very bad (because there will be only one character per TCP + transfer): + + CONFIG_STDIO_BUFFER_SIZE - Some value >= 64 + CONFIG_STDIO_LINEBUFFER=y + +examples/nx +^^^^^^^^^^^ + + This directory contains a simple test of a subset of the NX APIs + defined in include/nuttx/nx/nx.h. The following configuration options + can be selected: + + CONFIG_EXAMPLES_NX_BUILTIN -- Build the NX example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NX_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NX_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NX_BGCOLOR -- The color of the background. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_COLOR1 -- The color of window 1. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_COLOR2 -- The color of window 2. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_TBCOLOR -- The color of the toolbar. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_FONTID - Selects the font (see font ID numbers in + include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NX_FONTCOLOR -- The color of the fonts. Default depends on + CONFIG_EXAMPLES_NX_BPP. + CONFIG_EXAMPLES_NX_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NX_RAWWINDOWS -- Use raw windows; Default is to + use pretty, framed NXTK windows with toolbars. + CONFIG_EXAMPLES_NX_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + This test can be performed with either the single-user version of + NX or with the multiple user version of NX selected with CONFIG_NX_MULTIUSER. + If CONFIG_NX_MULTIUSER is defined, then the following configuration + options also apply: + + CONFIG_EXAMPLES_NX_STACKSIZE -- The stacksize to use when creating + the NX server. Default 2048 + CONFIG_EXAMPLES_NX_CLIENTPRIO -- The client priority. Default: 100 + CONFIG_EXAMPLES_NX_SERVERPRIO -- The server priority. Default: 120 + CONFIG_EXAMPLES_NX_LISTENERPRIO -- The priority of the event listener + thread. Default 80. + CONFIG_EXAMPLES_NX_NOTIFYSIGNO -- The signal number to use with + nx_eventnotify(). Default: 4 + + If CONFIG_NX_MULTIUSER is defined, then the example also expects the + following settings and will generate an error if they are not as expected: + + CONFIG_DISABLE_MQUEUE=n + CONFIG_DISABLE_SIGNALS=n + CONFIG_DISABLE_PTHREAD=n + CONFIG_NX_BLOCKING=y + +examples/nxconsole +^^^^^^^^^^^^^^^^^^ + + This directory contains yet another version of the NuttShell (NSH). This + version uses the NX console device defined in include/nuttx/nx/nxconsole.h + for output. the result is that the NSH input still come from the standard + console input (probably a serial console). But the text output will go to + an NX winbdow. Prerequisite configuration settings for this test include: + + CONFIG_NX=y -- NX graphics must be enabled + CONFIG_NXCONSOLE=y -- The NX console driver must be built + CONFIG_NX_MULTIUSER=y -- NX multi-user support must be enabled. + CONFIG_DISABLE_MQUEUE=n -- Message queue support must be available. + CONFIG_DISABLE_SIGNALS=n -- Signals are needed + CONFIG_DISABLE_PTHREAD=n -- pthreads are needed + CONFIG_NX_BLOCKING=y -- pthread APIs must be blocking + CONFIG_NSH_CONSOLE=y -- NSH must be configured to use a console. + + The following configuration options can be selected to customize the + test: + + CONFIG_EXAMPLES_NXCON_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXCON_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXCON_BGCOLOR -- The color of the background. Default + Default is a darker royal blue. + CONFIG_EXAMPLES_NXCON_WCOLOR -- The color of the window. Default is a light + slate blue. + CONFIG_EXAMPLES_NXCON_FONTID -- Selects the font (see font ID numbers in + include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXCON_FONTCOLOR -- The color of the fonts. Default is + black. + CONFIG_EXAMPLES_NXCON_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NXCON_TOOLBAR_HEIGHT -- The height of the toolbar. + Default: 16 + CONFIG_EXAMPLES_NXCON_TBCOLOR -- The color of the toolbar. Default is + a medium grey. + CONFIG_EXAMPLES_NXCON_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + CONFIG_EXAMPLES_NXCON_MINOR -- The NX console device minor number. + Default is 0 corresponding to /dev/nxcon0 + CONFIG_EXAMPLES_NXCON_DEVNAME -- The quoated, full path to the + NX console device corresponding to CONFIG_EXAMPLES_NXCON_MINOR. + Default: "/dev/nxcon0" + CONFIG_EXAMPLES_NXCONSOLE_PRIO - Priority of the NxConsole task. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_NXCONSOLE_STACKSIZE - Stack size allocated for the + NxConsole task. Default: 2048 + + The following configuration settings determine how to set up the NX + server (CONFIG_NX_MULTIUSER): + + CONFIG_EXAMPLES_NXCON_STACKSIZE -- The stacksize to use when creating + the NX server. Default 2048 + CONFIG_EXAMPLES_NXCON_CLIENTPRIO -- The client priority. Default: 100 + CONFIG_EXAMPLES_NXCON_SERVERPRIO -- The server priority. Default: 120 + CONFIG_EXAMPLES_NXCON_LISTENERPRIO -- The priority of the event listener + thread. Default 80. + CONFIG_EXAMPLES_NXCON_NOTIFYSIGNO -- The signal number to use with + nx_eventnotify(). Default: 4 + +examples/nxffs +^^^^^^^^^^^^^^ + + This is a test of the NuttX NXFFS FLASH file system. This is an NXFFS + stress test and beats on the file system very hard. It should only + be used in a simulation environment! Putting this NXFFS test on real + hardware will most likely destroy your FLASH. You have been warned. + +examples/nxflat +^^^^^^^^^^^^^^^ + + This example builds a small NXFLAT test case. This includes several + test programs under examples/nxflat tests. These tests are build using + the NXFLAT format and installed in a ROMFS file system. At run time, + each program in the ROMFS file system is executed. Requires CONFIG_NXFLAT. + +examplex/nxhello +^^^^^^^^^^^^^^^^ + + A very simple graphics example that just says "Hello, World!" in the + center of the display. + + The following configuration options can be selected: + + CONFIG_EXAMPLES_NXHELLO_BUILTIN -- Build the NXHELLO example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXHELLO_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXHELLO_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXHELLO_BGCOLOR -- The color of the background. Default + depends on CONFIG_EXAMPLES_NXHELLO_BPP. + CONFIG_EXAMPLES_NXHELLO_FONTID - Selects the font (see font ID numbers in + include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXHELLO_FONTCOLOR -- The color of the fonts used in the + background window. Default depends on CONFIG_EXAMPLES_NXHELLO_BPP. + CONFIG_EXAMPLES_NXHELLO_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NXHELLO_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + +examples/nximage +^^^^^^^^^^^^^^^^ + + This is a simple example that just puts the NuttX logo image in the center + of the display. This only works for RGB23 (888), RGB16 (656), RGB8 (332), + and 8-bit greyscale for now. + + CONFIG_EXAMPLES_NXIMAGE_BUILTIN -- Build the NXIMAGE example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXIMAGE_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXIMAGE_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXIMAGE_BPP -- Pixels per pixel to use. Valid options + include 8, 16, and 24. Default is 16. + CONFIG_EXAMPLES_NXIMAGE_XSCALEp5, CONFIG_EXAMPLES_NXIMAGE_XSCALE1p5, + CONFIG_EXAMPLES_NXIMAGE_XSCALE2p0 -- The logo image width is 160 columns. + One of these may be defined to rescale the image horizontally by .5, 1.5, + or 2.0. + CONFIG_EXAMPLES_NXIMAGE_YSCALEp5, CONFIG_EXAMPLES_NXIMAGE_YSCALE1p5, + CONFIG_EXAMPLES_NXIMAGE_YSCALE2p0 -- The logo image height is 160 rows. + One of these may be defined to rescale the image vertically by .5, 1.5, + or 2.0. + CONFIG_EXAMPLES_NXIMAGE_GREYSCALE -- Grey scale image. Default: RGB. + CONFIG_EXAMPLES_NXIMAGE_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + How was that run-length encoded image produced? + + a. I used GIMP output the image as a .c file. + b. I added som C logic to palette-ize the RGB image in the GIMP .c file + c. Then I add some simple run-length encoding to palette-ized image. + + NOTE: As of this writing, most of the pixel depth, scaling options, and + combinations thereof have not been tested. + +examplex/nxlines +^^^^^^^^^^^^^^^^ + + A very simple graphics example that just exercised the NX line drawing + logic. + + The following configuration options can be selected: + + CONFIG_EXAMPLES_NXLINES_BUILTIN -- Build the NXLINES example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXLINES_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXLINES_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXLINES_BGCOLOR -- The color of the background. Default + depends on CONFIG_EXAMPLES_NXLINES_BPP. + CONFIG_EXAMPLES_NXLINES_LINEWIDTH - Selects the width of the lines in + pixels (default: 16) + CONFIG_EXAMPLES_NXLINES_LINECOLOR -- The color of the central lines drawn + in the background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP + (there really is no meaningful default). + CONFIG_EXAMPLES_NXLINES_BORDERWIDTH -- The width of the circular border + drawn in the background window. (default: 16). + CONFIG_EXAMPLES_NXLINES_BORDERCOLOR -- The color of the circular border + drawn in the background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP + (there really is no meaningful default). + CONFIG_EXAMPLES_NXLINES_CIRCLECOLOR -- The color of the circular region + filled in the background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP + (there really is no meaningful default). + CONFIG_EXAMPLES_NXLINES_BORDERCOLOR -- The color of the lines drawn in the + background window. Default depends on CONFIG_EXAMPLES_NXLINES_BPP (there + really is no meaningful default). + + CONFIG_EXAMPLES_NXLINES_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 16. + CONFIG_EXAMPLES_NXLINES_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + +examples/nxtext +^^^^^^^^^^^^^^^ + + This directory contains another simple test of a subset of the NX APIs + defined in include/nuttx/nx/nx.h. This text focuses on text displays on + the dispaly background combined with pop-up displays over the text. + The text display will continue to update while the pop-up is visible. + + NOTE: This example will *only* work with FB drivers and with LCD + drivers that support reading the contents of the internal LCD memory + *unless* you define CONFIG_EXAMPLES_NXTEXT_NOGETRUN. If you notice + garbage on the display or a failure at the point where the display + should scroll, it is probably because you have an LCD driver that is + write-only. + + The following configuration options can be selected: + + CONFIG_EXAMPLES_NXTEXT_BUILTIN -- Build the NXTEXT example as a "built-in" + that can be executed from the NSH command line + CONFIG_EXAMPLES_NXTEXT_VPLANE -- The plane to select from the frame- + buffer driver for use in the test. Default: 0 + CONFIG_EXAMPLES_NXTEXT_DEVNO - The LCD device to select from the LCD + driver for use in the test: Default: 0 + CONFIG_EXAMPLES_NXTEXT_BGCOLOR -- The color of the background. Default + depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_BGFONTID - Selects the font to use in the + background text (see font ID numbers in include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXTEXT_BGFONTCOLOR -- The color of the fonts used in the + background window. Default depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_PUCOLOR -- The color of the pop-up window. Default + depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_PUFONTID - Selects the font to use in the pop-up + windows (see font ID numbers in include/nuttx/nx/nxfonts.h) + CONFIG_EXAMPLES_NXTEXT_PUFONTCOLOR -- The color of the fonts used in the + background window. Default depends on CONFIG_EXAMPLES_NXTEXT_BPP. + CONFIG_EXAMPLES_NXTEXT_BPP -- Pixels per pixel to use. Valid options + include 2, 4, 8, 16, 24, and 32. Default is 32. + CONFIG_EXAMPLES_NXTEXT_NOGETRUN -- If your display is read-only OR if + reading is not reliable, then select this configuration to avoid + reading from the display. + CONFIG_EXAMPLES_NXTEXT_EXTERNINIT - The driver for the graphics device on + this platform requires some unusual initialization. This is the + for, for example, SPI LCD/OLED devices. If this configuration is + selected, then the platform code must provide an LCD initialization + function with a prototype like: + + #ifdef CONFIG_NX_LCDDRIVER + FAR struct lcd_dev_s *up_nxdrvinit(unsigned int devno); + #else + FAR struct fb_vtable_s *up_nxdrvinit(unsigned int devno); + #endif + + CONFIG_EXAMPLES_NXTEXT_BMCACHE - The maximum number of characters that + can be put in the background window. Default is 128. + CONFIG_EXAMPLES_NXTEXT_GLCACHE - The maximum nuber of pre-rendered + fonts that can be retained for the background window. + + This test can be performed with either the single-user version of + NX or with the multiple user version of NX selected with CONFIG_NX_MULTIUSER. + If CONFIG_NX_MULTIUSER is defined, then the following configuration + options also apply: + + CONFIG_EXAMPLES_NXTEXT_STACKSIZE -- The stacksize to use when creating + the NX server. Default 2048 + CONFIG_EXAMPLES_NXTEXT_CLIENTPRIO -- The client priority. Default: 100 + CONFIG_EXAMPLES_NXTEXT_SERVERPRIO -- The server priority. Default: 120 + CONFIG_EXAMPLES_NXTEXT_LISTENERPRIO -- The priority of the event listener + thread. Default 80. + CONFIG_EXAMPLES_NXTEXT_NOTIFYSIGNO -- The signal number to use with + nx_eventnotify(). Default: 4 + + If CONFIG_NX_MULTIUSER is defined, then the example also expects the + following settings and will generate an error if they are not as expected: + + CONFIG_DISABLE_MQUEUE=n + CONFIG_DISABLE_SIGNALS=n + CONFIG_DISABLE_PTHREAD=n + CONFIG_NX_BLOCKING=y + +examples/null +^^^^^^^^^^^^^ + + This is the do nothing application. It is only used for bringing + up new NuttX architectures in the most minimal of environments. + +examples/ostest +^^^^^^^^^^^^^^^ + + This is the NuttX 'qualification' suite. It attempts to exercise + a broad set of OS functionality. Its coverage is not very extensive + as of this writing, but it is used to qualify each NuttX release. + + The behavior of the ostest can be modified with the following + settings in the configs/<board-name>/defconfig file: + + * CONFIG_EXAMPLES_OSTEST_BUILTIN + Build the OS test example as an NSH built-in application. + * CONFIG_EXAMPLES_OSTEST_LOOPS + Used to control the number of executions of the test. If + undefined, the test executes one time. If defined to be + zero, the test runs forever. + * CONFIG_EXAMPLES_OSTEST_STACKSIZE + Used to create the ostest task. Default is 8192. + * CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS + Specifies the number of threads to create in the barrier + test. The default is 8 but a smaller number may be needed on + systems without sufficient memory to start so many threads. + +examples/pashello +^^^^^^^^^^^^^^^^^ + + This is "Hello, World" implemented via the Pascal P-Code interpreter. In + order to use this example, you must first download and install the + NuttX pascal module. After unpacking the pascal module, you can find + installation instructions in pascal/nuttx/README.txt. + + The correct install location for the NuttX examples and build files is + apps/interpreters. + +examples/pipe +^^^^^^^^^^^^^ + + A test of the mkfifo() and pipe() APIs. + + * CONFIG_EXAMPLES_PIPE_STACKSIZE + Sets the size of the stack to use when creating the child tasks. + The default size is 1024. + +examples/poll +^^^^^^^^^^^^^ + + A test of the poll() and select() APIs using FIFOs and, if available, + stdin, and a TCP/IP socket. In order to build this test, you must the + following selected in your NuttX configuration file: + + CONFIG_NFILE_DESCRIPTORS - Defined to be greater than 0 + CONFIG_DISABLE_POLL - NOT defined + + In order to use the TCP/IP select test, you have also the following + additional things selected in your NuttX configuration file: + + CONFIG_NET - Defined for general network support + CONFIG_NET_TCP - Defined for TCP/IP support + CONFIG_NSOCKET_DESCRIPTORS - Defined to be greater than 0 + CONFIG_NET_NTCP_READAHEAD_BUFFERS - Defined to be greater than zero + + CONFIG_EXAMPLE_POLL_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_POLL_IPADDR - Target IP address + CONFIG_EXAMPLE_POLL_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_POLL_NETMASK - Network mask + + In order to for select to work with incoming connections, you + must also select: + + CONFIG_NET_TCPBACKLOG - Incoming connections pend in a backlog until accept() is called. + + In additional to the target device-side example, there is also + a host-side application in this directory. It can be compiled under + Linux or Cygwin as follows: + + cd examples/usbserial + make -f Makefile.host TOPDIR=<nuttx-directory> TARGETIP=<target-ip> + + Where <target-ip> is the IP address of your target board. + + This will generate a small program called 'host'. Usage: + + 1. Build the examples/poll target program with TCP/IP poll support + and start the target. + + 3. Then start the host application: + + ./host + + The host and target will exchange are variety of small messages. Each + message sent from the host should cause the select to return in target. + The target example should read the small message and send it back to + the host. The host should then receive the echo'ed message. + + If networking is enabled, applications using this example will need to + provide an appconfig file in the configuration driver with instruction + to build applications like: + + CONFIGURED_APPS += uiplib + +examples/pwm +^^^^^^^^^^^^ + + A test of a PWM device driver. It simply enables a pulsed output for + a specified frequency and duty for a specified period of time. This + example can ONLY be built as an NSH built-in function. + + This test depends on these specific PWM/NSH configurations settings (your + specific PWM settings might require additional settings). + + CONFIG_PWM - Enables PWM support. + CONFIG_EXAMPLES_PWM_COUNT - Enabled PWM pulse count support (if the + hardware supports it). + CONFIG_NSH_BUILTIN_APPS - Build the PWM test as an NSH built-in function. + Default: Not built! The example can only be used as an NSH built-in + application + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_PWM_DEVPATH - The path to the default PWM device. Default: /dev/pwm0 + CONFIG_EXAMPLES_PWM_FREQUENCY - The initial PWM frequency. Default: 100 Hz + CONFIG_EXAMPLES_PWM_DUTYPCT - The initial PWM duty as a percentage. Default: 50% + CONFIG_EXAMPLES_PWM_DURATION - The initial PWM pulse train duration in seconds. + Used only if the current pulse count is zero (pulse count is only supported + if CONFIG_PWM_PULSECOUNT is defined). Default: 5 seconds + CONFIG_EXAMPLES_PWM_PULSECOUNT - The initial PWM pulse count. This option is + only available if CONFIG_PWM_PULSECOUNT is non-zero. 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. + CONFIG_EXAMPLES_QENCODER_DELAY - This value provides the delay (in + milliseonds) between each sample. If CONFIG_NSH_BUILTIN_APPS + is defined, then this value is the default delay if no other delay is + provided on the command line. Default: 100 milliseconds + +examples/rgmp +^^^^^^^^^^^^^ + + RGMP stands for RTOS and GPOS on Multi-Processor. RGMP is a project for + running GPOS and RTOS simultaneously on multi-processor platforms. You can + port your favorite RTOS to RGMP together with an unmodified Linux to form a + hybrid operating system. This makes your application able to use both RTOS + and GPOS features. + + See http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further + + At present, the RGMP example folder contains only an empty main.c file. + +examples/romfs +^^^^^^^^^^^^^^ + + This example exercises the romfs filesystem. Configuration options + include: + + * CONFIG_EXAMPLES_ROMFS_RAMDEVNO + The minor device number to use for the ROM disk. The default is + 1 (meaning /dev/ram1) + + * CONFIG_EXAMPLES_ROMFS_SECTORSIZE + The ROM disk sector size to use. Default is 64. + + * CONFIG_EXAMPLES_ROMFS_MOUNTPOINT + The location to mount the ROM disk. Deafault: "/usr/local/share" + +examples/sendmail +^^^^^^^^^^^^^^^^^ + + This examples exercises the uIP SMTP logic by sending a test message + to a selected recipient. This test can also be built to execute on + the Cygwin/Linux host environment: + + cd examples/sendmail + make -f Makefile.host TOPDIR=<nuttx-directory> + + Settings unique to this example include: + + CONFIG_EXAMPLE_SENDMAIL_NOMAC - May be defined to use software assigned MAC (optional) + CONFIG_EXAMPLE_SENDMAIL_IPADDR - Target IP address (required) + CONFIG_EXAMPLE_SENDMAIL_DRIPADDR - Default router IP addess (required) + CONFIG_EXAMPLE_SENDMAILT_NETMASK - Network mask (required) + CONFIG_EXAMPLE_SENDMAIL_RECIPIENT - The recipient of the email (required) + CONFIG_EXAMPLE_SENDMAIL_SENDER - Optional. Default: "nuttx-testing@example.com" + CONFIG_EXAMPLE_SENDMAIL_SUBJECT - Optional. Default: "Testing SMTP from NuttX" + CONFIG_EXAMPLE_SENDMAIL_BODY - Optional. Default: "Test message sent by NuttX" + + NOTE: This test has not been verified on the NuttX target environment. + As of this writing, unit-tested in the Cygwin/Linux host environment. + + NOTE 2: This sendmail example only works for the simplest of + environments. Virus protection software on your host may have + to be disabled to allow you to send messages. Only very open, + unprotected recipients can be used. Most will protect themselves + from this test email because it looks like SPAM. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += smtp + +examples/serloop +^^^^^^^^^^^^^^^^ + + This is a mindlessly simple loopback test on the console. Useful + for testing new serial drivers. Configuration options include: + + * CONFIG_EXAMPLES_SERLOOP_BUFIO + Use C buffered I/O (getchar/putchar) vs. raw console I/O + (read/read). + +examples/telnetd +^^^^^^^^^^^^^^^^ + + This directory contains a functional port of the tiny uIP shell. In + the NuttX environment, the NuttShell (at apps/nshlib) supercedes this + tiny shell and also supports telnetd. + + CONFIG_EXAMPLES_TELNETD_DAEMONPRIO - Priority of the Telnet daemon. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the + Telnet daemon. Default: 2048 + CONFIG_EXAMPLES_TELNETD_CLIENTPRIO- Priority of the Telnet client. + Default: SCHED_PRIORITY_DEFAULT + CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the + Telnet client. Default: 2048 + CONFIG_EXAMPLE_TELNETD_NOMAC - If the hardware has no MAC address of its + own, define this =y to provide a bogus address for testing. + CONFIG_EXAMPLE_TELNETD_IPADDR - The target IP address. Default 10.0.0.2 + CONFIG_EXAMPLE_TELNETD_DRIPADDR - The default router address. Default + 10.0.0.1 + CONFIG_EXAMPLE_TELNETD_NETMASK - The network mask. Default: 255.255.255.0 + + The appconfig file (apps/.config) should include: + + CONFIGURED_APPS += examples/telnetd + CONFIGURED_APPS += netutils/uiplib + CONFIGURED_APPS += netutils/telnetd + + Also, make sure that you have the following set in the NuttX configuration + file or else the performance will be very bad (because there will be only + one character per TCP transfer): + + CONFIG_STDIO_BUFFER_SIZE - Some value >= 64 + CONFIG_STDIO_LINEBUFFER=y + +examples/thttpd +^^^^^^^^^^^^^^^ + + An example that builds netutils/thttpd with some simple NXFLAT + CGI programs. see configs/README.txt for most THTTPD settings. + In addition to those, this example accepts: + + CONFIG_EXAMPLE_THTTPD_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_THTTPD_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_THTTPD_NETMASK - Network mask + + Applications using this example will need to provide an appconfig + file in the configuration directory with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += thttpd + +examples/tiff +^^^^^^^^^^^^^ + + This is a simple unit test for the TIFF creation library at apps/graphic/tiff. + It is configured to work in the Linux user-mode simulation and has not been + tested in any other environment. Since the example also depends on some + other logic to mount a file system, currently it will only work as an NSH + built-on, i.e., if the following is defined: + + CONFIG_NSH_BUILTIN_APPS=y + CONFIG_EXAMPLES_TIFF_BUILTIN=y + + At a miniumum, to run in an embedded environment, you will probably have to + change the configured paths to the TIFF files defined in the example. + + CONFIG_EXAMPLES_TIFF_OUTFILE - Name of the resulting TIFF file. Default is + "/tmp/result.tif" + CONFIG_EXAMPLES_TIFF_TMPFILE1/2 - Names of two temporaries files that + will be used in the file creation. Defaults are "/tmp/tmpfile1.dat" and + "/tmp/tmpfile2.dat" + + The following must also be defined in your apps/ configuration file: + + CONFIGURED_APPS += examples/tiff + CONFIGURED_APPS += graphics/tiff + +examples/touchscreen +^^^^^^^^^^^^^^^^^^^^ + + This configuration implements a simple touchscreen test at + apps/examples/touchscreen. This test will create an empty X11 window + and will print the touchscreen output as it is received from the + simulated touchscreen driver. + + CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN - Build the touchscreen test as + an NSH built-in function. Default: Built as a standalone problem + CONFIG_EXAMPLES_TOUCHSCREEN_MINOR - The minor device number. Minor=N + correspnds to touchscreen device /dev/input0. Note this value must + with CONFIG_EXAMPLES_TOUCHSCREEN_DEVPATH. Default 0. + CONFIG_EXAMPLES_TOUCHSCREEN_DEVPATH - The path to the touchscreen + device. This must be consistent with CONFIG_EXAMPLES_TOUCHSCREEN_MINOR. + Default: "/dev/input0" + CONFIG_EXAMPLES_TOUCHSCREEN_NSAMPLES - If CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN + 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. + + The following additional configurations must be set in the NuttX + configuration file: + + CONFIG_INPUTP=y + (Plus any touchscreen-specific settings). + + The following must also be defined in your apps configuration file: + + CONFIGURED_APPS += examples/tiff + CONFIGURED_APPS += graphics/tiff + + The board-specific logic must provide the following interfaces that will + be called by the example in order to initialize and uninitialize the + touchscreen hardware: + + int arch_tcinitialize(int minor); + int arch_tcuninitialize(void); + +examples/udp +^^^^^^^^^^^^ + + This is a simple network test for verifying client- and server- + functionality over UDP. + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + +examples/uip +^^^^^^^^^^^^ + + This is a port of uIP tiny webserver example application. Settings + specific to this example include: + + CONFIG_EXAMPLE_UIP_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_UIP_IPADDR - Target IP address + CONFIG_EXAMPLE_UIP_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_UIP_NETMASK - Network mask + CONFIG_EXAMPLE_UIP_DHCPC - Select to get IP address via DHCP + + If you use DHCPC, then some special configuration network options are + required. These include: + + CONFIG_NET=y - Of course + CONFIG_NSOCKET_DESCRIPTORS - And, of course, you must allocate some + socket descriptors. + CONFIG_NET_UDP=y - UDP support is required for DHCP + (as well as various other UDP-related + configuration settings). + CONFIG_NET_BROADCAST=y - UDP broadcast support is needed. + CONFIG_NET_BUFSIZE=650 - Per RFC2131 (p. 9), the DHCP client must be + (or larger) prepared to receive DHCP messages of up to + 576 bytes (excluding Ethernet, IP, or UDP + headers and FCS). + + Other configuration items apply also to the selected webserver net utility. + Additional relevant settings for the uIP webserver net utility are: + + CONFIG_NETUTILS_HTTPDSTACKSIZE + CONFIG_NETUTILS_HTTPDFILESTATS + CONFIG_NETUTILS_HTTPDNETSTATS + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += dhcpc + CONFIGURED_APPS += resolv + CONFIGURED_APPS += webserver + +examples/usbserial +^^^^^^^^^^^^^^^^^^ + + TARGET CONFIGURATION: + + This is another implementation of "Hello, World" but this one uses + a USB serial driver. Configuration options can be used to simply + the test. These options include: + + CONFIG_EXAMPLES_USBSERIAL_INONLY + Only verify IN (device-to-host) data transfers. Default: both + CONFIG_EXAMPLES_USBSERIAL_OUTONLY + Only verify OUT (host-to-device) data transfers. Default: both + CONFIG_EXAMPLES_USBSERIAL_ONLYSMALL + Send only small, single packet messages. Default: Send large and small. + CONFIG_EXAMPLES_USBSERIAL_ONLYBIG + Send only large, multi-packet messages. Default: Send large and small. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB), then + the example code will also manage the USB trace output. The amount of trace output + can be controlled using: + + CONFIG_EXAMPLES_USBSERIAL_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_USBSERIAL_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_USBSERIAL_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_USBSERIAL_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_USBSERIAL_TRACEINTERRUPTS + Show interrupt-related events. + + Error results are always shown in the trace output + + HOST-SIDE TEST PROGRAM + + In additional to the target device-side example, there is also a + host-side application in this directory. This host side application + must be executed on a Linux host in order to perform the USBSERIAL + test. The host application can be compiled under Linux (or Cygwin?) + as follows: + + cd examples/usbserial + make -f Makefile.host TOPDIR=<nuttx-directory> + + RUNNING THE TEST + + This will generate a small program called 'host'. Usage: + + 1. Build the examples/usbserial target program and start the target. + + 2. Wait a bit, then do enter: + + dmesg + + At the end of the dmesg output, you should see the serial + device was successfully idenfied and assigned to a tty device, + probably /dev/ttyUSB0 or /dev/ttyACM0 (depending on the configured + USB serial driver). + + 3. Then start the host application: + + ./host [<tty-dev>] + + Where: + + <tty-dev> is the USB TTY device to use. The default is + "/dev/ttyUSB0" (for the PL2303 emulation) or "/dev/ttyACM0" (for + the CDC/ACM serial device). + + The host and target will exchange are variety of very small and very large + serial messages. + +examples/usbstorage +^^^^^^^^^^^^^^^^^^^ + + This example registers a block device driver, then exports the block + the device using the USB storage class driver. In order to use this + example, your board-specific logic must provide the function: + + void usbmsc_archinitialize(void); + + This function will be called by the example/usbstorage in order to + do the actual registration of the block device drivers. For examples + of the implementation of usbmsc_archinitialize() see + configs/mcu123-lpc124x/src/up_usbmsc.c or + configs/stm3210e-eval/src/usbmsc.c + + Configuration options: + + CONFIG_EXAMPLES_USBMSC_BUILTIN + This example can be built as two NSH "built-in" commands if this option + is selected: 'msconn' will connect the USB mass storage device; 'msdis' + will disconnect the USB storage device. + CONFIG_EXAMPLES_USBMSC_NLUNS + Defines the number of logical units (LUNs) exported by the USB storage + driver. Each LUN corresponds to one exported block driver (or partition + of a block driver). May be 1, 2, or 3. Default is 1. + CONFIG_EXAMPLES_USBMSC_DEVMINOR1 + The minor device number of the block driver for the first LUN. For + example, N in /dev/mmcsdN. Used for registering the block driver. Default + is zero. + CONFIG_EXAMPLES_USBMSC_DEVPATH1 + The full path to the registered block driver. Default is "/dev/mmcsd0" + CONFIG_EXAMPLES_USBMSC_DEVMINOR2 and CONFIG_EXAMPLES_USBMSC_DEVPATH2 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_USBMSC_NLUNS + is 2 or 3. No defaults. + CONFIG_EXAMPLES_USBMSC_DEVMINOR3 and CONFIG_EXAMPLES_USBMSC_DEVPATH3 + Similar parameters that would have to be provided if CONFIG_EXAMPLES_USBMSC_NLUNS + is 3. No defaults. + CONFIG_EXAMPLES_USBMSC_DEBUGMM + Enables some debug tests to check for memory usage and memory leaks. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB), then + the example code will also manage the USB trace output. The amount of trace output + can be controlled using: + + CONFIG_EXAMPLES_USBMSC_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_USBMSC_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_USBMSC_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_USBMSC_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_USBMSC_TRACEINTERRUPTS + Show interrupt-related events. + + Error results are always shown in the trace output + + NOTE 1: When built as an NSH add-on command (CONFIG_EXAMPLES_USBMSC_BUILTIN=y), + Caution should be used to assure that the SD drive (or other storage device) is + not in use when the USB storage device is configured. Specifically, the SD + driver should be unmounted like: + + nsh> mount -t vfat /dev/mmcsd0 /mnt/sdcard # Card is mounted in NSH + ... + nsh> umount /mnd/sdcard # Unmount before connecting USB!!! + nsh> msconn # Connect the USB storage device + ... + nsh> msdis # Disconnect USB storate device + nsh> mount -t vfat /dev/mmcsd0 /mnt/sdcard # Restore the mount + + Failure to do this could result in corruption of the SD card format. + + NOTE 2: This test exercises internal USB device driver interfaces. As such, + it relies on internal OS interfaces that are not normally available to a + user-space program. As a result, this example cannot be used if a + NuttX is built as a protected, supervisor kernel (CONFIG_NUTTX_KERNEL). + +examples/usbterm +^^^^^^^^^^^^^^^^ + + This example implements a little USB terminal.. more of a USB "chat" + edited lines are received from the remote host connected via USB + serial and echoed out the target serial console. Edited lines from + the local target serial console are received and forwarded to the + remote host via USB serial. + + Usage: + - Build the example and load into the target FLASH + - Connect on terminal to the target RS-232 connect and configure + for 115200 8N1. For example, suppose this Tera Term on a Windows + box. + - Power up the target board + - Connect the USB to a Linux box. Use the Linux dmesg command to + assure that the connect was successful. The USB CDC ACM device + should appear as /dev/ttyACM0 + - On the Linux box, open minicom with tty=/dev/ttyACM0. + Configure minicom so that (1) local characters are echoed and (2) + so that no CR is required. + - Now what you type on the target Tera Term window should echo on + the Linux minicom window and, conversely, what you type on the + minicom winow should be echo in the target Tera Term window. + + Configuration options: + + CONFIG_EXAMPLES_USBTERM_BUILTIN - Build the usbterm example as an NSH + built-in command. NOTE: This is not fully functional as of this + writing.. It should work, but there is no mechanism in place yet + to exit the USB terminal program and return to NSH. + CONFIG_EXAMPLES_USBTERM_DEVINIT - If defined, then the example will + call a user provided function as part of its initialization: + int usbterm_devinit(void); + And another user provided function at termination: + void usbterm_devuninit(void); + CONFIG_EXAMPLES_USBTERM_BUFLEN - The size of the input and output + buffers used for receiving data. Default 256 bytes. + + If CONFIG_USBDEV_TRACE is enabled (or CONFIG_DEBUG and CONFIG_DEBUG_USB, or + CONFIG_USBDEV_TRACE), then the example code will also manage the USB trace + output. The amount of trace output can be controlled using: + + CONFIG_EXAMPLES_USBTERM_TRACEINIT + Show initialization events + CONFIG_EXAMPLES_USBTERM_TRACECLASS + Show class driver events + CONFIG_EXAMPLES_USBTERM_TRACETRANSFERS + Show data transfer events + CONFIG_EXAMPLES_USBTERM_TRACECONTROLLER + Show controller events + CONFIG_EXAMPLES_USBTERM_TRACEINTERRUPTS + Show interrupt-related events. + + NOTE: By default, USBterm uses readline to get data from stdin. So your + appconfig file must have the following build path: + + CONFIGURED_APPS += system/readline + + NOTE: If you use the USBterm task over a telnet NSH connection, then you + should set the following configuration item: + + CONFIG_EXAMPLES_USBTERM_FGETS=y + + By default, the USBterm client will use readline() to get characters from + the console. Readline includes and command-line editor and echos + characters received in stdin back through stdout. Neither of these + behaviors are desire-able if Telnet is used. + + Error results are always shown in the trace output + + Other relevant configuration options: CONFIG_CDCACM selected by the + Prolifics emulation (not defined) and the CDC serial implementation + (when defined). CONFIG_USBDEV_TRACE_INITIALIDSET. + +examples/watchdog +^^^^^^^^^^^^^^^^^ + + A simple test of a watchdog timer driver. Initializes starts the watchdog + timer. It pings the watchdog timer for a period of time then lets the + watchdog timer expire... resetting the CPU is successful. This + example can ONLY be built as an NSH built-in function. + + This test depends on these specific Watchdog/NSH configurations settings (your + specific watchdog hardware settings might require additional settings). + + CONFIG_WATCHDOG- Enables watchdog timer support support. + CONFIG_NSH_BUILTIN_APPS - Build the watchdog time test as an NSH + built-in function. Default: Not built! The example can only be used + as an NSH built-in application + + Specific configuration options for this example include: + + CONFIG_EXAMPLES_WATCHDOG_DEVPATH - The path to the Watchdog device. + Default: /dev/watchdog0 + CONFIG_EXAMPLES_WATCHDOG_PINGTIME - Time in milliseconds that the example + will ping the watchdog before letting the watchdog expire. Default: 5000 + milliseconds + CONFIG_EXAMPLES_WATCHDOG_PINGDELAY - Time delay between pings in + milliseconds. Default: 500 milliseconds. + CONFIG_EXAMPLES_WATCHDOG_TIMEOUT - The watchdog timeout value in + milliseconds before the watchdog timer expires. Default: 2000 + milliseconds. + +examples/wget +^^^^^^^^^^^^^ + + A simple web client example. It will obtain a file from a server using the HTTP + protocol. Settings unique to this example include: + + CONFIG_EXAMPLE_WGET_URL - The URL of the file to get + CONFIG_EXAMPLE_WGET_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLE_WGET_IPADDR - Target IP address + CONFIG_EXAMPLE_WGET_DRIPADDR - Default router IP addess + CONFIG_EXAMPLE_WGET_NETMASK - Network mask + + This example uses netutils/webclient. Additional configuration settings apply + to that code as follows (but built-in defaults are probably OK): + + CONFIG_WEBCLIENT_GETMIMETYPE, CONFIG_WEBCLIENT_MAXHTTPLINE, + CONFIG_WEBCLIENT_MAXMIMESIZE, CONFIG_WEBCLIENT_MAXHOSTNAME, + CONFIG_WEBCLIENT_MAXFILENAME + + Of course, the example also requires other settings including CONFIG_NET and + CONFIG_NET_TCP. The example also uses the uIP resolver which requires CONFIG_UDP. + + WARNNG: As of this writing, wget is untested on the target platform. At present + it has been tested only in the host-based configuration described in the following + note. The primary difference is that the target version will rely on the also + untested uIP name resolver. + + NOTE: For test purposes, this example can be built as a host-based wget function. + This can be built as follows: + + cd examples/wget + make -f Makefile.host + + Applications using this example will need to provide an appconfig + file in the configuration driver with instruction to build applications + like: + + CONFIGURED_APPS += uiplib + CONFIGURED_APPS += resolv + CONFIGURED_APPS += webclient + + diff --git a/apps/examples/adc/Kconfig b/apps/examples/adc/Kconfig new file mode 100644 index 000000000..b6dca047c --- /dev/null +++ b/apps/examples/adc/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_ADC + bool "ADC example" + default n + ---help--- + Enable the ADC example + +if EXAMPLES_ADC +endif diff --git a/apps/examples/adc/Makefile b/apps/examples/adc/Makefile new file mode 100644 index 000000000..6357dfc3d --- /dev/null +++ b/apps/examples/adc/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/adc/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NuttX NX Graphics Example. + +ASRCS = +CSRCS = adc_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 . + +# Touchscreen built-in application info + +APPNAME = adc +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 diff --git a/apps/examples/adc/adc.h b/apps/examples/adc/adc.h new file mode 100644 index 000000000..9f79db92a --- /dev/null +++ b/apps/examples/adc/adc.h @@ -0,0 +1,125 @@ +/**************************************************************************** + * examples/examples/adc/adc.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_ADC_ADC_H +#define __APPS_EXAMPLES_ADC_ADC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_NSH_BUILTIN_APPS - Build the ADC test as an NSH built-in function. + * Default: Built as a standalone problem + * CONFIG_EXAMPLES_ADC_DEVPATH - The default path to the ADC device. Default: /dev/adc0 + * CONFIG_EXAMPLES_ADC_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. + * CONFIG_EXAMPLES_ADC_GROUPSIZE - The number of samples to read at once. + * Default: 4 + */ + +#ifndef CONFIG_ADC +# error "ADC device support is not enabled (CONFIG_ADC)" +#endif + +#ifndef CONFIG_EXAMPLES_ADC_DEVPATH +# define CONFIG_EXAMPLES_ADC_DEVPATH "/dev/adc0" +#endif + +#ifndef CONFIG_EXAMPLES_ADC_GROUPSIZE +# define CONFIG_EXAMPLES_ADC_GROUPSIZE 4 +#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 + ****************************************************************************/ + +struct adc_state_s +{ + bool initialized; + FAR char *devpath; +#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_ADC_NSAMPLES) + int count; +#endif +}; + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: adc_devinit() + * + * Description: + * Perform architecuture-specific initialization of the ADC hardware. This + * interface must be provided by all configurations using apps/examples/adc + * + ****************************************************************************/ + +int adc_devinit(void); + +#endif /* __APPS_EXAMPLES_ADC_ADC_H */ diff --git a/apps/examples/adc/adc_main.c b/apps/examples/adc/adc_main.c new file mode 100644 index 000000000..b88032654 --- /dev/null +++ b/apps/examples/adc/adc_main.c @@ -0,0 +1,367 @@ +/**************************************************************************** + * examples/adc/adc_main.c + * + * 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 + * 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include <nuttx/analog/adc.h> + +#include "adc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +# define MAIN_NAME adc_main +# define MAIN_STRING "adc_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct adc_state_s g_adcstate; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: adc_devpath + ****************************************************************************/ + +static void adc_devpath(FAR struct adc_state_s *adc, FAR const char *devpath) +{ + /* Get rid of any old device path */ + + if (adc->devpath) + { + free(adc->devpath); + } + + /* Then set-up the new device path by copying the string */ + + adc->devpath = strdup(devpath); +} + +/**************************************************************************** + * Name: adc_help + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static void adc_help(FAR struct adc_state_s *adc) +{ + message("Usage: adc [OPTIONS]\n"); + message("\nArguments are \"sticky\". For example, once the ADC device is\n"); + message("specified, that device will be re-used until it is changed.\n"); + message("\n\"sticky\" OPTIONS include:\n"); + message(" [-p devpath] selects the ADC device. " + "Default: %s Current: %s\n", + CONFIG_EXAMPLES_ADC_DEVPATH, g_adcstate.devpath ? g_adcstate.devpath : "NONE"); + message(" [-n count] selects the samples to collect. " + "Default: 1 Current: %d\n", adc->count); + message(" [-h] shows this message and exits\n"); +} +#endif + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static 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 +static 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 +static void parse_args(FAR struct adc_state_s *adc, int argc, FAR char **argv) +{ + FAR char *ptr; + FAR char *str; + long value; + int index; + int nargs; + + 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) + { + message("Count must be non-negative: %ld\n", value); + exit(1); + } + + adc->count = (uint32_t)value; + index += nargs; + break; + + case 'p': + nargs = arg_string(&argv[index], &str); + adc_devpath(adc, str); + index += nargs; + break; + + case 'h': + adc_help(adc); + exit(0); + + default: + message("Unsupported option: %s\n", ptr); + adc_help(adc); + exit(1); + } + } +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/adc_main + ****************************************************************************/ + +int MAIN_NAME(int argc, char *argv[]) +{ + struct adc_msg_s sample[CONFIG_EXAMPLES_ADC_GROUPSIZE]; + size_t readsize; + ssize_t nbytes; + int fd; + int errval = 0; + int ret; + int i; + + /* Check if we have initialized */ + + if (!g_adcstate.initialized) + { + /* Initialization of the ADC hardware is performed by logic external to + * this test. + */ + + message(MAIN_STRING "Initializing external ADC device\n"); + ret = adc_devinit(); + if (ret != OK) + { + message(MAIN_STRING "adc_devinit failed: %d\n", ret); + errval = 1; + goto errout; + } + + /* Set the default values */ + + adc_devpath(&g_adcstate, CONFIG_EXAMPLES_ADC_DEVPATH); + +#ifdef CONFIG_EXAMPLES_ADC_NSAMPLES + g_adcstate.count = CONFIG_EXAMPLES_ADC_NSAMPLES; +#else + g_adcstate.count = 1; +#endif + g_adcstate.initialized = true; + } + + /* Parse the command line */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + parse_args(&g_adcstate, argc, argv); +#endif + + /* If this example is configured as an NX add-on, then limit the number of + * samples that we collect before returning. Otherwise, we never return + */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_ADC_NSAMPLES) + message(MAIN_STRING "g_adcstate.count: %d\n", g_adcstate.count); +#endif + + /* Open the ADC device for reading */ + + message(MAIN_STRING "Hardware initialized. Opening the ADC device: %s\n", + g_adcstate.devpath); + + fd = open(g_adcstate.devpath, O_RDONLY); + if (fd < 0) + { + message(MAIN_STRING "open %s failed: %d\n", g_adcstate.devpath, errno); + errval = 2; + goto errout_with_dev; + } + + /* Now loop the appropriate number of times, displaying the collected + * ADC samples. + */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) + for (; g_adcstate.count > 0; g_adcstate.count--) +#elif defined(CONFIG_EXAMPLES_ADC_NSAMPLES) + for (g_adcstate.count = 0; g_adcstate.count < CONFIG_EXAMPLES_ADC_NSAMPLES; g_adcstate.count++) +#else + for (;;) +#endif + { + /* Flush any output before the loop entered or from the previous pass + * through the loop. + */ + + msgflush(); + + /* Read CONFIG_EXAMPLES_ADC_GROUPSIZE samples */ + + readsize = CONFIG_EXAMPLES_ADC_GROUPSIZE * sizeof(struct adc_msg_s); + nbytes = read(fd, sample, readsize); + + /* Handle unexpected return values */ + + if (nbytes < 0) + { + errval = errno; + if (errval != EINTR) + { + message(MAIN_STRING "read %s failed: %d\n", + g_adcstate.devpath, errval); + errval = 3; + goto errout_with_dev; + } + + message(MAIN_STRING "Interrupted read...\n"); + } + else if (nbytes == 0) + { + message(MAIN_STRING "No data read, Ignoring\n"); + } + + /* Print the sample data on successful return */ + + else + { + int nsamples = nbytes / sizeof(struct adc_msg_s); + if (nsamples * sizeof(struct adc_msg_s) != nbytes) + { + message(MAIN_STRING "read size=%d is not a multiple of sample size=%d, Ignoring\n", + nbytes, sizeof(struct adc_msg_s)); + } + else + { + message("Sample:\n"); + for (i = 0; i < nsamples ; i++) + { + message("%d: channel: %d value: %d\n", + i, sample[i].am_channel, sample[i].am_data); + } + } + } + } + +errout_with_dev: + close(fd); + +errout: + message("Terminating!\n"); + msgflush(); + return errval; +} diff --git a/apps/examples/buttons/Kconfig b/apps/examples/buttons/Kconfig new file mode 100644 index 000000000..9c34b37bc --- /dev/null +++ b/apps/examples/buttons/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_BUTTONS + bool "Buttons example" + default n + ---help--- + Enable the buttons example + +if EXAMPLES_BUTTONS +endif diff --git a/apps/examples/buttons/Makefile b/apps/examples/buttons/Makefile new file mode 100644 index 000000000..9c0587199 --- /dev/null +++ b/apps/examples/buttons/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/buttons/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# Hello, World! Example + +ASRCS = +CSRCS = 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 . + +# Buttons built-in application info + +APPNAME = buttons +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 diff --git a/apps/examples/buttons/main.c b/apps/examples/buttons/main.c new file mode 100644 index 000000000..fe447ca6b --- /dev/null +++ b/apps/examples/buttons/main.c @@ -0,0 +1,509 @@ +/**************************************************************************** + * examples/buttons/main.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * NOTE: This test exercises internal button driver interfaces. As such, it + * it relies on internal OS interfaces that are not normally available to a + * user-space program. As a result, this example cannot be used if a + * NuttX is built as a protected, supervisor kernel (CONFIG_NUTTX_KERNEL). + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/arch.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <debug.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_ARCH_BUTTONS +# error "CONFIG_ARCH_BUTTONS is not defined in the configuration" +#endif + +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME0 +# define CONFIG_EXAMPLE_BUTTONS_NAME0 "BUTTON0" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME1 +# define CONFIG_EXAMPLE_BUTTONS_NAME1 "BUTTON1" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME2 +# define CONFIG_EXAMPLE_BUTTONS_NAME2 "BUTTON2" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME3 +# define CONFIG_EXAMPLE_BUTTONS_NAME3 "BUTTON3" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME4 +# define CONFIG_EXAMPLE_BUTTONS_NAME4 "BUTTON4" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME5 +# define CONFIG_EXAMPLE_BUTTONS_NAME5 "BUTTON5" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME6 +# define CONFIG_EXAMPLE_BUTTONS_NAME6 "BUTTON6" +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_NAME7 +# define CONFIG_EXAMPLE_BUTTONS_NAME7 "BUTTON7" +#endif + +#define BUTTON_MIN 0 +#define BUTTON_MAX 7 + +#ifndef CONFIG_EXAMPLE_BUTTONS_MIN +# define CONFIG_EXAMPLE_BUTTONS_MIN BUTTON_MIN +#endif +#ifndef CONFIG_EXAMPLE_BUTTONS_MAX +# define CONFIG_EXAMPLE_BUTTONS_MAX BUTTON_MAX +#endif + +#if CONFIG_EXAMPLE_BUTTONS_MIN > CONFIG_EXAMPLE_BUTTONS_MAX +# error "CONFIG_EXAMPLE_BUTTONS_MIN > CONFIG_EXAMPLE_BUTTONS_MAX" +#endif +#if CONFIG_EXAMPLE_BUTTONS_MAX > 7 +# error "CONFIG_EXAMPLE_BUTTONS_MAX > 7" +#endif + +#ifndef CONFIG_EXAMPLE_IRQBUTTONS_MIN +# define CONFIG_EXAMPLE_IRQBUTTONS_MIN CONFIG_EXAMPLE_BUTTONS_MIN +#endif +#ifndef CONFIG_EXAMPLE_IRQBUTTONS_MAX +# define CONFIG_EXAMPLE_IRQBUTTONS_MAX CONFIG_EXAMPLE_BUTTONS_MAX +#endif + +#if CONFIG_EXAMPLE_IRQBUTTONS_MIN > CONFIG_EXAMPLE_IRQBUTTONS_MAX +# error "CONFIG_EXAMPLE_IRQBUTTONS_MIN > CONFIG_EXAMPLE_IRQBUTTONS_MAX" +#endif +#if CONFIG_EXAMPLE_IRQBUTTONS_MAX > 7 +# error "CONFIG_EXAMPLE_IRQBUTTONS_MAX > 7" +#endif + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + +#define MIN_BUTTON MIN(CONFIG_EXAMPLE_BUTTONS_MIN, CONFIG_EXAMPLE_IRQBUTTONS_MIN) +#define MAX_BUTTON MAX(CONFIG_EXAMPLE_BUTTONS_MAX, CONFIG_EXAMPLE_IRQBUTTONS_MAX) + +#define NUM_BUTTONS (MAX_BUTTON - MIN_BUTTON + 1) +#define BUTTON_INDEX(b) ((b)-MIN_BUTTON) + +/* Is this being built as an NSH built-in application? */ + +#ifdef CONFIG_NSH_BUILTIN_APPS +# define MAIN_NAME buttons_main +# define MAIN_STRING "buttons_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct button_info_s +{ + FAR const char *name; /* Name for the button */ +#ifdef CONFIG_ARCH_IRQBUTTONS + xcpt_t handler; /* Button interrupt handler */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void show_buttons(uint8_t oldset, uint8_t newset); + +#ifdef CONFIG_ARCH_IRQBUTTONS +static void button_handler(int id, int irq); + +#if MIN_BUTTON < 1 +static int button0_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 2 && MAX_BUTTON > 0 +static int button1_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 3 && MAX_BUTTON > 1 +static int button2_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 4 && MAX_BUTTON > 2 +static int button3_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 5 && MAX_BUTTON > 3 +static int button4_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 6 && MAX_BUTTON > 4 +static int button5_handler(int irq, FAR void *context); +#endif +#if MIN_BUTTON < 7 && MAX_BUTTON > 5 +static int button6_handler(int irq, FAR void *context); +#endif +#if MAX_BUTTON > 6 +static int button7_handler(int irq, FAR void *context); +#endif +#endif /* CONFIG_ARCH_IRQBUTTONS */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + + /* Button Names */ + +static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = +{ +#if MIN_BUTTON < 1 + { + CONFIG_EXAMPLE_BUTTONS_NAME0, +#ifdef CONFIG_ARCH_IRQBUTTONS + button0_handler +#endif + }, +#endif +#if MIN_BUTTON < 2 && MAX_BUTTON > 0 + { + CONFIG_EXAMPLE_BUTTONS_NAME1, +#ifdef CONFIG_ARCH_IRQBUTTONS + button1_handler +#endif + }, +#endif +#if MIN_BUTTON < 3 && MAX_BUTTON > 1 + { + CONFIG_EXAMPLE_BUTTONS_NAME2, +#ifdef CONFIG_ARCH_IRQBUTTONS + button2_handler +#endif + }, +#endif +#if MIN_BUTTON < 4 && MAX_BUTTON > 2 + { + CONFIG_EXAMPLE_BUTTONS_NAME3, +#ifdef CONFIG_ARCH_IRQBUTTONS + button3_handler +#endif + }, +#endif +#if MIN_BUTTON < 5 && MAX_BUTTON > 3 + { + CONFIG_EXAMPLE_BUTTONS_NAME4, +#ifdef CONFIG_ARCH_IRQBUTTONS + button4_handler +#endif + }, +#endif +#if MIN_BUTTON < 6 && MAX_BUTTON > 4 + { + CONFIG_EXAMPLE_BUTTONS_NAME5, +#ifdef CONFIG_ARCH_IRQBUTTONS + button5_handler +#endif + }, +#endif +#if MIN_BUTTON < 7 && MAX_BUTTON > 5 + { + CONFIG_EXAMPLE_BUTTONS_NAME6, +#ifdef CONFIG_ARCH_IRQBUTTONS + button6_handler +#endif + }, +#endif +#if MAX_BUTTON > 6 + { + CONFIG_EXAMPLE_BUTTONS_NAME7, +#ifdef CONFIG_ARCH_IRQBUTTONS + button7_handler +#endif + } +#endif +}; + +/* Last sampled button set */ + +static uint8_t g_oldset; + +/* Used to limit the number of button presses */ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static volatile long g_nbuttons; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void show_buttons(uint8_t oldset, uint8_t newset) +{ + uint8_t chgset = oldset ^ newset; + int i; + + /* Update the count of button presses shown */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + if ((chgset & newset) != 0) + { + g_nbuttons++; + } +#endif + + /* Show each button state change */ + + for (i = MIN_BUTTON; i <= MAX_BUTTON; i++) + { + uint8_t mask = (1 << i); + if ((chgset & mask) != 0) + { + FAR const char *state; + + /* Get the button state */ + + if ((newset & mask) != 0) + { + state = "depressed"; + } + else + { + state = "released"; + } + + /* Use lib_lowprintf() because we make be executing from an + * interrupt handler. + */ + + lib_lowprintf(" %s %s\n", g_buttoninfo[BUTTON_INDEX(i)].name, state); + } + } +} + +#ifdef CONFIG_ARCH_IRQBUTTONS +static void button_handler(int id, int irq) +{ + uint8_t newset = up_buttons(); + + lib_lowprintf("IRQ:%d Button %d:%s SET:%02x:\n", + irq, id, g_buttoninfo[BUTTON_INDEX(id)].name, newset); + show_buttons(g_oldset, newset); + g_oldset = newset; +} + +#if MIN_BUTTON < 1 +static int button0_handler(int irq, FAR void *context) +{ + button_handler(0, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 2 && MAX_BUTTON > 0 +static int button1_handler(int irq, FAR void *context) +{ + button_handler(1, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 3 && MAX_BUTTON > 1 +static int button2_handler(int irq, FAR void *context) +{ + button_handler(2, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 4 && MAX_BUTTON > 2 +static int button3_handler(int irq, FAR void *context) +{ + button_handler(3, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 5 && MAX_BUTTON > 3 +static int button4_handler(int irq, FAR void *context) +{ + button_handler(4, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 6 && MAX_BUTTON > 4 +static int button5_handler(int irq, FAR void *context) +{ + button_handler(5, irq); + return OK; +} +#endif + +#if MIN_BUTTON < 7 && MAX_BUTTON > 5 +static int button6_handler(int irq, FAR void *context) +{ + button_handler(6, irq); + return OK; +} +#endif + +#if MAX_BUTTON > 6 +static int button7_handler(int irq, FAR void *context) +{ + button_handler(7, irq); + return OK; +} +#endif +#endif /* CONFIG_ARCH_IRQBUTTONS */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start/buttons_main + ****************************************************************************/ + +int MAIN_NAME(int argc, char *argv[]) +{ + uint8_t newset; + irqstate_t flags; + int i; + + /* If this example is configured as an NX add-on, then limit the number of + * samples that we collect before returning. Otherwise, we never return + */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + long maxbuttons = 1; + g_nbuttons = 0; + if (argc > 1) + { + maxbuttons = strtol(argv[1], NULL, 10); + } + lib_lowprintf("maxbuttons: %d\n", maxbuttons); +#endif + + /* Initialize the button GPIOs */ + + up_buttoninit(); + + /* Register to recieve button interrupts */ + +#ifdef CONFIG_ARCH_IRQBUTTONS + for (i = CONFIG_EXAMPLE_IRQBUTTONS_MIN; i <= CONFIG_EXAMPLE_IRQBUTTONS_MAX; i++) + { + xcpt_t oldhandler = up_irqbutton(i, g_buttoninfo[BUTTON_INDEX(i)].handler); + + /* Use lib_lowprintf() for compatibility with interrrupt handler output. */ + + lib_lowprintf("Attached handler at %p to button %d [%s], oldhandler:%p\n", + g_buttoninfo[BUTTON_INDEX(i)].handler, i, + g_buttoninfo[BUTTON_INDEX(i)].name, oldhandler); + + /* Some hardware multiplexes different GPIO button sources to the same + * physical interrupt. If we register multiple such multiplexed button + * interrupts, then the second registration will overwrite the first. In + * this case, the first button interrupts may be aliased to the second + * interrupt handler (or worse, could be lost). + */ + + if (oldhandler != NULL) + { + lib_lowprintf("WARNING: oldhandler:%p is not NULL! " + "Button events may be lost or aliased!\n", + oldhandler); + } + } +#endif + + /* Poll button state */ + + g_oldset = up_buttons(); +#ifdef CONFIG_NSH_BUILTIN_APPS + while (g_nbuttons < maxbuttons) +#else + for (;;) +#endif + { + /* Get the set of pressed and release buttons. */ + + newset = up_buttons(); + + /* Any changes from the last sample? */ + + if (newset != g_oldset) + { + /* Disable interrupts so that output here will not collide with + * output from an interrupt handler. + */ + + flags = irqsave(); + + /* Use lib_lowprintf() for compatibility with interrrupt handler + * output. + */ + + lib_lowprintf("POLL SET:%02x:\n", newset); + show_buttons(g_oldset, newset); + g_oldset = newset; + irqrestore(flags); + } + + /* Sleep a little... but not long. This will determine how fast we + * poll for button changes. + */ + + usleep(150000); /* 150 Milliseconds */ + } + + /* Un-register button handlers */ + +#if defined(CONFIG_ARCH_IRQBUTTONS) && defined(CONFIG_NSH_BUILTIN_APPS) + for (i = CONFIG_EXAMPLE_IRQBUTTONS_MIN; i <= CONFIG_EXAMPLE_IRQBUTTONS_MAX; i++) + { + (void)up_irqbutton(i, NULL); + } +#endif + + return 0; +} + diff --git a/apps/examples/can/Kconfig b/apps/examples/can/Kconfig new file mode 100644 index 000000000..2b4504d68 --- /dev/null +++ b/apps/examples/can/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_CAN + bool "CAN example" + default n + ---help--- + Enable the CAN example + +if EXAMPLES_CAN +endif + diff --git a/apps/examples/can/Makefile b/apps/examples/can/Makefile new file mode 100644 index 000000000..c6dc5af84 --- /dev/null +++ b/apps/examples/can/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/can/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# NuttX NX Graphics Example. + +ASRCS = +CSRCS = can_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 . + +# Touchscreen built-in application info + +APPNAME = can +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 diff --git a/apps/examples/can/can.h b/apps/examples/can/can.h new file mode 100644 index 000000000..53a6b63ea --- /dev/null +++ b/apps/examples/can/can.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * examples/examples/can/can.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_CAN_CAN_H +#define __APPS_EXAMPLES_CAN_CAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* This test depends on these specific CAN configurations settings (your + * specific CAN settings might require additional settings). + * + * CONFIG_CAN - Enables CAN support. + * CONFIG_CAN_LOOPBACK - A CAN driver may or may not support a loopback + * mode for testing. The STM32 CAN driver does support loopback mode. + * + * Specific configuration options for this example include: + * + * CONFIG_NSH_BUILTIN_APPS - Build the CAN test as an NSH built-in function. + * Default: Built as a standalone problem + * CONFIG_CAN_LOOPBACK + * CONFIG_EXAMPLES_CAN_DEVPATH - The path to the CAN device. Default: /dev/can0 + * CONFIG_EXAMPLES_CAN_NMSGS - If CONFIG_NSH_BUILTIN_APPS + * is defined, then the number of loops is provided on the command line + * and this value is ignored. Otherwise, this number of CAN message is + * collected and the program terminates. Default: If built as an NSH + * built-in, the default is 32. Otherwise messages are sent and received + * indefinitely. + * CONFIG_EXAMPLES_CAN_READONLY - Only receive messages + * CONFIG_EXAMPLES_CAN_WRITEONLY - Only send messages + */ + +#ifndef CONFIG_CAN +# error "CAN device support is not enabled (CONFIG_CAN)" +#endif + +#ifndef CONFIG_CAN_LOOPBACK +# warning "CAN loopback is not enabled (CONFIG_CAN_LOOPBACK)" +#endif + +#ifndef CONFIG_EXAMPLES_CAN_DEVPATH +# define CONFIG_EXAMPLES_CAN_DEVPATH "/dev/can0" +#endif + +#if defined(CONFIG_NSH_BUILTIN_APPS) && !defined(CONFIG_EXAMPLES_CAN_NMSGS) +# define CONFIG_EXAMPLES_CAN_NMSGS 32 +#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 + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: can_devinit() + * + * Description: + * Perform architecuture-specific initialization of the CAN hardware. This + * interface must be provided by all configurations using apps/examples/can + * + ****************************************************************************/ + +int can_devinit(void); + +#endif /* __APPS_EXAMPLES_CAN_CAN_H */ diff --git a/apps/examples/can/can_main.c b/apps/examples/can/can_main.c new file mode 100644 index 000000000..0ea729e5e --- /dev/null +++ b/apps/examples/can/can_main.c @@ -0,0 +1,309 @@ +/**************************************************************************** + * examples/can/can_main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include <nuttx/can.h> + +#include "can.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_EXAMPLES_CAN_READONLY) +# undef CONFIG_EXAMPLES_CAN_WRITEONLY +# undef CONFIG_EXAMPLES_CAN_READWRITE +# define CAN_OFLAGS O_RDONLY +#elif defined(CONFIG_EXAMPLES_CAN_WRITEONLY) +# undef CONFIG_EXAMPLES_CAN_READWRITE +# define CAN_OFLAGS O_WRONLY +#else +# undef CONFIG_EXAMPLES_CAN_READWRITE +# define CONFIG_EXAMPLES_CAN_READWRITE 1 +# define CAN_OFLAGS O_RDWR +#endif + +#ifdef CONFIG_CAN_EXTID +# define MAX_ID (1 << 29) +#else +# define MAX_ID (1 << 11) +#endif + +#ifdef CONFIG_NSH_BUILTIN_APPS +# define MAIN_NAME can_main +# define MAIN_STRING "can_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/can_main + ****************************************************************************/ + +int MAIN_NAME(int argc, char *argv[]) +{ +#ifndef CONFIG_EXAMPLES_CAN_READONLY + struct can_msg_s txmsg; +#ifdef CONFIG_CAN_EXTID + uint32_t msgid; +#else + uint16_t msgid; +#endif + int msgdlc; + uint8_t msgdata; +#endif + +#ifndef CONFIG_EXAMPLES_CAN_WRITEONLY + struct can_msg_s rxmsg; +#endif + + size_t msgsize; + ssize_t nbytes; +#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_CAN_NMSGS) + long nmsgs; +#endif + + int fd; + int errval = 0; + int ret; + int i; + + /* If this example is configured as an NX add-on, then limit the number of + * samples that we collect before returning. Otherwise, we never return + */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) + nmsgs = CONFIG_EXAMPLES_CAN_NMSGS; + if (argc > 1) + { + nmsgs = strtol(argv[1], NULL, 10); + } + message(MAIN_STRING "nmsgs: %d\n", nmsgs); +#elif defined(CONFIG_EXAMPLES_CAN_NMSGS) + message(MAIN_STRING "nmsgs: %d\n", CONFIG_EXAMPLES_CAN_NMSGS); +#endif + + /* Initialization of the CAN hardware is performed by logic external to + * this test. + */ + + message(MAIN_STRING "Initializing external CAN device\n"); + ret = can_devinit(); + if (ret != OK) + { + message(MAIN_STRING "can_devinit failed: %d\n", ret); + errval = 1; + goto errout; + } + + /* Open the CAN device for reading */ + + message(MAIN_STRING "Hardware initialized. Opening the CAN device\n"); + fd = open(CONFIG_EXAMPLES_CAN_DEVPATH, CAN_OFLAGS); + if (fd < 0) + { + message(MAIN_STRING "open %s failed: %d\n", + CONFIG_EXAMPLES_CAN_DEVPATH, errno); + errval = 2; + goto errout_with_dev; + } + + /* Now loop the appropriate number of times, performing one loopback test + * on each pass. + */ + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + msgdlc = 1; + msgid = 1; + msgdata = 0; +#endif + +#if defined(CONFIG_NSH_BUILTIN_APPS) + for (; nmsgs > 0; nmsgs--) +#elif defined(CONFIG_EXAMPLES_CAN_NMSGS) + for (nmsgs = 0; nmsgs < CONFIG_EXAMPLES_CAN_NMSGS; nmsgs++) +#else + for (;;) +#endif + { + /* Flush any output before the loop entered or from the previous pass + * through the loop. + */ + + msgflush(); + + /* Construct the next TX message */ + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + txmsg.cm_hdr.ch_id = msgid; + txmsg.cm_hdr.ch_rtr = false; + txmsg.cm_hdr.ch_dlc = msgdlc; +#ifdef CONFIG_CAN_EXTID + txmsg.cm_hdr.ch_extid = true; +#endif + + for (i = 0; i < msgdlc; i++) + { + txmsg.cm_data[i] = msgdata + i; + } + + /* Send the TX message */ + + msgsize = CAN_MSGLEN(msgdlc); + nbytes = write(fd, &txmsg, msgsize); + if (nbytes != msgsize) + { + message("ERROR: write(%d) returned %d\n", msgsize, nbytes); + errval = 3; + goto errout_with_dev; + } +#endif + +#ifdef CONFIG_EXAMPLES_CAN_WRITEONLY + message(" ID: %4d DLC: %d\n", msgid, msgdlc); +#endif + + /* Read the RX message */ + +#ifndef CONFIG_EXAMPLES_CAN_WRITEONLY + msgsize = sizeof(struct can_msg_s); + nbytes = read(fd, &rxmsg, msgsize); + if (nbytes < CAN_MSGLEN(0) || nbytes > msgsize) + { + message("ERROR: read(%d) returned %d\n", msgsize, nbytes); + errval = 4; + goto errout_with_dev; + } +#endif + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + message(" ID: %4d DLC: %d\n", rxmsg.cm_hdr.id, rxmsg.cm_hdr.dlc); +#endif + + /* Verify that the received messages are the same */ + +#ifdef CONFIG_EXAMPLES_CAN_READWRITE + if (memcmp(&txmsg.cm_hdr, &rxmsg.cm_hdr, sizeof(struct can_hdr_s)) != 0) + { + message("ERROR: Sent header does not match received header:\n"); + lib_dumpbuffer("Sent header", (FAR const uint8_t*)&txmsg.cm_hdr, + sizeof(struct can_hdr_s)); + lib_dumpbuffer("Received header", (FAR const uint8_t*)&rxmsg.cm_hdr, + sizeof(struct can_hdr_s)); + errval = 4; + goto errout_with_dev; + } + + if (memcmp(txmsg.cm_data, rxmsg.cm_data, msgdlc) != 0) + { + message("ERROR: Data does not match. DLC=%d\n", msgdlc); + for (i = 0; i < msgdlc; i++) + { + message(" %d: TX %02x RX %02x\n", i, txmsg.cm_data[i], rxmsg.cm_data[i]); + errval = 5; + goto errout_with_dev; + } + } + + /* Report success */ + + message(" ID: %4d DLC: %d -- OK\n", msgid, msgdlc); +#endif + + /* Set up for the next pass */ + +#ifndef CONFIG_EXAMPLES_CAN_READONLY + msgdata += msgdlc; + + if (++msgid >= MAX_ID) + { + msgid = 1; + } + + if (++msgdlc > CAN_MAXDATALEN) + { + msgdlc = 1; + } +#endif + } + +errout_with_dev: + close(fd); + +errout: + message("Terminating!\n"); + msgflush(); + return errval; +} diff --git a/apps/examples/cdcacm/.context b/apps/examples/cdcacm/.context new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/apps/examples/cdcacm/.context diff --git a/apps/examples/cdcacm/Kconfig b/apps/examples/cdcacm/Kconfig new file mode 100644 index 000000000..8cd9c6e99 --- /dev/null +++ b/apps/examples/cdcacm/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_CDCACM + bool "CAN example" + default n + ---help--- + Enable the USB CDC/ACM class driver example + +if EXAMPLES_CDCACM +endif + diff --git a/apps/examples/cdcacm/Makefile b/apps/examples/cdcacm/Makefile new file mode 100644 index 000000000..3fa886d56 --- /dev/null +++ b/apps/examples/cdcacm/Makefile @@ -0,0 +1,109 @@ +############################################################################ +# apps/examples/cdcacm/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 + +# USB CDC/ACM serial mass storage example + +ASRCS = +CSRCS = cdcacm_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 . + +# USB CDC/ACM built-in application info + +APPNAME1 = sercon +PRIORITY1 = SCHED_PRIORITY_DEFAULT +STACKSIZE1 = 2048 + +APPNAME2 = serdis +PRIORITY2 = SCHED_PRIORITY_DEFAULT +STACKSIZE2 = 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: + $(call REGISTER,$(APPNAME1),$(PRIORITY1),$(STACKSIZE1),$(APPNAME1)_main) + $(call REGISTER,$(APPNAME2),$(PRIORITY2),$(STACKSIZE2),$(APPNAME2)_main) + @touch $@ + +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 + diff --git a/apps/examples/cdcacm/cdcacm.h b/apps/examples/cdcacm/cdcacm.h new file mode 100644 index 000000000..18570bff0 --- /dev/null +++ b/apps/examples/cdcacm/cdcacm.h @@ -0,0 +1,165 @@ +/**************************************************************************** + * examples/cdcacm/cdcacm.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __EXAMPLES_CDCACM_CDCACM_H +#define __EXAMPLES_CDCACM_CDCACM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdlib.h> + +#include <nuttx/usb/usbdev_trace.h> + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Prerequisites */ + +#ifndef CONFIG_USBDEV +# error "CONFIG_USBDEV is not defined" +#endif + +#ifndef CONFIG_CDCACM +# error "CONFIG_CDCACM is not defined" +#endif + +#ifndef CONFIG_NSH_BUILTIN_APPS +# error "This example can only be built as an NSH built-in application" +#endif + +/* Default configuration values */ + +#ifndef CONFIG_EXAMPLES_CDCACM_DEVMINOR +# define CONFIG_EXAMPLES_CDCACM_DEVMINOR 0 +#endif + +/* Trace Configuration ******************************************************/ + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACEINIT +# define TRACE_INIT_BITS (TRACE_INIT_BIT) +#else +# define TRACE_INIT_BITS (0) +#endif + +#define TRACE_ERROR_BITS (TRACE_DEVERROR_BIT|TRACE_CLSERROR_BIT) + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACECLASS +# define TRACE_CLASS_BITS (TRACE_CLASS_BIT|TRACE_CLASSAPI_BIT|TRACE_CLASSSTATE_BIT) +#else +# define TRACE_CLASS_BITS (0) +#endif + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACETRANSFERS +# define TRACE_TRANSFER_BITS (TRACE_OUTREQQUEUED_BIT|TRACE_INREQQUEUED_BIT|TRACE_READ_BIT|\ + TRACE_WRITE_BIT|TRACE_COMPLETE_BIT) +#else +# define TRACE_TRANSFER_BITS (0) +#endif + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACECONTROLLER +# define TRACE_CONTROLLER_BITS (TRACE_EP_BIT|TRACE_DEV_BIT) +#else +# define TRACE_CONTROLLER_BITS (0) +#endif + +#ifdef CONFIG_EXAMPLES_CDCACM_TRACEINTERRUPTS +# define TRACE_INTERRUPT_BITS (TRACE_INTENTRY_BIT|TRACE_INTDECODE_BIT|TRACE_INTEXIT_BIT) +#else +# define TRACE_INTERRUPT_BITS (0) +#endif + +#define TRACE_BITSET (TRACE_INIT_BITS|TRACE_ERROR_BITS|TRACE_CLASS_BITS|\ + TRACE_TRANSFER_BITS|TRACE_CONTROLLER_BITS|TRACE_INTERRUPT_BITS) + +/* Debug ********************************************************************/ + +#ifdef CONFIG_CPP_HAVE_VARARGS +# ifdef CONFIG_DEBUG +# define message(...) lib_lowprintf(__VA_ARGS__) +# define msgflush() +# else +# define message(...) printf(__VA_ARGS__) +# define msgflush() fflush(stdout) +# endif +#else +# ifdef CONFIG_DEBUG +# define message lib_lowprintf +# define msgflush() +# else +# define message printf +# define msgflush() fflush(stdout) +# endif +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* All global variables used by this example are packed into a structure in + * order to avoid name collisions. + */ + +struct cdcacm_state_s +{ + /* This is the handle that references to this particular USB storage driver + * instance. It is only needed if the USB mass storage device example is + * built using CONFIG_NSH_BUILTIN_APPS. In this case, the value + * of the driver handle must be remembered between the 'sercon' and 'msdis' + * commands. + */ + + FAR void *handle; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* All global variables used by this example are packed into a structure in + * order to avoid name collisions. + */ + +extern struct cdcacm_state_s g_cdcacm; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#endif /* __EXAMPLES_CDCACM_CDCACM_H */ diff --git a/apps/examples/cdcacm/cdcacm_main.c b/apps/examples/cdcacm/cdcacm_main.c new file mode 100644 index 000000000..aeb7a9e74 --- /dev/null +++ b/apps/examples/cdcacm/cdcacm_main.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * examples/cdcacm/cdcacm_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 <stdio.h> +#include <debug.h> + +#include <nuttx/usb/usbdev.h> +#include <nuttx/usb/cdcacm.h> + +#include "cdcacm.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* All global variables used by this example are packed into a structure in + * order to avoid name collisions. + */ + +struct cdcacm_state_s g_cdcacm; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * sercon_main + * + * Description: + * This is the main program that configures the CDC/ACM serial device. + * + ****************************************************************************/ + +int sercon_main(int argc, char *argv[]) +{ + int ret; + + /* Check if there is a non-NULL USB mass storage device handle (meaning that the + * USB mass storage device is already configured). + */ + + if (g_cdcacm.handle) + { + message("sercon:: ERROR: Already connected\n"); + return EXIT_FAILURE; + } + + /* Then, in any event, enable trace data collection as configured BEFORE + * enabling the CDC/ACM device. + */ + + usbtrace_enable(TRACE_BITSET); + + /* Initialize the USB CDC/ACM serial driver */ + + message("sercon: Registering CDC/ACM serial driver\n"); + ret = cdcacm_initialize(CONFIG_EXAMPLES_CDCACM_DEVMINOR, &g_cdcacm.handle); + if (ret < 0) + { + message("sercon: ERROR: Failed to create the CDC/ACM serial device: %d\n", -ret); + return EXIT_FAILURE; + } + + message("sercon: Successfully registered the CDC/ACM serial driver\n"); + return EXIT_SUCCESS; +} + +/**************************************************************************** + * serdis_main + * + * Description: + * This is a program entry point that will disconnect the CDC/ACM serial + * device. + * + ****************************************************************************/ + +int serdis_main(int argc, char *argv[]) +{ + /* First check if the USB mass storage device is already connected */ + + if (!g_cdcacm.handle) + { + message("serdis: ERROR: Not connected\n"); + return EXIT_FAILURE; + } + + /* Then, in any event, disable trace data collection as configured BEFORE + * enabling the CDC/ACM device. + */ + + usbtrace_enable(0); + + /* Then disconnect the device and uninitialize the USB mass storage driver */ + + cdcacm_uninitialize(g_cdcacm.handle); + g_cdcacm.handle = NULL; + message("serdis: Disconnected\n"); + return EXIT_SUCCESS; +} diff --git a/apps/examples/hello/Kconfig b/apps/examples/hello/Kconfig new file mode 100644 index 000000000..d697daa8a --- /dev/null +++ b/apps/examples/hello/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_HELLO + bool "\"Hello, World!\" example" + default n + ---help--- + Enable the \"Hello, World!\" example + +if EXAMPLES_HELLO +endif diff --git a/apps/examples/hello/Makefile b/apps/examples/hello/Makefile new file mode 100644 index 000000000..9c3cda894 --- /dev/null +++ b/apps/examples/hello/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/hello/Makefile +# +# Copyright (C) 2008, 2010-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 + +# Hello, World! built-in application info + +APPNAME = hello +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Hello, World! Example + +ASRCS = +CSRCS = 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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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_EXAMPLES_HELLO_BUILTIN),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 diff --git a/apps/examples/hello/main.c b/apps/examples/hello/main.c new file mode 100644 index 000000000..7934dc34b --- /dev/null +++ b/apps/examples/hello/main.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * examples/hello/main.c + * + * Copyright (C) 2008, 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 + * 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 <stdio.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start/hello_main + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_HELLO_BUILTIN +# define MAIN_NAME hello_main +#else +# define MAIN_NAME user_start +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + printf("Hello, World!!\n"); + return 0; +} + diff --git a/apps/examples/helloxx/Kconfig b/apps/examples/helloxx/Kconfig new file mode 100644 index 000000000..336389d24 --- /dev/null +++ b/apps/examples/helloxx/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_HELLOXX + bool "\"Hello, World!\" C++ example" + default n + ---help--- + Enable the \"Hello, World!\" C++ example + +if EXAMPLES_HELLOXX +endif diff --git a/apps/examples/helloxx/Makefile b/apps/examples/helloxx/Makefile new file mode 100644 index 000000000..c34378d24 --- /dev/null +++ b/apps/examples/helloxx/Makefile @@ -0,0 +1,122 @@ +############################################################################ +# apps/examples/helloxx/Makefile +# +# Copyright (C) 2009-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# Hello, World! C++ Example + +ASRCS = +CSRCS = +CXXSRCS = main.cxx + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) +CXXOBJS = $(CXXSRCS:.cxx=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(CXXSRCS) +OBJS = $(AOBJS) $(COBJS) $(CXXOBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# helloxx built-in application info + +APPNAME = helloxx +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend disclean chkcxx + +chkcxx: +ifneq ($(CONFIG_HAVE_CXX),y) + @echo "" + @echo "In order to use this example, you toolchain must support must" + @echo "" + @echo " (1) Explicitly select CONFIG_HAVE_CXX to build in C++ support" + @echo " (2) Define CXX, CXXFLAGS, and COMPILEXX in the Make.defs file" + @echo " of the configuration that you are using." + @echo "" + @exit 1 +endif + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(CXXOBJS): %$(OBJEXT): %.cxx + $(call COMPILEXX, $<, $@) + +.built: chkcxx $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),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 diff --git a/apps/examples/helloxx/main.cxx b/apps/examples/helloxx/main.cxx new file mode 100644 index 000000000..8514fead2 --- /dev/null +++ b/apps/examples/helloxx/main.cxx @@ -0,0 +1,178 @@ +//*************************************************************************** +// examples/helloxx/main.cxx +// +// Copyright (C) 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 +// 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 <cstdio> +#include <debug.h> + +#include <nuttx/init.h> +#include <nuttx/arch.h> + +//*************************************************************************** +// Definitions +//*************************************************************************** +// Debug ******************************************************************** +// Non-standard debug that may be enabled just for testing the constructors + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_CXX +#endif + +#ifdef CONFIG_DEBUG_CXX +# define cxxdbg dbg +# define cxxlldbg lldbg +# ifdef CONFIG_DEBUG_VERBOSE +# define cxxvdbg vdbg +# define cxxllvdbg llvdbg +# else +# define cxxvdbg(x...) +# define cxxllvdbg(x...) +# endif +#else +# define cxxdbg(x...) +# define cxxlldbg(x...) +# define cxxvdbg(x...) +# define cxxllvdbg(x...) +#endif + +//*************************************************************************** +// Private Classes +//*************************************************************************** + +class CHelloWorld +{ + public: + CHelloWorld(void) : mSecret(42) + { + cxxdbg("Constructor: mSecret=%d\n", mSecret); + } + + ~CHelloWorld(void) + { + cxxdbg("Destructor\n"); + } + + bool HelloWorld(void) + { + cxxdbg("HelloWorld: mSecret=%d\n", mSecret); + + if (mSecret != 42) + { + printf("CHelloWorld::HelloWorld: CONSTRUCTION FAILED!\n"); + return false; + } + else + { + printf("CHelloWorld::HelloWorld: Hello, World!!\n"); + return true; + } + } + + private: + int mSecret; +}; + +//*************************************************************************** +// Private Data +//*************************************************************************** + +// Define a statically constructed CHellowWorld instance if C++ static +// initializers are supported by the platform + +#ifdef CONFIG_HAVE_CXXINITIALIZE +static CHelloWorld g_HelloWorld; +#endif + +//*************************************************************************** +// Public Functions +//*************************************************************************** + +//*************************************************************************** +// user_start +//*************************************************************************** + +/**************************************************************************** + * Name: user_start/nxhello_main + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_HELLOXX_BUILTIN +extern "C" int helloxx_main(int argc, char *argv[]); +# define MAIN_NAME helloxx_main +# define MAIN_STRING "helloxx_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + // If C++ initialization for static constructors is supported, then do + // that first + +#ifdef CONFIG_HAVE_CXXINITIALIZE + up_cxxinitialize(); +#endif + + // Exercise an explictly instantiated C++ object + + CHelloWorld *pHelloWorld = new CHelloWorld; + printf(MAIN_STRING "Saying hello from the dynamically constructed instance\n"); + pHelloWorld->HelloWorld(); + + // Exercise an C++ object instantiated on the stack + +#ifndef CONFIG_EXAMPLES_HELLOXX_NOSTACKCONST + CHelloWorld HelloWorld; + + printf(MAIN_STRING "Saying hello from the instance constructed on the stack\n"); + HelloWorld.HelloWorld(); +#endif + + // Exercise an statically constructed C++ object + +#ifdef CONFIG_HAVE_CXXINITIALIZE + printf(MAIN_STRING "Saying hello from the statically constructed instance\n"); + g_HelloWorld.HelloWorld(); +#endif + + delete pHelloWorld; + return 0; +} + diff --git a/apps/examples/lcdrw/Kconfig b/apps/examples/lcdrw/Kconfig new file mode 100644 index 000000000..2308ddc60 --- /dev/null +++ b/apps/examples/lcdrw/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_LCDRW + bool "LCD read/write example" + default n + ---help--- + Enable the LCD read/write example + +if EXAMPLES_LCDRW +endif diff --git a/apps/examples/lcdrw/Makefile b/apps/examples/lcdrw/Makefile new file mode 100644 index 000000000..053c62670 --- /dev/null +++ b/apps/examples/lcdrw/Makefile @@ -0,0 +1,105 @@ +############################################################################ +# apps/examples/lcdrw/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# LCD Read/Write Test + +ASRCS = +CSRCS = lcdrw_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 . + +# LCD R/W built-in application info + +APPNAME = lcdrw +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Common build + +VPATH = + +all: .built +.PHONY: 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_EXAMPLES_LCDRW_BUILTIN),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 diff --git a/apps/examples/lcdrw/lcdrw_main.c b/apps/examples/lcdrw/lcdrw_main.c new file mode 100644 index 000000000..c366743f4 --- /dev/null +++ b/apps/examples/lcdrw/lcdrw_main.c @@ -0,0 +1,259 @@ +/**************************************************************************** + * examples/lcdrw/lcdrw_main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <stdlib.h> + +#include <nuttx/lcd/lcd.h> +#include <nuttx/nx/nxglib.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* Most of the NX configuration settings are probbably *not* needed by this + * example. But, presumeably you are using NX too and so the checks might + * be good for you. + */ + +#ifndef CONFIG_NX +# error "CONFIG_NX must be defined to use this test" +#endif + +#ifndef CONFIG_NX_LCDDRIVER +# error "CONFIG_NX_LCDDRIVER must be defined to use this test" +#endif + +#ifndef CONFIG_EXAMPLES_LCDRW_BPP +# define CONFIG_EXAMPLES_LCDRW_BPP 16 +#endif + +#if CONFIG_EXAMPLES_LCDRW_BPP != 16 +# error "Currently only RGB565 is supported -- feel free to extend" +#endif + +#ifdef CONFIG_NX_DISABLE_16BPP +# error "CONFIG_NX_DISABLE_16BPP disables 16-bit support" +#endif + +#ifndef CONFIG_EXAMPLES_LDCRW_DEVNO +# define CONFIG_EXAMPLES_LDCRW_DEVNO 0 +#endif + +#ifndef CONFIG_EXAMPLES_LDCRW_XRES +# define CONFIG_EXAMPLES_LDCRW_XRES 240 +#endif + +#ifndef CONFIG_EXAMPLES_LDCRW_YRES +# define CONFIG_EXAMPLES_LDCRW_YRES 320 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct lcdrw_instance_s +{ + /* LCD device handle and planeinfo */ + + FAR struct lcd_dev_s *dev; + struct lcd_planeinfo_s pinfo; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: lcdrw_initialize + ****************************************************************************/ + +static inline int lcdrw_initialize(FAR struct lcdrw_instance_s *inst) +{ + int ret; + + /* Initialize the LCD device */ + + printf("screens_initialize: Initializing LCD\n"); + ret = up_lcdinitialize(); + if (ret < 0) + { + fprintf(stderr, "screens_initialize: up_lcdinitialize failed: %d\n", -ret); + return ret; + } + + /* Get the device instance. */ + + printf("Get LCD instance\n"); + inst->dev = up_lcdgetdev(CONFIG_EXAMPLES_LDCRW_DEVNO); + if (!inst->dev) + { + fprintf(stderr, "up_lcdgetdev failed, devno=%d\n", CONFIG_EXAMPLES_LDCRW_DEVNO); + return ret; + } + + /* Turn the LCD on at 75% power. This should not be necessary. */ + + (void)inst->dev->setpower(inst->dev, ((3*CONFIG_LCD_MAXPOWER + 3)/4)); + + /* Get the planeinfo structure */ + + ret = inst->dev->getplaneinfo(inst->dev, 0, &inst->pinfo); + if (ret < 0) + { + fprintf(stderr, "getplaneinfo failed: %d\n", ret); + } + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lcdrw_main/user_start + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_LCDRW_BUILTIN +# define MAIN_NAME lcdrw_main +#else +# define MAIN_NAME user_start +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + struct lcdrw_instance_s inst; + nxgl_coord_t row; + nxgl_coord_t col; + uint16_t value; + uint32_t offset; + FAR uint16_t *ptr; + int ret; + + /* Initialize the LCD driver */ + + ret = lcdrw_initialize(&inst); + if (ret < 0) + { + exit(1); + } + + /* Loop, writing all possible values to the LCD */ + + value = 0; + for (row = 0; row < CONFIG_EXAMPLES_LDCRW_YRES; row++) + { + /* Create a dummy row. The important thing is to try all + * bit combinations in a predictable way. + */ + + ptr = (FAR uint16_t*)inst.pinfo.buffer; + for (col = 0; col < CONFIG_EXAMPLES_LDCRW_XRES; col++) + { + *ptr++ = value++; + } + + /* Write the row to the LCD */ + + ret = inst.pinfo.putrun(row, 0, inst.pinfo.buffer, + CONFIG_EXAMPLES_LDCRW_XRES); + if (ret < 0) + { + fprintf(stderr, "putrun failed: %d\n", ret); + exit(1); + } + } + + /* Print a header */ + + printf(" "); + for (col = 0; col < 15; col++) + { + printf("---%x ", col); + } + printf("---f\n"); + + /* Then read each line back from the LCD. */ + + offset = 0; + for (row = 0; row < CONFIG_EXAMPLES_LDCRW_YRES; row++) + { + /* Read the row */ + + ret = inst.pinfo.getrun(row, 0, inst.pinfo.buffer, + CONFIG_EXAMPLES_LDCRW_XRES); + if (ret < 0) + { + fprintf(stderr, "getrun failed: %d\n", ret); + exit(1); + } + + /* Then dump the row to the display */ + + ptr = (FAR uint16_t*)inst.pinfo.buffer; + for (col = 0; col < CONFIG_EXAMPLES_LDCRW_XRES; col++) + { + if ((offset & 15) == 0) + { + printf("%06x ", offset); + } + + value = *ptr++; + offset++; + + if ((offset & 15) == 0) + { + printf("%04x\n", value); + } + else + { + printf("%04x ", value); + } + } + } + fflush(stdout); + + return 0; +} + diff --git a/apps/examples/mm/Kconfig b/apps/examples/mm/Kconfig new file mode 100644 index 000000000..81ce4c453 --- /dev/null +++ b/apps/examples/mm/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_MM + bool "Memory management example" + default n + ---help--- + Enable the memory management example + +if EXAMPLES_MM +endif diff --git a/apps/examples/mm/Makefile b/apps/examples/mm/Makefile new file mode 100644 index 000000000..e5d9ffb4c --- /dev/null +++ b/apps/examples/mm/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/examples/mm/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# Memory Management Test + +ASRCS = +CSRCS = mm_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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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: + +.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 diff --git a/apps/examples/mm/mm_main.c b/apps/examples/mm/mm_main.c new file mode 100644 index 000000000..036c39047 --- /dev/null +++ b/apps/examples/mm/mm_main.c @@ -0,0 +1,300 @@ +/**************************************************************************** + * examples/mm/mm_main.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NTEST_ALLOCS 32 + +/* #define STOP_ON_ERRORS do{}while(0) */ +#define STOP_ON_ERRORS exit(1) + +/* All other definitions derive from these two */ + +#define MM_MIN_SHIFT 4 /* 16 bytes */ +#define MM_MIN_CHUNK (1 << MM_MIN_SHIFT) +#define MM_GRAN_MASK (MM_MIN_CHUNK-1) +#define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK) +#define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK) + +#ifdef CONFIG_SMALL_MEMORY +# define SIZEOF_MM_ALLOCNODE 4 +#else +# define SIZEOF_MM_ALLOCNODE 8 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* Test allocations */ + +static const int alloc_sizes[NTEST_ALLOCS] = +{ + 1024, 12, 962, 5692, 10254, 111, 9932, 601, + 222, 2746, 3, 124321, 68, 776, 6750, 852, + 4732, 28, 901, 480, 5011, 1536, 2011, 81647, + 646, 1646, 69179, 194, 2590, 7, 969, 70 +}; + +static const int realloc_sizes[NTEST_ALLOCS] = +{ + 18, 3088, 963, 123, 511, 11666, 3723, 42, + 9374, 1990, 1412, 6, 592, 4088, 11, 5040, + 8663, 91255, 28, 4346, 9172, 168, 229, 4734, + 59139, 221, 7830, 30421, 1666, 4, 812, 416 +}; + +static const int random1[NTEST_ALLOCS] = +{ + 20, 11, 3, 31, 9, 29, 7, 17, + 21, 2, 26, 18, 14, 25, 0, 10, + 27, 19, 22, 28, 8, 30, 12, 15, + 4, 1, 24, 6, 16, 13, 5, 23 +}; + +static const int random2[NTEST_ALLOCS] = +{ + 2, 19, 12, 23, 30, 11, 27, 4, + 20, 7, 0, 16, 28, 15, 5, 24, + 10, 17, 25, 31, 8, 29, 3, 26, + 9, 18, 22, 13, 1, 21, 14, 6 +}; + +static const int random3[NTEST_ALLOCS] = +{ + 8, 17, 3, 18, 26, 23, 30, 11, + 12, 22, 4, 20, 25, 10, 27, 1, + 29, 14, 19, 21, 0, 31, 7, 24, + 9, 15, 2, 28, 16, 6, 13, 5 +}; + +static const int alignment[NTEST_ALLOCS/2] = +{ + 128, 2048, 131072, 8192, 32, 32768, 16384 , 262144, + 512, 4096, 65536, 8, 64, 1024, 16, 4 +}; + +static void *allocs[NTEST_ALLOCS]; +static struct mallinfo alloc_info; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void mm_showmallinfo(void) +{ + alloc_info = mallinfo(); + printf(" mallinfo:\n"); + printf(" Total space allocated from system = %ld\n", + alloc_info.arena); + printf(" Number of non-inuse chunks = %ld\n", + alloc_info.ordblks); + printf(" Largest non-inuse chunk = %ld\n", + alloc_info.mxordblk); + printf(" Total allocated space = %ld\n", + alloc_info.uordblks); + printf(" Total non-inuse space = %ld\n", + alloc_info.fordblks); +} + +static void do_mallocs(void **mem, const int *size, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + if (!mem[j]) + { + printf("(%d)Allocating %d bytes\n", i, size[j]); + mem[j] = malloc(size[j]); + printf("(%d)Memory allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE); + fprintf(stderr, "(%d)malloc failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0xAA, size[j]); + } + + mm_showmallinfo(); + } + } +} + +static void do_reallocs(void **mem, const int *oldsize, const int *newsize, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + printf("(%d)Re-allocating at %p from %d to %d bytes\n", + i, mem[j], oldsize[j], newsize[j]); + mem[j] = realloc(mem[j], newsize[j]); + printf("(%d)Memory re-allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(newsize[j] + SIZEOF_MM_ALLOCNODE); + fprintf(stderr, "(%d)realloc failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0x55, newsize[j]); + } + + mm_showmallinfo(); + } +} + +static void do_memaligns(void **mem, const int *size, const int *align, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + printf("(%d)Allocating %d bytes aligned to 0x%08x\n", + i, size[j], align[i]); + mem[j] = memalign(align[i], size[j]); + printf("(%d)Memory allocated at %p\n", i, mem[j]); + if (mem[j] == NULL) + { + int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE) + 2*align[i]; + fprintf(stderr, "(%d)memalign failed for allocsize=%d\n", i, allocsize); + if (allocsize > alloc_info.mxordblk) + { + fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk); + } + else + { + fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk); + exit(1); + } + } + else + { + memset(mem[j], 0x33, size[j]); + } + + mm_showmallinfo(); + } +} + +static void do_frees(void **mem, const int *size, const int *seq, int n) +{ + int i; + int j; + + for (i = 0; i < n; i++) + { + j = seq[i]; + printf("(%d)Releasing memory at %p (size=%d bytes)\n", + i, mem[j], size[j]); + free(mem[j]); + mem[j] = NULL; + + mm_showmallinfo(); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + mm_showmallinfo(); + + /* Allocate some memory */ + + do_mallocs(allocs, alloc_sizes, random1, NTEST_ALLOCS); + + /* Re-allocate the memory */ + + do_reallocs(allocs, alloc_sizes, realloc_sizes, random2, NTEST_ALLOCS); + + /* Release the memory */ + + do_frees(allocs, realloc_sizes, random3, NTEST_ALLOCS); + + /* Allocate aligned memory */ + + do_memaligns(allocs, alloc_sizes, alignment, random2, NTEST_ALLOCS/2); + do_memaligns(allocs, alloc_sizes, alignment, &random2[NTEST_ALLOCS/2], NTEST_ALLOCS/2); + + /* Release aligned memory */ + + do_frees(allocs, alloc_sizes, random1, NTEST_ALLOCS); + + printf("TEST COMPLETE\n"); + return 0; +} diff --git a/apps/examples/mount/Kconfig b/apps/examples/mount/Kconfig new file mode 100644 index 000000000..b38c4763c --- /dev/null +++ b/apps/examples/mount/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_MOUNT + bool "File system mount example" + default n + ---help--- + Enable the file system mount example + +if EXAMPLES_MOUNT +endif diff --git a/apps/examples/mount/Makefile b/apps/examples/mount/Makefile new file mode 100644 index 000000000..7e48ea44a --- /dev/null +++ b/apps/examples/mount/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/Makefile +# +# Copyright (C) 2007-2008, 2010-2010 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# mount() test + +ASRCS = +CSRCS = mount_main.c ramdisk.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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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: + +.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 diff --git a/apps/examples/mount/mount.h b/apps/examples/mount/mount.h new file mode 100644 index 000000000..68a03674d --- /dev/null +++ b/apps/examples/mount/mount.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * examples/mount/mount.h + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 __EXAMPLES_MOUNT_MOUNT_H +#define __EXAMPLES_MOUNT_MOUNT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configure the test */ + +#if defined(CONFIG_EXAMPLES_MOUNT_DEVNAME) +# if !defined(CONFIG_FS_WRITABLE) +# error "Writable filesystem required in this configuration" +# endif +# undef CONFIG_EXAMPLES_MOUNT_NSECTORS +# undef CONFIG_EXAMPLES_MOUNT_SECTORSIZE +# undef CONFIG_EXAMPLES_MOUNT_RAMDEVNO +# define MOUNT_DEVNAME CONFIG_EXAMPLES_MOUNT_DEVNAME +#else +# if !defined(CONFIG_FS_FAT) +# error "CONFIG_FS_FAT required in this configuration" +# endif +# if !defined(CONFIG_EXAMPLES_MOUNT_SECTORSIZE) +# define CONFIG_EXAMPLES_MOUNT_SECTORSIZE 512 +# endif +# if !defined(CONFIG_EXAMPLES_MOUNT_NSECTORS) +# define CONFIG_EXAMPLES_MOUNT_NSECTORS 2048 +# endif +# if !defined(CONFIG_EXAMPLES_MOUNT_RAMDEVNO) +# define CONFIG_EXAMPLES_MOUNT_RAMDEVNO 0 +# endif +# define STR_RAMDEVNO(m) #m +# define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m) +# define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_EXAMPLES_MOUNT_RAMDEVNO) +#endif + + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +extern const char g_source[]; /* Mount 'source' path */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_EXAMPLES_MOUNT_DEVNAME +extern int create_ramdisk(void); +#endif + +#endif /* __EXAMPLES_MOUNT_MOUNT_H */ diff --git a/apps/examples/mount/mount_main.c b/apps/examples/mount/mount_main.c new file mode 100644 index 000000000..00070b94c --- /dev/null +++ b/apps/examples/mount/mount_main.c @@ -0,0 +1,754 @@ +/**************************************************************************** + * examples/mount/mount_main.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <sys/mount.h> +#include <sys/stat.h> +#include <sys/statfs.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> + +#include "mount.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define TEST_USE_STAT 1 +#define TEST_SHOW_DIRECTORIES 1 +#define TEST_USE_STATFS 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_mntdir[] = "/mnt"; +static const char g_target[] = "/mnt/fs"; +static const char g_filesystemtype[] = "vfat"; + +static const char g_testdir1[] = "/mnt/fs/TestDir"; +static const char g_testdir2[] = "/mnt/fs/NewDir1"; +static const char g_testdir3[] = "/mnt/fs/NewDir2"; +static const char g_testdir4[] = "/mnt/fs/NewDir3"; +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME +static const char g_testfile1[] = "/mnt/fs/TestDir/TestFile.txt"; +#endif +static const char g_testfile2[] = "/mnt/fs/TestDir/WrTest1.txt"; +static const char g_testfile3[] = "/mnt/fs/NewDir1/WrTest2.txt"; +static const char g_testfile4[] = "/mnt/fs/NewDir3/Renamed.txt"; +static const char g_testmsg[] = "This is a write test"; + +static int g_nerrors = 0; + +static char g_namebuffer[256]; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + + const char g_source[] = MOUNT_DEVNAME; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef TEST_USE_STAT +static void show_stat(const char *path, struct stat *ps) +{ + printf("%s stat:\n", path); + printf("\tmode : %08x\n", ps->st_mode); + if (S_ISREG(ps->st_mode)) + { + printf("\ttype : File\n"); + } + else if (S_ISDIR(ps->st_mode)) + { + printf("\ttype : Directory\n"); + } + else if (S_ISCHR(ps->st_mode)) + { + printf("\ttype : Character driver\n"); + } + else if (S_ISBLK(ps->st_mode)) + { + printf("\ttype : Block driver\n"); + } + else + { + printf("\ttype : Unknown\n"); + } + + printf("\tsize : %d (bytes)\n", ps->st_size); + printf("\tblock size : %d (bytes)\n", ps->st_blksize); + printf("\tsize : %d (blocks)\n", ps->st_blocks); + printf("\taccess time : %d\n", ps->st_atime); + printf("\tmodify time : %d\n", ps->st_mtime); + printf("\tchange time : %d\n", ps->st_ctime); +} +#endif + +/**************************************************************************** + * Name: show_statfs + ****************************************************************************/ + +#ifdef TEST_USE_STATFS +static void show_statfs(const char *path) +{ + struct statfs buf; + int ret; + + /* Try stat() against a file or directory. It should fail with expectederror */ + + printf("show_statfs: Try statfs(%s)\n", path); + ret = statfs(path, &buf); + if (ret == 0) + { + printf("show_statfs: statfs(%s) succeeded\n", path); + printf("\tFS Type : %0x\n", buf.f_type); + printf("\tBlock size : %d\n", buf.f_bsize); + printf("\tNumber of blocks : %d\n", buf.f_blocks); + printf("\tFree blocks : %d\n", buf.f_bfree); + printf("\tFree user blocks : %d\n", buf.f_bavail); + printf("\tNumber file nodes : %d\n", buf.f_files); + printf("\tFree file nodes : %d\n", buf.f_ffree); + printf("\tFile name length : %d\n", buf.f_namelen); + } + else + { + printf("show_statfs: ERROR statfs(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} +#else +# define show_statfs(p) +#endif + +/**************************************************************************** + * Name: show_directories + ****************************************************************************/ + +#ifdef TEST_SHOW_DIRECTORIES +static void show_directories(const char *path, int indent) +{ + DIR *dirp; + struct dirent *direntry; + int i; + + dirp = opendir(path); + if ( !dirp ) + { + printf("show_directories: ERROR opendir(\"%s\") failed with errno=%d\n", + path, errno); + g_nerrors++; + return; + } + + for (direntry = readdir(dirp); direntry; direntry = readdir(dirp)) + { + for (i = 0; i < 2*indent; i++) + { + putchar(' '); + } + if (DIRENT_ISDIRECTORY(direntry->d_type)) + { + char *subdir; + printf("%s/\n", direntry->d_name); + sprintf(g_namebuffer, "%s/%s", path, direntry->d_name); + subdir = strdup(g_namebuffer); + show_directories( subdir, indent + 1); + free(subdir); + } + else + { + printf("%s\n", direntry->d_name); + } + } + + closedir(dirp); +} +#else +# define show_directories(p,i) +#endif + +/**************************************************************************** + * Name: fail_read_open + ****************************************************************************/ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME +static void fail_read_open(const char *path, int expectederror) +{ + int fd; + + printf("fail_read_open: Try open(%s) for reading\n", path); + + fd = open(path, O_RDONLY); + if (fd >= 0) + { + printf("fail_read_open: ERROR open(%s) succeeded\n", path); + g_nerrors++; + close(fd); + } + else if (errno != expectederror) + { + printf("fail_read_open: ERROR open(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} +#endif + +/**************************************************************************** + * Name: read_test_file + ****************************************************************************/ + +static void read_test_file(const char *path) +{ + char buffer[128]; + int nbytes; + int fd; + + /* Read a test file that is already on the test file system image */ + + printf("read_test_file: opening %s for reading\n", path); + + fd = open(path, O_RDONLY); + if (fd < 0) + { + printf("read_test_file: ERROR failed to open %s, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + memset(buffer, 0, 128); + nbytes = read(fd, buffer, 128); + if (nbytes < 0) + { + printf("read_test_file: ERROR failed to read from %s, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + buffer[127]='\0'; + printf("read_test_file: Read \"%s\" from %s\n", buffer, path); + } + close(fd); + } +} + +/**************************************************************************** + * Name: write_test_file + ****************************************************************************/ + +static void write_test_file(const char *path) +{ + int fd; + + /* Write a test file into a pre-existing file on the test file system */ + + printf("write_test_file: opening %s for writing\n", path); + + fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0) + { + printf("write_test_file: ERROR failed to open %s for writing, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + int nbytes = write(fd, g_testmsg, strlen(g_testmsg)); + if (nbytes < 0) + { + printf("write_test_file: ERROR failed to write to %s, errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + printf("write_test_file: wrote %d bytes to %s\n", nbytes, path); + } + close(fd); + } +} + +/**************************************************************************** + * Name: fail_mkdir + ****************************************************************************/ + +static void fail_mkdir(const char *path, int expectederror) +{ + int ret; + + /* Try mkdir() against a file or directory. It should fail with expectederror */ + + printf("fail_mkdir: Try mkdir(%s)\n", path); + + ret = mkdir(path, 0666); + if (ret == 0) + { + printf("fail_mkdir: ERROR mkdir(%s) succeeded\n", path); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_mkdir: ERROR mkdir(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_mkdir + ****************************************************************************/ + +static void succeed_mkdir(const char *path) +{ + int ret; + + printf("succeed_mkdir: Try mkdir(%s)\n", path); + + ret = mkdir(path, 0666); + if (ret != 0) + { + printf("succeed_mkdir: ERROR mkdir(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_rmdir + ****************************************************************************/ + +static void fail_rmdir(const char *path, int expectederror) +{ + int ret; + + /* Try rmdir() against a file or directory. It should fail with expectederror */ + + printf("fail_rmdir: Try rmdir(%s)\n", path); + + ret = rmdir(path); + if (ret == 0) + { + printf("fail_rmdir: ERROR rmdir(%s) succeeded\n", path); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_rmdir: ERROR rmdir(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_rmdir + ****************************************************************************/ + +static void succeed_rmdir(const char *path) +{ + int ret; + + printf("succeed_rmdir: Try rmdir(%s)\n", path); + + ret = rmdir(path); + if (ret != 0) + { + printf("succeed_rmdir: ERROR rmdir(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_unlink + ****************************************************************************/ + +static void fail_unlink(const char *path, int expectederror) +{ + int ret; + + /* Try unlink() against a file or directory. It should fail with expectederror */ + + printf("fail_unlink: Try unlink(%s)\n", path); + + ret = unlink(path); + if (ret == 0) + { + printf("fail_unlink: ERROR unlink(%s) succeeded\n", path); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_unlink: ERROR unlink(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_unlink + ****************************************************************************/ + +static void succeed_unlink(const char *path) +{ + int ret; + + /* Try unlink() against the test file. It should succeed. */ + + printf("succeed_unlink: Try unlink(%s)\n", path); + + ret = unlink(path); + if (ret != 0) + { + printf("succeed_unlink: ERROR unlink(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_rename + ****************************************************************************/ + +static void fail_rename(const char *oldpath, const char *newpath, int expectederror) +{ + int ret; + + /* Try rename() against a file or directory. It should fail with expectederror */ + + printf("fail_rename: Try rename(%s->%s)\n", oldpath, newpath); + + ret = rename(oldpath, newpath); + if (ret == 0) + { + printf("fail_rename: ERROR rename(%s->%s) succeeded\n", + oldpath, newpath); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_rename: ERROR rename(%s->%s) failed with errno=%d (expected %d)\n", + oldpath, newpath, errno, expectederror); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: succeed_rename + ****************************************************************************/ + +static void succeed_rename(const char *oldpath, const char *newpath) +{ + int ret; + + printf("succeed_rename: Try rename(%s->%s)\n", oldpath, newpath); + + ret = rename(oldpath, newpath); + if (ret != 0) + { + printf("succeed_rename: ERROR rename(%s->%s) failed with errno=%d\n", + oldpath, newpath, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: fail_stat + ****************************************************************************/ + +#ifdef TEST_USE_STAT +static void fail_stat(const char *path, int expectederror) +{ + struct stat buf; + int ret; + + /* Try stat() against a file or directory. It should fail with expectederror */ + + printf("fail_stat: Try stat(%s)\n", path); + + ret = stat(path, &buf); + if (ret == 0) + { + printf("fail_stat: ERROR stat(%s) succeeded\n", path); + show_stat(path, &buf); + g_nerrors++; + } + else if (errno != expectederror) + { + printf("fail_stat: ERROR stat(%s) failed with errno=%d (expected %d)\n", + path, errno, expectederror); + g_nerrors++; + } +} +#else +# define fail_stat(p,e); +#endif + +/**************************************************************************** + * Name: succeed_stat + ****************************************************************************/ + +#ifdef TEST_USE_STAT +static void succeed_stat(const char *path) +{ + struct stat buf; + int ret; + + printf("succeed_stat: Try stat(%s)\n", path); + + ret = stat(path, &buf); + if (ret != 0) + { + printf("succeed_stat: ERROR stat(%s) failed with errno=%d\n", + path, errno); + g_nerrors++; + } + else + { + printf("succeed_stat: stat(%s) succeeded\n", path); + show_stat(path, &buf); + } +} +#else +#define succeed_stat(p) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int ret; + +#ifndef CONFIG_EXAMPLES_MOUNT_DEVNAME + /* Create a RAM disk for the test */ + + ret = create_ramdisk(); + if (ret < 0) + { + printf("user_start: ERROR failed to create RAM disk\n"); + return 1; + } +#endif + + /* Mount the test file system (see arch/sim/src/up_deviceimage.c */ + + printf("user_start: mounting %s filesystem at target=%s with source=%s\n", + g_filesystemtype, g_target, g_source); + + ret = mount(g_source, g_target, g_filesystemtype, 0, NULL); + printf("user_start: mount() returned %d\n", ret); + + if (ret == 0) + { + show_statfs(g_mntdir); + show_statfs(g_target); + +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + /* Read a test file that is already on the test file system image */ + + show_directories("", 0); + succeed_stat(g_testfile1); + show_statfs(g_testfile1); + read_test_file(g_testfile1); +#else + /* Create the test directory that would have been on the canned filesystem */ + + succeed_mkdir(g_testdir1); + show_directories("", 0); + succeed_stat(g_testdir1); + show_statfs(g_testdir1); +#endif + + /* Write a test file into a pre-existing directory on the test file system */ + + fail_stat(g_testfile2, ENOENT); + write_test_file(g_testfile2); + show_directories("", 0); + succeed_stat(g_testfile2); + show_statfs(g_testfile2); + + /* Read the file that we just wrote */ + + read_test_file(g_testfile2); + + /* Try rmdir() against a file on the directory. It should fail with ENOTDIR */ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + fail_rmdir(g_testfile1, ENOTDIR); +#endif + + /* Try rmdir() against the test directory. It should fail with ENOTEMPTY */ + + fail_rmdir(g_testdir1, ENOTEMPTY); + + /* Try unlink() against the test directory. It should fail with EISDIR */ + + fail_unlink(g_testdir1, EISDIR); + + /* Try unlink() against the test file1. It should succeed. */ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + succeed_unlink(g_testfile1); + fail_stat(g_testfile1, ENOENT); + show_directories("", 0); +#endif + + /* Attempt to open testfile1 should fail with ENOENT */ +#ifdef CONFIG_EXAMPLES_MOUNT_DEVNAME + fail_read_open(g_testfile1, ENOENT); +#endif + /* Try rmdir() against the test directory. It should still fail with ENOTEMPTY */ + + fail_rmdir(g_testdir1, ENOTEMPTY); + + /* Try mkdir() against the test file2. It should fail with EEXIST. */ + + fail_mkdir(g_testfile2, EEXIST); + + /* Try unlink() against the test file2. It should succeed. */ + + succeed_unlink(g_testfile2); + show_directories("", 0); + fail_stat(g_testfile2, ENOENT); + + /* Try mkdir() against the test dir1. It should fail with EEXIST. */ + + fail_mkdir(g_testdir1, EEXIST); + + /* Try rmdir() against the test directory. mkdir should now succeed. */ + + succeed_rmdir(g_testdir1); + show_directories("", 0); + fail_stat(g_testdir1, ENOENT); + + /* Try mkdir() against the test dir2. It should succeed */ + + succeed_mkdir(g_testdir2); + show_directories("", 0); + succeed_stat(g_testdir2); + show_statfs(g_testdir2); + + /* Try mkdir() against the test dir2. It should fail with EXIST */ + + fail_mkdir(g_testdir2, EEXIST); + + /* Write a test file into a new directory on the test file system */ + + fail_stat(g_testfile3, ENOENT); + write_test_file(g_testfile3); + show_directories("", 0); + succeed_stat(g_testfile3); + show_statfs(g_testfile3); + + /* Read the file that we just wrote */ + + read_test_file(g_testfile3); + + /* Use mkdir() to create test dir3. It should succeed */ + + fail_stat(g_testdir3, ENOENT); + succeed_mkdir(g_testdir3); + show_directories("", 0); + succeed_stat(g_testdir3); + show_statfs(g_testdir3); + + /* Try rename() on the root directory. Should fail with EXDEV*/ + + fail_rename(g_target, g_testdir4, EXDEV); + + /* Try rename() to an existing directory. Should fail with EEXIST */ + + fail_rename(g_testdir2, g_testdir3, EEXIST); + + /* Try rename() to a non-existing directory. Should succeed */ + + fail_stat(g_testdir4, ENOENT); + succeed_rename(g_testdir3, g_testdir4); + show_directories("", 0); + fail_stat(g_testdir3, ENOENT); + succeed_stat(g_testdir4); + show_statfs(g_testdir4); + + /* Try rename() of file. Should work. */ + + fail_stat(g_testfile4, ENOENT); + succeed_rename(g_testfile3, g_testfile4); + show_directories("", 0); + fail_stat(g_testfile3, ENOENT); + succeed_stat(g_testfile4); + show_statfs(g_testfile4); + + /* Make sure that we can still read the renamed file */ + + read_test_file(g_testfile4); + + /* Unmount the file system */ + + printf("user_start: Try unmount(%s)\n", g_target); + + ret = umount(g_target); + if (ret != 0) + { + printf("user_start: ERROR umount() failed, errno %d\n", errno); + g_nerrors++; + } + + printf("user_start: %d errors reported\n", g_nerrors); + } + + fflush(stdout); + return 0; +} diff --git a/apps/examples/mount/ramdisk.c b/apps/examples/mount/ramdisk.c new file mode 100644 index 000000000..9688580c0 --- /dev/null +++ b/apps/examples/mount/ramdisk.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * examples/mount/ramdisk.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <nuttx/ramdisk.h> +#include <nuttx/fs/mkfatfs.h> + +#include "mount.h" + +#ifndef CONFIG_EXAMPLES_MOUNT_DEVNAME + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +#define BUFFER_SIZE (CONFIG_EXAMPLES_MOUNT_NSECTORS*CONFIG_EXAMPLES_MOUNT_SECTORSIZE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct fat_format_s g_fmt = FAT_FORMAT_INITIALIZER; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: create_ramdisk + * + * Description: + * Create a RAM disk of the specified size formatting with a FAT file + * system + * + * Input Parameters: + * None + * + * Return: + * Zero on success, a negated errno on failure. + * + ****************************************************************************/ + +int create_ramdisk(void) +{ + char *pbuffer; + int ret; + + /* Allocate a buffer to hold the file system image. */ + + pbuffer = (char*)malloc(BUFFER_SIZE); + if (!pbuffer) + { + printf("create_ramdisk: Failed to allocate ramdisk of size %d\n", + BUFFER_SIZE); + return -ENOMEM; + } + + /* Register a RAMDISK device to manage this RAM image */ + + ret = ramdisk_register(CONFIG_EXAMPLES_MOUNT_RAMDEVNO, + pbuffer, + CONFIG_EXAMPLES_MOUNT_NSECTORS, + CONFIG_EXAMPLES_MOUNT_SECTORSIZE, + true); + if (ret < 0) + { + printf("create_ramdisk: Failed to register ramdisk at %s: %d\n", + g_source, -ret); + free(pbuffer); + return ret; + } + + /* Create a FAT filesystem on the ramdisk */ + + ret = mkfatfs(g_source, &g_fmt); + if (ret < 0) + { + printf("create_ramdisk: Failed to create FAT filesystem on ramdisk at %s\n", + g_source); + /* free(pbuffer); -- RAM disk is registered */ + return ret; + } + + return 0; +} +#endif /* !CONFIG_EXAMPLES_MOUNT_DEVNAME */ diff --git a/apps/examples/nsh/Kconfig b/apps/examples/nsh/Kconfig new file mode 100644 index 000000000..289c7e515 --- /dev/null +++ b/apps/examples/nsh/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_NSH + bool "NuttShell (NSH) example" + default n + ---help--- + Enable the NuttShell (NSH) example + +if EXAMPLES_NSH +endif diff --git a/apps/examples/nsh/Makefile b/apps/examples/nsh/Makefile new file mode 100644 index 000000000..b5844f9ed --- /dev/null +++ b/apps/examples/nsh/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/examples/nsh/Makefile +# +# Copyright (C) 2007-2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# NuttShell (NSH) Example + +ASRCS = +CSRCS = nsh_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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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: + +.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 diff --git a/apps/examples/nsh/nsh_main.c b/apps/examples/nsh/nsh_main.c new file mode 100644 index 000000000..c5b671ab1 --- /dev/null +++ b/apps/examples/nsh/nsh_main.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * examples/nsh/nsh_main.c + * + * Copyright (C) 2007-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/stat.h> +#include <stdint.h> +#include <stdio.h> +#include <sched.h> +#include <errno.h> + +#include <nuttx/arch.h> + +#include <apps/nsh.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The NSH telnet console requires networking support (and TCP/IP) */ + +#ifndef CONFIG_NET +# undef CONFIG_NSH_TELNET +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int exitval = 0; + int ret; + + /* Call all C++ static constructors */ + +#if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE) + up_cxxinitialize(); +#endif + + /* Initialize the NSH library */ + + nsh_initialize(); + + /* If the Telnet console is selected as a front-end, then start the + * Telnet daemon. + */ + +#ifdef CONFIG_NSH_TELNET + ret = nsh_telnetstart(); + if (ret < 0) + { + /* The daemon is NOT running. Report the the error then fail... + * either with the serial console up or just exiting. + */ + + fprintf(stderr, "ERROR: Failed to start TELNET daemon: %d\n", ret); + exitval = 1; + } +#endif + + /* If the serial console front end is selected, then run it on this thread */ + +#ifdef CONFIG_NSH_CONSOLE + ret = nsh_consolemain(0, NULL); + + /* nsh_consolemain() should not return. So if we get here, something + * is wrong. + */ + + fprintf(stderr, "ERROR: nsh_consolemain() returned: %d\n", ret); + exitval = 1; +#endif + + return exitval; +} diff --git a/apps/examples/null/Kconfig b/apps/examples/null/Kconfig new file mode 100644 index 000000000..1f19dfd2c --- /dev/null +++ b/apps/examples/null/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_NULL + bool "NULL example" + default n + ---help--- + Enable the NULL example + +if EXAMPLES_NULL +endif diff --git a/apps/examples/null/Makefile b/apps/examples/null/Makefile new file mode 100644 index 000000000..3938eb171 --- /dev/null +++ b/apps/examples/null/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# examples/null/Makefile +# +# Copyright (C) 2007-2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# The smallest thing you can build -- the NULL example. + +ASRCS = +CSRCS = null_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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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: + +.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 diff --git a/apps/examples/null/null_main.c b/apps/examples/null/null_main.c new file mode 100644 index 000000000..10fc1bf1e --- /dev/null +++ b/apps/examples/null/null_main.c @@ -0,0 +1,67 @@ +/**************************************************************************** + * examples/null/null_main.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 Gregory Nutt 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 + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + return 0; +} diff --git a/apps/examples/ostest/Kconfig b/apps/examples/ostest/Kconfig new file mode 100644 index 000000000..ca8957993 --- /dev/null +++ b/apps/examples/ostest/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_OSTEST + bool "OS test example" + default n + ---help--- + Enable the OS test example + +if EXAMPLES_OSTEST +endif diff --git a/apps/examples/ostest/Makefile b/apps/examples/ostest/Makefile new file mode 100644 index 000000000..eab1db8b3 --- /dev/null +++ b/apps/examples/ostest/Makefile @@ -0,0 +1,149 @@ +############################################################################ +# apps/examples/ostest/Makefile +# +# Copyright (C) 2007-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 + +# ostest built-in application info + +APPNAME = ostest +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# NuttX OS Test + +ASRCS = +CSRCS = main.c dev_null.c + +ifeq ($(CONFIG_ARCH_FPU),y) +CSRCS += fpu.c +endif + +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +CSRCS += cancel.c cond.c mutex.c sem.c barrier.c +ifneq ($(CONFIG_RR_INTERVAL),0) +CSRCS += roundrobin.c +endif # CONFIG_RR_INTERVAL +ifeq ($(CONFIG_MUTEX_TYPES),y) +CSRCS += rmutex.c +endif # CONFIG_MUTEX_TYPES +endif # CONFIG_DISABLE_PTHREAD + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +CSRCS += sighand.c +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +ifneq ($(CONFIG_DISABLE_CLOCK),y) +CSRCS += timedwait.c +endif # CONFIG_DISABLE_CLOCK +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_SIGNALS + +ifneq ($(CONFIG_DISABLE_MQUEUE),y) +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +CSRCS += mqueue.c +ifneq ($(CONFIG_DISABLE_CLOCK),y) +CSRCS += timedmqueue.c +endif # CONFIG_DISABLE_CLOCK +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_MQUEUE + +ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y) +CSRCS += posixtimer.c +endif + +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) +CSRCS += prioinherit.c +endif # CONFIG_PRIORITY_INHERITANCE +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_SIGNALS + +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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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_EXAMPLES_OSTEST_BUILTIN),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 diff --git a/apps/examples/ostest/barrier.c b/apps/examples/ostest/barrier.c new file mode 100644 index 000000000..da1301dc3 --- /dev/null +++ b/apps/examples/ostest/barrier.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * examples/ostest/barrier.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <unistd.h> +#include <pthread.h> + +#include "ostest.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define HALF_SECOND 500000L + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static pthread_barrier_t barrier; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: barrier_func + ****************************************************************************/ + +static void *barrier_func(void *parameter) +{ + int id = (int)parameter; + int status; + + printf("barrier_func: Thread %d started\n", id); +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND); +#endif + + /* Wait at the barrier until all threads are synchronized. */ + + printf("barrier_func: Thread %d calling pthread_barrier_wait()\n", + id); + FFLUSH(); + status = pthread_barrier_wait(&barrier); + if (status == 0) + { + printf("barrier_func: Thread %d, back with " + "status=0 (I am not special)\n", + id, status); + } + else if (status == PTHREAD_BARRIER_SERIAL_THREAD) + { + printf("barrier_func: Thread %d, back with " + "status=PTHREAD_BARRIER_SERIAL_THREAD (I AM SPECIAL)\n", + id, status); + } + else + { + printf("barrier_func: ERROR thread %d could not get semaphore value\n", + id); + } + FFLUSH(); + +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND); +#endif + printf("barrier_func: Thread %d done\n", id); + FFLUSH(); + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: barrier_test + ****************************************************************************/ + +void barrier_test(void) +{ + pthread_t barrier_thread[CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS]; + pthread_addr_t result; + pthread_attr_t attr; + pthread_barrierattr_t barrierattr; + int status; + int i; + + printf("barrier_test: Initializing barrier\n"); + + status = pthread_barrierattr_init(&barrierattr); + if (status != OK) + { + printf("barrier_test: pthread_barrierattr_init failed, status=%d\n", + status); + } + + status = pthread_barrier_init(&barrier, &barrierattr, + CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS); + if (status != OK) + { + printf("barrier_test: pthread_barrierattr_init failed, status=%d\n", + status); + } + + /* Create the barrier */ + + status = pthread_barrierattr_init(&barrierattr); + + /* Start CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS thread instances */ + + status = pthread_attr_init(&attr); + if (status != OK) + { + printf("barrier_test: pthread_attr_init failed, status=%d\n", + status); + } + + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS; i++) + { + status = pthread_create(&barrier_thread[i], &attr, barrier_func, + (pthread_addr_t)i); + if (status != 0) + { + printf("barrier_test: Error in thread %d create, status=%d\n", + i, status); + printf("barrier_test: Test aborted with waiting threads\n"); + goto abort_test; + } + else + { + printf("barrier_test: Thread %d created\n", i); + } + } + FFLUSH(); + + /* Wait for all thread instances to complete */ + + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS; i++) + { + status = pthread_join(barrier_thread[i], &result); + if (status != 0) + { + printf("barrier_test: Error in thread %d join, status=%d\n", + i, status); + } + else + { + printf("barrier_test: Thread %d completed with result=%p\n", + i, result); + } + } + + /* Destroy the barrier */ + +abort_test: + status = pthread_barrier_destroy(&barrier); + if (status != OK) + { + printf("barrier_test: pthread_barrier_destroy failed, status=%d\n", + status); + } + + status = pthread_barrierattr_destroy(&barrierattr); + if (status != OK) + { + printf("barrier_test: pthread_barrierattr_destroy failed, status=%d\n", + status); + } + FFLUSH(); +} diff --git a/apps/examples/ostest/cancel.c b/apps/examples/ostest/cancel.c new file mode 100644 index 000000000..bf2d03615 --- /dev/null +++ b/apps/examples/ostest/cancel.c @@ -0,0 +1,333 @@ +/*********************************************************************** + * examples/ostest/cancel.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <time.h> +#include <pthread.h> +#include <errno.h> +#include "ostest.h" + +static pthread_mutex_t mutex; +static pthread_cond_t cond; + +static void *thread_waiter(void *parameter) +{ + int status; + + /* Take the mutex */ + + printf("thread_waiter: Taking mutex\n"); + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_lock failed, status=%d\n", status); + } + + printf("thread_waiter: Starting wait for condition\n"); + + /* Are we a non-cancelable thread? Yes, set the non-cancelable state */ + + if (!parameter) + { + printf("thread_waiter: Setting non-cancelable\n"); + status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_setcancelstate failed, status=%d\n", status); + } + } + + /* The wait -- we will never awaken from this. */ + + status = pthread_cond_wait(&cond, &mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_cond_wait failed, status=%d\n", status); + } + + /* Release the mutex */ + + printf("thread_waiter: Releasing mutex\n"); + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_unlock failed, status=%d\n", status); + } + + /* Set the cancelable state */ + + printf("thread_waiter: Setting cancelable\n"); + status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_setcancelstate failed, status=%d\n", status); + } + + printf("thread_waiter: Exit with status 0x12345678\n"); + pthread_exit((pthread_addr_t)0x12345678); + return NULL; +} + +static void start_thread(pthread_t *waiter, int cancelable) +{ + pthread_attr_t attr; + int status; + + /* Initialize the mutex */ + + printf("start_thread: Initializing mutex\n"); + status = pthread_mutex_init(&mutex, NULL); + if (status != 0) + { + printf("start_thread: ERROR pthread_mutex_init failed, status=%d\n", status); + } + + /* Initialize the condition variable */ + + printf("start_thread: Initializing cond\n"); + status = pthread_cond_init(&cond, NULL); + if (status != 0) + { + printf("start_thread: ERROR pthread_cond_init failed, status=%d\n", status); + } + + /* Set up attributes */ + + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("start_thread: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("start_thread: pthread_attr_setstacksize failed, status=%d\n", status); + } + + /* Start the waiter thread */ + + printf("start_thread: Starting thread\n"); + status = pthread_create(waiter, &attr, thread_waiter, (pthread_addr_t)cancelable); + if (status != 0) + { + printf("start_thread: ERROR pthread_create failed, status=%d\n", status); + } + + /* Make sure that the waiter thread gets a chance to run */ + + printf("start_thread: Yielding\n"); + pthread_yield(); +} + +static void restart_thread(pthread_t *waiter, int cancelable) +{ + int status; + + /* Destroy the condition variable */ + + printf("restart_thread: Destroying cond\n"); + status = pthread_cond_destroy(&cond); + if (status != 0) + { + printf("restart_thread: ERROR pthread_cond_destroy failed, status=%d\n", status); + } + + /* Destroy the mutex */ + + printf("restart_thread: Destroying mutex\n"); + status = pthread_cond_destroy(&cond); + if (status != 0) + { + printf("restart_thread: ERROR pthread_mutex_destroy failed, status=%d\n", status); + } + + /* Then restart the thread */ + + printf("restart_thread: Re-starting thread\n"); + start_thread(waiter, cancelable); +} + +void cancel_test(void) +{ + pthread_t waiter; + void *result; + int status; + + /* Test 1: Normal Cancel *********************************************/ + /* Start the waiter thread */ + + printf("cancel_test: Test 1: Normal Cancelation\n"); + printf("cancel_test: Starting thread\n"); + start_thread(&waiter, 1); + + /* Then cancel it. It should be in the pthread_cond_wait now */ + + printf("cancel_test: Canceling thread\n"); + status = pthread_cancel(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status); + } + + /* Then join to the thread to pick up the result (if we don't do + * we will have a memory leak!) + */ + + printf("cancel_test: Joining\n"); + status = pthread_join(waiter, &result); + if (status != 0) + { + printf("cancel_test: ERROR pthread_join failed, status=%d\n", status); + } + else + { + printf("cancel_test: waiter exited with result=%p\n", result); + if (result != PTHREAD_CANCELED) + { + printf("cancel_test: ERROR expected result=%p\n", PTHREAD_CANCELED); + } + else + { + printf("cancel_test: PASS thread terminated with PTHREAD_CANCELED\n"); + } + } + + /* Test 2: Cancel Detached Thread ************************************/ + + printf("cancel_test: Test 2: Cancelation of detached thread\n"); + printf("cancel_test: Re-starting thread\n"); + restart_thread(&waiter, 1); + + /* Detach the thread */ + + status = pthread_detach(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_detach, status=%d\n", status); + } + + /* Then cancel it. It should be in the pthread_cond_wait now */ + + printf("cancel_test: Canceling thread\n"); + status = pthread_cancel(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status); + } + + /* Join should now fail */ + + printf("cancel_test: Joining\n"); + status = pthread_join(waiter, &result); + if (status == 0) + { + printf("cancel_test: ERROR pthread_join succeeded\n"); + } + else if (status != ESRCH) + { + printf("cancel_test: ERROR pthread_join failed but with wrong status=%d\n", status); + } + else + { + printf("cancel_test: PASS pthread_join failed with status=ESRCH\n"); + } + + /* Test 3: Non-cancelable threads ************************************/ + + printf("cancel_test: Test 3: Non-cancelable threads\n"); + printf("cancel_test: Re-starting thread (non-cancelable)\n"); + restart_thread(&waiter, 0); + + /* Then cancel it. It should be in the pthread_cond_wait now. The + * behavior here is non-standard: when the thread is at a cancelation + * point, it should be cancelable, even when cancelation is disable. + * + * The cancelation should succeed, because the cancelation is pending. + */ + + printf("cancel_test: Canceling thread\n"); + status = pthread_cancel(waiter); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status); + } + + /* Signal the thread. It should wake up and restore the cancelable state. + * When the cancelable state is re-enabled, the thread should be canceled. + */ + + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("cancel_test: ERROR pthread_mutex_lock failed, status=%d\n", status); + } + + status = pthread_cond_signal(&cond); + if (status != 0) + { + printf("cancel_test: ERROR pthread_cond_signal failed, status=%d\n", status); + } + + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("cancel_test: ERROR pthread_mutex_unlock failed, status=%d\n", status); + } + + /* Then join to the thread to pick up the result (if we don't do + * we will have a memory leak!) + */ + + printf("cancel_test: Joining\n"); + status = pthread_join(waiter, &result); + if (status != 0) + { + printf("cancel_test: ERROR pthread_join failed, status=%d\n", status); + } + else + { + printf("cancel_test: waiter exited with result=%p\n", result); + if (result != PTHREAD_CANCELED) + { + printf("cancel_test: ERROR expected result=%p\n", PTHREAD_CANCELED); + } + else + { + printf("cancel_test: PASS thread terminated with PTHREAD_CANCELED\n"); + } + } + +} diff --git a/apps/examples/ostest/cond.c b/apps/examples/ostest/cond.c new file mode 100644 index 000000000..11191b7d5 --- /dev/null +++ b/apps/examples/ostest/cond.c @@ -0,0 +1,294 @@ +/*********************************************************************** + * cond.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <pthread.h> +#include <unistd.h> +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +static volatile enum { RUNNING, MUTEX_WAIT, COND_WAIT} waiter_state; + +static pthread_mutex_t mutex; +static pthread_cond_t cond; +static volatile int data_available = 0; +static int waiter_nloops = 0; +static int waiter_waits = 0; +static int waiter_nerrors = 0; +static int signaler_nloops = 0; +static int signaler_already = 0; +static int signaler_state = 0; +static int signaler_nerrors = 0; + +static void *thread_waiter(void *parameter) +{ + int status; + + printf("waiter_thread: Started\n"); + + for(;;) + { + /* Take the mutex */ + + waiter_state = MUTEX_WAIT; + status = pthread_mutex_lock(&mutex); + waiter_state = RUNNING; + + if (status != 0) + { + printf("waiter_thread: ERROR pthread_mutex_lock failed, status=%d\n", status); + waiter_nerrors++; + } + + /* Check if data is available -- if data is not available then + * wait for it + */ + + if (!data_available) + { + /* We are higher priority than the signaler thread so the + * only time that the signaler thread will have a chance to run is when + * we are waiting for the condition variable. In this case, pthread_cond_wait + * will automatically release the mutex for the signaler (then re-acquire + * the mutex before returning. + */ + + waiter_state = COND_WAIT; + status = pthread_cond_wait(&cond, &mutex); + waiter_state = RUNNING; + + if (status != 0) + { + printf("waiter_thread: ERROR pthread_cond_wait failed, status=%d\n", status); + waiter_nerrors++; + } + waiter_waits++; + } + + /* Now data should be available */ + + if (!data_available) + { + printf("waiter_thread: ERROR data not available after wait\n"); + waiter_nerrors++; + } + + /* Clear data available */ + + data_available = 0; + + /* Release the mutex */ + + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("waiter_thread: ERROR waiter: pthread_mutex_unlock failed, status=%d\n", status); + waiter_nerrors++; + } + + waiter_nloops++; + } + return NULL; +} + +static void *thread_signaler(void *parameter) +{ + int status; + int i; + + printf("thread_signaler: Started\n"); + for (i = 0; i < 32; i++) + { + /* Take the mutex. The waiter is higher priority and should + * run until it waits for the condition. So, at this point + * signaler should be waiting for the condition. + */ + + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("thread_signaler: ERROR pthread_mutex_lock failed, status=%d\n", status); + signaler_nerrors++; + } + + /* Verify the state */ + + if (waiter_state != COND_WAIT) + { + printf("thread_signaler: ERROR waiter state = %d != COND_WAITING\n", waiter_state); + signaler_state++; + } + + if (data_available) + { + printf("thread_signaler: ERROR data already available, waiter_state=%d\n", waiter_state); + signaler_already++; + } + + /* Set data available and signal the waiter */ + + data_available = 1; + status = pthread_cond_signal(&cond); + if (status != 0) + { + printf("thread_signaler: ERROR pthread_cond_signal failed, status=%d\n", status); + signaler_nerrors++; + } + + /* Release the mutex */ + + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("thread_signaler: ERROR pthread_mutex_unlock failed, status=%d\n", status); + signaler_nerrors++; + } + + signaler_nloops++; + } + + printf("thread_signaler: Terminating\n"); + pthread_exit(NULL); + return NULL; /* Non-reachable -- needed for some compilers */ +} + +void cond_test(void) +{ + pthread_t waiter; + pthread_t signaler; + pthread_attr_t attr; +#ifdef SDCC + pthread_addr_t result; +#endif + struct sched_param sparam; + int prio_min; + int prio_max; + int prio_mid; + int status; + + /* Initialize the mutex */ + + printf("cond_test: Initializing mutex\n"); + status = pthread_mutex_init(&mutex, NULL); + if (status != 0) + { + printf("cond_test: ERROR pthread_mutex_init failed, status=%d\n", status); + } + + /* Initialize the condition variable */ + + printf("cond_test: Initializing cond\n"); + status = pthread_cond_init(&cond, NULL); + if (status != 0) + { + printf("cond_test: ERROR pthread_condinit failed, status=%d\n", status); + } + + /* Start the waiter thread at higher priority */ + + printf("cond_test: Starting waiter\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("cond_test: pthread_attr_init failed, status=%d\n", status); + } + + prio_min = sched_get_priority_min(SCHED_FIFO); + prio_max = sched_get_priority_max(SCHED_FIFO); + prio_mid = (prio_min + prio_max) / 2; + + sparam.sched_priority = prio_mid; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("cond_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("cond_test: Set thread 1 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter, &attr, thread_waiter, NULL); + if (status != 0) + { + printf("cond_test: pthread_create failed, status=%d\n", status); + } + + printf("cond_test: Starting signaler\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("cond_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = (prio_min + prio_mid) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("cond_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("cond_test: Set thread 2 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&signaler, &attr, thread_signaler, NULL); + if (status != 0) + { + printf("cond_test: pthread_create failed, status=%d\n", status); + } + + /* Wait for the threads to stop */ + +#ifdef SDCC + pthread_join(signaler, &result); +#else + pthread_join(signaler, NULL); +#endif + printf("cond_test: signaler terminated, now cancel the waiter\n"); + pthread_detach(waiter); + pthread_cancel(waiter); + + printf("cond_test: \tWaiter\tSignaler\n"); + printf("cond_test: Loops\t%d\t%d\n", waiter_nloops, signaler_nloops); + printf("cond_test: Errors\t%d\t%d\n", waiter_nerrors, signaler_nerrors); + printf("cond_test:\n"); + printf("cond_test: %d times, waiter did not have to wait for data\n", waiter_nloops - waiter_waits); + printf("cond_test: %d times, data was already available when the signaler run\n", signaler_already); + printf("cond_test: %d times, the waiter was in an unexpected state when the signaler ran\n", signaler_state); +} diff --git a/apps/examples/ostest/dev_null.c b/apps/examples/ostest/dev_null.c new file mode 100644 index 000000000..e8fc6cf3f --- /dev/null +++ b/apps/examples/ostest/dev_null.c @@ -0,0 +1,92 @@ +/**************************************************************************** + * examples/ostest/dev_null.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include "ostest.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +static FAR char buffer[1024]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int dev_null(void) +{ + int nbytes; + int fd; + + fd = open("/dev/null", O_RDWR); + if (fd < 0) + { + printf("dev_null: ERROR Failed to open /dev/null\n"); + return -1; + } + + nbytes = read(fd, buffer, 1024); + if (nbytes < 0) + { + printf("dev_null: ERROR Failed to read from /dev/null\n"); + close(fd); + return -1; + } + printf("dev_null: Read %d bytes from /dev/null\n", nbytes); + + nbytes = write(fd, buffer, 1024); + if (nbytes < 0) + { + printf("dev_null: ERROR Failed to write to /dev/null\n"); + close(fd); + return -1; + } + printf("dev_null: Wrote %d bytes to /dev/null\n", nbytes); + + close(fd); + return 0; +} + +#endif /*CONFIG_NFILE_DESCRIPTORS */ diff --git a/apps/examples/ostest/fpu.c b/apps/examples/ostest/fpu.c new file mode 100644 index 000000000..89a1034ce --- /dev/null +++ b/apps/examples/ostest/fpu.c @@ -0,0 +1,344 @@ +/*********************************************************************** + * apps/examples/ostest/fpu.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/wait.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sched.h> + +#include "ostest.h" + +/*********************************************************************** + * Pre-processor definitions + ***********************************************************************/ +/* Configuration *******************************************************/ + +#undef HAVE_FPU +#ifdef CONFIG_ARCH_FPU +# if defined(CONFIG_EXAMPLES_OSTEST_FPUSIZE) && defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_DISABLE_SIGNALS) +# define HAVE_FPU 1 +# else +# ifndef CONFIG_EXAMPLES_OSTEST_FPUSIZE +# warning "FPU test not built; CONFIG_EXAMPLES_OSTEST_FPUSIZE not defined" +# endif +# ifndef CONFIG_SCHED_WAITPID +# warning "FPU test not built; CONFIG_SCHED_WAITPID not defined" +# endif +# ifdef CONFIG_DISABLE_SIGNALS +# warning "FPU test not built; CONFIG_DISABLE_SIGNALS defined" +# endif +# endif +#endif + +#ifdef HAVE_FPU + +#ifndef CONFIG_EXAMPLES_OSTEST_FPULOOPS +# define CONFIG_EXAMPLES_OSTEST_FPULOOPS 16 +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUMSDELAY +# define CONFIG_EXAMPLES_OSTEST_FPUMSDELAY 750 +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUPRIORITY +# define CONFIG_EXAMPLES_OSTEST_FPUPRIORITY SCHED_PRIORITY_DEFAULT +#endif + +#ifndef CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE +# define CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE 2048 +#endif + +/* Other defintions ****************************************************/ +/* We'll keep all data using 32-bit values only to force 32-bit alignment. + * This logic has no real notion of the underlying representation. + */ + +#define FPU_WORDSIZE ((CONFIG_EXAMPLES_OSTEST_FPUSIZE+3)>>2) +#define FPU_NTHREADS 2 + +#ifndef NULL +# define NULL (void*)0 +#endif + +/*********************************************************************** + * External Dependencies + ***********************************************************************/ +/* This test is very dependent on support provided by the chip/board- + * layer logic. In particular, it expects the following functions + * to be provided: + */ + +/* Given an array of size CONFIG_EXAMPLES_OSTEST_FPUSIZE, this function + * will return the current FPU registers. + */ + +extern void arch_getfpu(FAR uint32_t *fpusave); + +/* Given two arrays of size CONFIG_EXAMPLES_OSTEST_FPUSIZE this + * function will compare them and return true if they are identical. + */ + +extern bool arch_cmpfpu(FAR const uint32_t *fpusave1, + FAR const uint32_t *fpusave2); + +/*********************************************************************** + * Private Types + ***********************************************************************/ + +struct fpu_threaddata_s +{ + uint32_t save1[FPU_WORDSIZE]; + uint32_t save2[FPU_WORDSIZE]; + + /* These are just dummy values to force the compiler to do the + * requested floating point computations without the nonsense + * computations being optimized away. + */ + + volatile float sp1; + volatile float sp2; + volatile float sp3; + volatile float sp4; + + volatile float dp1; + volatile float dp2; + volatile float dp3; + volatile float dp4; +}; + +/*********************************************************************** + * Private Data + ***********************************************************************/ + +static uint8_t g_fpuno; +/* static */ struct fpu_threaddata_s g_fputhread[FPU_NTHREADS]; + +/*********************************************************************** + * Private Functions + ***********************************************************************/ + +static void fpu_dump(FAR uint32_t *buffer, FAR const char *msg) +{ + int i, j, k; + + printf("%s (%p):\n", msg, buffer); + for (i = 0; i < FPU_WORDSIZE; i += 8) + { + printf(" %04x: ", i); + for (j = 0; j < 8; j++) + { + k = i + j; + + if (k < FPU_WORDSIZE) + { + printf("%08x ", buffer[k]); + } + else + { + printf("\n"); + break; + } + } + printf("\n"); + } +} + +static int fpu_task(int argc, char *argv[]) +{ + FAR struct fpu_threaddata_s *fpu; + register float sp1; + register float sp2; + register float sp3; + register float sp4; + register double dp1; + register double dp2; + register double dp3; + register double dp4; + + int id; + int i; + + /* Which are we? */ + + sched_lock(); + fpu = &g_fputhread[g_fpuno]; + id = (int)(++g_fpuno); + sched_unlock(); + + /* Seed the flowing point values */ + + sp1 = (float)id; + dp1 = (double)id; + + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_FPULOOPS; i++) + { + printf("FPU#%d: pass %d\n", id, i+1); + fflush(stdout); + + /* Set the FPU register save arrays to a known-but-illogical values so + * that we can verify that reading of the registers actually occurs. + */ + + memset(fpu->save1, 0xff, FPU_WORDSIZE * sizeof(uint32_t)); + memset(fpu->save2, 0xff, FPU_WORDSIZE * sizeof(uint32_t)); + + /* Prevent context switches while we set up some stuff */ + + sched_lock(); + + /* Do some trivial floating point operations that should cause some + * changes to floating point registers. First, some single preceision + * nonsense. + */ + + sp4 = (float)3.14159 * sp1; /* Multiple by Pi */ + sp3 = sp4 + (float)1.61803; /* Add the golden ratio */ + sp2 = sp3 / (float)2.71828; /* Divide by Euler's constant */ + sp1 = sp2 + (float)1.0; /* Plus one */ + + fpu->sp1 = sp1; /* Make the compiler believe that somebody cares about the result */ + fpu->sp2 = sp2; + fpu->sp3 = sp3; + fpu->sp4 = sp4; + + /* Again using double precision */ + + dp4 = (double)3.14159 * dp1; /* Multiple by Pi */ + dp3 = dp4 + (double)1.61803; /* Add the golden ratio */ + dp2 = dp3 / (double)2.71828; /* Divide by Euler's constant */ + dp1 = dp2 + (double)1.0; /* Plus one */ + + fpu->dp1 = dp1; /* Make the compiler believe that somebody cares about the result */ + fpu->dp2 = dp2; + fpu->dp3 = dp3; + fpu->dp4 = dp4; + + /* Sample the floating point registers */ + + arch_getfpu(fpu->save1); + + /* Re-read and verify the FPU registers consistently without corruption */ + + arch_getfpu(fpu->save2); + if (!arch_cmpfpu(fpu->save1, fpu->save2)) + { + printf("ERROR FPU#%d: save1 and save2 do not match\n", id); + fpu_dump(fpu->save1, "Values after math operations (save1)"); + fpu_dump(fpu->save2, "Values after verify re-read (save2)"); + return EXIT_FAILURE; + } + + /* Now unlock and sleep for a while -- this should result in some context switches */ + + sched_unlock(); + usleep(CONFIG_EXAMPLES_OSTEST_FPUMSDELAY * 1000); + + /* Several context switches should have occurred. Now verify that the floating + * point registers are still correctly set. + */ + + arch_getfpu(fpu->save2); + if (!arch_cmpfpu(fpu->save1, fpu->save2)) + { + printf("ERROR FPU#%d: save1 and save2 do not match\n", id); + fpu_dump(fpu->save1, "Values before waiting (save1)"); + fpu_dump(fpu->save2, "Values after waiting (save2)"); + return EXIT_FAILURE; + } + } + + printf("FPU#%d: Succeeded\n", id); + fflush(stdout); + return EXIT_SUCCESS; +} +#endif /* HAVE_FPU */ + +/*********************************************************************** + * Private Functions + ***********************************************************************/ + +void fpu_test(void) +{ +#ifdef HAVE_FPU + pid_t task1; + pid_t task2; + int statloc; + + /* Start two two tasks */ + + g_fpuno = 0; + printf("Starting task FPU#1\n"); + task1 = TASK_CREATE("FPU#1", CONFIG_EXAMPLES_OSTEST_FPUPRIORITY, CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE, fpu_task, NULL); + if (task1 < 0) + { + printf("fpu_test: ERROR Failed to start task FPU#1\n"); + } + else + { + printf("fpu_test: Started task FPU#1 at PID=%d\n", task1); + } + fflush(stdout); + usleep(250); + + printf("Starting task FPU#2\n"); + task2 = TASK_CREATE("FPU#2", CONFIG_EXAMPLES_OSTEST_FPUPRIORITY, CONFIG_EXAMPLES_OSTEST_FPUSTACKSIZE, fpu_task, NULL); + if (task2 < 0) + { + printf("fpu_test: ERROR Failed to start task FPU#1\n"); + } + else + { + printf("fpu_test: Started task FPU#2 at PID=%d\n", task2); + } + + /* Wait for each task to complete */ + + fflush(stdout); + (void)waitpid(task1, &statloc, 0); + (void)waitpid(task2, &statloc, 0); + +#else + printf("fpu_test: ERROR: The FPU test is not properly configured\n"); +#endif + printf("fpu_test: Returning\n"); +} diff --git a/apps/examples/ostest/main.c b/apps/examples/ostest/main.c new file mode 100644 index 000000000..7d63c0ff4 --- /dev/null +++ b/apps/examples/ostest/main.c @@ -0,0 +1,530 @@ +/**************************************************************************** + * apps/examples/ostest/main.c + * + * 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 + * 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 <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sched.h> +#include <nuttx/init.h> + +#include "ostest.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define PRIORITY 100 +#define NARGS 4 +#define HALF_SECOND_USEC 500000L + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char arg1[] = "Arg1"; +static const char arg2[] = "Arg2"; +static const char arg3[] = "Arg3"; +static const char arg4[] = "Arg4"; + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static const char write_data1[] = "stdio_test: write fd=1\n"; +static const char write_data2[] = "stdio_test: write fd=2\n"; +#endif + +#ifdef SDCC +/* I am not yet certain why SDCC does not like the following + * initializer. It involves some issues with 2- vs 3-byte + * pointer types. + */ + +static const char *g_argv[NARGS+1]; +#else +static const char *g_argv[NARGS+1] = { arg1, arg2, arg3, arg4, NULL }; +#endif + +#ifndef CONFIG_DISABLE_SIGNALS +static struct mallinfo g_mmbefore; +static struct mallinfo g_mmprevious; +static struct mallinfo g_mmafter; +#endif + +#ifndef CONFIG_DISABLE_ENVIRON +const char g_var1_name[] = "Variable1"; +const char g_var1_value[] = "GoodValue1"; +const char g_var2_name[] = "Variable2"; +const char g_var2_value[] = "GoodValue2"; +const char g_var3_name[] = "Variable3"; +const char g_var3_value[] = "GoodValue3"; + +const char g_bad_value1[] = "BadValue1"; +const char g_bad_value2[] = "BadValue2"; + +const char g_putenv_value[] = "Variable1=BadValue3"; + +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: show_memory_usage + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +static void show_memory_usage(struct mallinfo *mmbefore, + struct mallinfo *mmafter) +{ + printf("VARIABLE BEFORE AFTER\n"); + printf("======== ======== ========\n"); + printf("arena %8x %8x\n", mmbefore->arena, mmafter->arena); + printf("ordblks %8d %8d\n", mmbefore->ordblks, mmafter->ordblks); + printf("mxordblk %8x %8x\n", mmbefore->mxordblk, mmafter->mxordblk); + printf("uordblks %8x %8x\n", mmbefore->uordblks, mmafter->uordblks); + printf("fordblks %8x %8x\n", mmbefore->fordblks, mmafter->fordblks); +} +#else +# define show_memory_usage(mm1, mm2) +#endif + +/**************************************************************************** + * Name: check_test_memory_usage + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_SIGNALS +static void check_test_memory_usage(void) +{ + /* Wait a little bit to let any threads terminate */ + + usleep(HALF_SECOND_USEC); + + /* Get the current memory usage */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmafter = mallinfo(); +#else + (void)mallinfo(&g_mmafter); +#endif + + /* Show the change from the previous time */ + + printf("\nEnd of test memory usage:\n"); + show_memory_usage(&g_mmprevious, &g_mmafter); + + /* Set up for the next test */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmprevious = g_mmafter; +#else + memcpy(&g_mmprevious, &g_mmafter, sizeof(struct mallinfo)); +#endif + + /* If so enabled, show the use of priority inheritance resources */ + + dump_nfreeholders("user_main:"); +} +#else +# define check_test_memory_usage() +#endif + +/**************************************************************************** + * Name: show_variable + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_ENVIRON +static void show_variable(const char *var_name, const char *exptd_value, bool var_valid) +{ + char *actual_value = getenv(var_name); + if (actual_value) + { + if (var_valid) + { + if (strcmp(actual_value, exptd_value) == 0) + { + printf("show_variable: Variable=%s has value=%s\n", var_name, exptd_value); + } + else + { + printf("show_variable: ERROR Variable=%s has the wrong value\n", var_name); + printf("show_variable: found=%s expected=%s\n", actual_value, exptd_value); + } + } + else + { + printf("show_variable: ERROR Variable=%s has a value when it should not\n", var_name); + printf("show_variable: value=%s\n", actual_value); + } + } + else if (var_valid) + { + printf("show_variable: ERROR Variable=%s has no value\n", var_name); + printf("show_variable: Should have had value=%s\n", exptd_value); + } + else + { + printf("show_variable: Variable=%s has no value\n", var_name); + } +} + +static void show_environment(bool var1_valid, bool var2_valid, bool var3_valid) +{ + show_variable(g_var1_name, g_var1_value, var1_valid); + show_variable(g_var2_name, g_var2_value, var2_valid); + show_variable(g_var3_name, g_var3_value, var3_valid); +} +#else +# define show_environment() +#endif + +/**************************************************************************** + * Name: user_main + ****************************************************************************/ + +static int user_main(int argc, char *argv[]) +{ + int i; + + /* Sample the memory usage now */ + +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmbefore = mallinfo(); + g_mmprevious = g_mmbefore; +#else + (void)mallinfo(&g_mmbefore); + memcpy(&g_mmprevious, &g_mmbefore, sizeof(struct mallinfo)); +#endif +#endif + + printf("\nuser_main: Begin argument test\n"); + printf("user_main: Started with argc=%d\n", argc); + + /* Verify passed arguments */ + + if (argc != NARGS + 1) + { + printf("user_main: Error expected argc=%d got argc=%d\n", + NARGS+1, argc); + } + + for (i = 0; i <= NARGS; i++) + { + printf("user_main: argv[%d]=\"%s\"\n", i, argv[i]); + } + + for (i = 1; i <= NARGS; i++) + { + if (strcmp(argv[i], g_argv[i-1]) != 0) + { + printf("user_main: ERROR argv[%d]: Expected \"%s\" found \"%s\"\n", + i, g_argv[i-1], argv[i]); + } + } + check_test_memory_usage(); + + /* Check environment variables */ +#ifndef CONFIG_DISABLE_ENVIRON + show_environment(true, true, true); + + unsetenv(g_var1_name); + show_environment(false, true, true); + check_test_memory_usage(); + + clearenv(); + show_environment(false, false, false); + check_test_memory_usage(); +#endif + + /* Top of test loop */ + +#if CONFIG_EXAMPLES_OSTEST_LOOPS > 1 + for (i = 0; i < CONFIG_EXAMPLES_OSTEST_LOOPS; i++) +#elif CONFIG_EXAMPLES_OSTEST_LOOPS == 0 + for (;;) +#endif + { +#if CONFIG_NFILE_DESCRIPTORS > 0 + /* Checkout /dev/null */ + + printf("\nuser_main: /dev/null test\n"); + dev_null(); + check_test_memory_usage(); +#endif + +#ifdef CONFIG_ARCH_FPU + /* Check that the FPU is properly supported during context switching */ + + printf("\nuser_main: FPU test\n"); + fpu_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthreads and pthread mutex */ + + printf("\nuser_main: mutex test\n"); + mutex_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_MUTEX_TYPES) + /* Verify recursive mutexes */ + + printf("\nuser_main: recursive mutex test\n"); + recursive_mutex_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthread cancellation */ + + printf("\nuser_main: cancel test\n"); + cancel_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthreads and semaphores */ + + printf("\nuser_main: semaphore test\n"); + sem_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthreads and condition variables */ + + printf("\nuser_main: condition variable test\n"); +#ifdef CONFIG_PRIORITY_INHERITANCE + printf("\n Skipping, Test logic incompatible with priority inheritance\n"); +#else + cond_test(); + check_test_memory_usage(); +#endif +#endif + +#if !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_DISABLE_CLOCK) + /* Verify pthreads and condition variable timed waits */ + + printf("\nuser_main: timed wait test\n"); + timedwait_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_PTHREAD) + /* Verify pthreads and message queues */ + + printf("\nuser_main: message queue test\n"); + mqueue_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_DISABLE_CLOCK) + /* Verify pthreads and message queues */ + + printf("\nuser_main: timed message queue test\n"); + timedmqueue_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_SIGNALS + /* Verify signal handlers */ + + printf("\nuser_main: signal handler test\n"); + sighand_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_POSIX_TIMERS) && !defined(CONFIG_DISABLE_SIGNALS) + /* Verify posix timers */ + + printf("\nuser_main: POSIX timer test\n"); + timer_test(); + check_test_memory_usage(); +#endif + +#if !defined(CONFIG_DISABLE_PTHREAD) && CONFIG_RR_INTERVAL > 0 + /* Verify round robin scheduling */ + + printf("\nuser_main: round-robin scheduler test\n"); + rr_test(); + check_test_memory_usage(); +#endif + +#ifndef CONFIG_DISABLE_PTHREAD + /* Verify pthread barriers */ + + printf("\nuser_main: barrier test\n"); + barrier_test(); + check_test_memory_usage(); +#endif + +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + /* Verify priority inheritance */ + + printf("\nuser_main: priority inheritance test\n"); + priority_inheritance(); + check_test_memory_usage(); +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ + + /* Compare memory usage at time user_start started until + * user_main exits. These should not be identical, but should + * be similar enough that we can detect any serious OS memory + * leaks. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + usleep(HALF_SECOND_USEC); + +#ifdef CONFIG_CAN_PASS_STRUCTS + g_mmafter = mallinfo(); +#else + (void)mallinfo(&g_mmafter); +#endif + + printf("\nFinal memory usage:\n"); + show_memory_usage(&g_mmbefore, &g_mmafter); +#endif + } + printf("user_main: Exitting\n"); + return 0; +} + +/**************************************************************************** + * Name: stdio_test + ****************************************************************************/ + +static void stdio_test(void) +{ + /* Verify that we can communicate */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + write(1, write_data1, sizeof(write_data1)-1); +#endif + printf("stdio_test: Standard I/O Check: printf\n"); + +#if CONFIG_NFILE_DESCRIPTORS > 1 + write(2, write_data2, sizeof(write_data2)-1); +#endif +#if CONFIG_NFILE_STREAMS > 0 + fprintf(stderr, "stdio_test: Standard I/O Check: fprintf to stderr\n"); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start/ostest_main + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_OSTEST_BUILTIN +# define MAIN_NAME ostest_main +# define MAIN_STRING "ostest_main: " +#else +# define MAIN_NAME user_start +# define MAIN_STRING "user_start: " +#endif + +int MAIN_NAME(int argc, char *argv[]) +{ + int result; + + /* Verify that stdio works first */ + + stdio_test(); + +#ifdef SDCC + /* I am not yet certain why SDCC does not like the following initilizers. + * It involves some issues with 2- vs 3-byte pointer types. + */ + + g_argv[0] = arg1; + g_argv[1] = arg2; + g_argv[2] = arg3; + g_argv[3] = arg4; + g_argv[4] = NULL; +#endif + + /* Set up some environment variables */ + +#ifndef CONFIG_DISABLE_ENVIRON + printf(MAIN_STRING "putenv(%s)\n", g_putenv_value); + putenv(g_putenv_value); /* Varaible1=BadValue3 */ + printf(MAIN_STRING "setenv(%s, %s, TRUE)\n", g_var1_name, g_var1_value); + setenv(g_var1_name, g_var1_value, TRUE); /* Variable1=GoodValue1 */ + + printf(MAIN_STRING "setenv(%s, %s, FALSE)\n", g_var2_name, g_bad_value1); + setenv(g_var2_name, g_bad_value1, FALSE); /* Variable2=BadValue1 */ + printf(MAIN_STRING "setenv(%s, %s, TRUE)\n", g_var2_name, g_var2_value); + setenv(g_var2_name, g_var2_value, TRUE); /* Variable2=GoodValue2 */ + + printf(MAIN_STRING "setenv(%s, %s, FALSE)\n", g_var3_name, g_var3_name); + setenv(g_var3_name, g_var3_value, FALSE); /* Variable3=GoodValue3 */ + printf(MAIN_STRING "setenv(%s, %s, FALSE)\n", g_var3_name, g_var3_name); + setenv(g_var3_name, g_bad_value2, FALSE); /* Variable3=GoodValue3 */ + show_environment(true, true, true); +#endif + + /* Verify that we can spawn a new task */ + +#ifndef CONFIG_CUSTOM_STACK + result = task_create("ostest", PRIORITY, STACKSIZE, user_main, g_argv); +#else + result = task_create("ostest", PRIORITY, user_main, g_argv); +#endif + if (result == ERROR) + { + printf(MAIN_STRING "ERROR Failed to start user_main\n"); + } + else + { + printf(MAIN_STRING "Started user_main at PID=%d\n", result); + } + + printf(MAIN_STRING "Exitting\n"); + return 0; +} diff --git a/apps/examples/ostest/mqueue.c b/apps/examples/ostest/mqueue.c new file mode 100644 index 000000000..39ef76a53 --- /dev/null +++ b/apps/examples/ostest/mqueue.c @@ -0,0 +1,394 @@ +/************************************************************************** + * apps/examples/ostest/mqueue.c + * + * Copyright (C) 2007-2009, 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. + * + **************************************************************************/ + +/************************************************************************** + * Included Files + **************************************************************************/ + +#include <nuttx/config.h> + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <pthread.h> +#include <mqueue.h> +#include <sched.h> +#include <errno.h> + +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +#define TEST_MESSAGE "This is a test and only a test" +#if defined(SDCC) || defined(__ZILOG__) + /* Cannot use strlen in array size */ + +# define TEST_MSGLEN (31) +#else + /* Message lenght is the size of the message plus the null terminator */ + +# define TEST_MSGLEN (strlen(TEST_MESSAGE)+1) +#endif + +#define TEST_SEND_NMSGS (10) +#ifndef CONFIG_DISABLE_SIGNALS +# define TEST_RECEIVE_NMSGS (11) +#else +# define TEST_RECEIVE_NMSGS (10) +#endif + +#define HALF_SECOND_USEC_USEC 500000L + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +static void *sender_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int status = 0; + int nerrors = 0; + int i; + + printf("sender_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = 20; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this process tries to send to the queue and the queue is full. + * + * O_CREAT - the queue will get created if it does not already exist. + * O_WRONLY - we are only planning to write to the queue. + * + * Open the queue, and create it if the receiving process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_WRONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("sender_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Fill in a test message buffer to send */ + + memcpy(msg_buffer, TEST_MESSAGE, TEST_MSGLEN); + + /* Perform the send TEST_SEND_NMSGS times */ + + for (i = 0; i < TEST_SEND_NMSGS; i++) + { + status = mq_send(mqfd, msg_buffer, TEST_MSGLEN, 42); + if (status < 0) + { + printf("sender_thread: ERROR mq_send failure=%d on msg %d\n", status, i); + nerrors++; + } + else + { + printf("sender_thread: mq_send succeeded on msg %d\n", i); + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("sender_thread: ERROR mq_close failed\n"); + } + + printf("sender_thread: returning nerrors=%d\n", nerrors); + return (pthread_addr_t)nerrors; +} + +static void *receiver_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int nbytes; + int nerrors = 0; + int i; + + printf("receiver_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = 20; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this task tries to read from the queue when the queue is empty + * + * O_CREAT - the queue will get created if it does not already exist. + * O_RDONLY - we are only planning to read from the queue. + * + * Open the queue, and create it if the sending process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_RDONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("receiver_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Perform the receive TEST_RECEIVE_NMSGS times */ + + for (i = 0; i < TEST_RECEIVE_NMSGS; i++) + { + memset(msg_buffer, 0xaa, TEST_MSGLEN); + nbytes = mq_receive(mqfd, msg_buffer, TEST_MSGLEN, 0); + if (nbytes < 0) + { + /* mq_receive failed. If the error is because of EINTR then + * it is not a failure. + */ + + if (errno != EINTR) + { + printf("receiver_thread: ERROR mq_receive failure on msg %d, errno=%d\n", i, errno); + nerrors++; + } + else + { + printf("receiver_thread: mq_receive interrupted!\n"); + } + } + else if (nbytes != TEST_MSGLEN) + { + printf("receiver_thread: mq_receive return bad size %d on msg %d\n", nbytes, i); + nerrors++; + } + else if (memcmp(TEST_MESSAGE, msg_buffer, nbytes) != 0) + { + int j; + + printf("receiver_thread: mq_receive returned corrupt message on msg %d\n", i); + printf("receiver_thread: i Expected Received\n"); + + for (j = 0; j < TEST_MSGLEN-1; j++) + { + if (isprint(msg_buffer[j])) + { + printf("receiver_thread: %2d %02x (%c) %02x (%c)\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j], msg_buffer[j]); + } + else + { + printf("receiver_thread: %2d %02x (%c) %02x\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j]); + } + } + printf("receiver_thread: %2d 00 %02x\n", + j, msg_buffer[j]); + } + else + { + printf("receiver_thread: mq_receive succeeded on msg %d\n", i); + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + /* Destroy the queue */ + + if (mq_unlink("testmq") < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + printf("receiver_thread: returning nerrors=%d\n", nerrors); + pthread_exit((pthread_addr_t)nerrors); + return (pthread_addr_t)nerrors; +} + +void mqueue_test(void) +{ + pthread_t sender; + pthread_t receiver; + void *result; + pthread_attr_t attr; + struct sched_param sparam; + int prio_min; + int prio_max; + int prio_mid; + int status; + + /* Start the sending thread at higher priority */ + + printf("mqueue_test: Starting receiver\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("mqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("mqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + prio_min = sched_get_priority_min(SCHED_FIFO); + prio_max = sched_get_priority_max(SCHED_FIFO); + prio_mid = (prio_min + prio_max) / 2; + + sparam.sched_priority = prio_mid; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("mqueue_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("mqueue_test: Set receiver priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&receiver, &attr, receiver_thread, NULL); + if (status != 0) + { + printf("mqueue_test: pthread_create failed, status=%d\n", status); + } + + /* Start the sending thread at lower priority */ + + printf("mqueue_test: Starting sender\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("mqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("mqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + sparam.sched_priority = (prio_min + prio_mid) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("mqueue_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("mqueue_test: Set sender thread priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&sender, &attr, sender_thread, NULL); + if (status != 0) + { + printf("mqueue_test: pthread_create failed, status=%d\n", status); + } + + printf("mqueue_test: Waiting for sender to complete\n"); + pthread_join(sender, &result); + if (result != (void*)0) + { + printf("mqueue_test: ERROR sender thread exited with %d errors\n", (int)result); + } + +#ifndef CONFIG_DISABLE_SIGNALS + /* Wake up the receiver thread with a signal */ + + printf("mqueue_test: Killing receiver\n"); + pthread_kill(receiver, 9); + + /* Wait a bit to see if the thread exits on its own */ + + usleep(HALF_SECOND_USEC_USEC); +#endif + + /* Then cancel the thread and see if it did */ + + printf("mqueue_test: Canceling receiver\n"); + status = pthread_cancel(receiver); + if (status == ESRCH) + { + printf("mqueue_test: receiver has already terminated\n"); + } + + pthread_join(receiver, &result); + if (result != (void*)0) + { + printf("mqueue_test: ERROR receiver thread exited with %d errors\n", (int)result); + } +} + + diff --git a/apps/examples/ostest/mutex.c b/apps/examples/ostest/mutex.c new file mode 100644 index 000000000..752f833f2 --- /dev/null +++ b/apps/examples/ostest/mutex.c @@ -0,0 +1,142 @@ +/*********************************************************************** + * mutex.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <pthread.h> +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define NLOOPS 32 + +static pthread_mutex_t mut; +static volatile int my_mutex = 0; +static unsigned long nloops[2] = {0, 0}; +static unsigned long nerrors[2] = {0, 0}; + +static void *thread_func(void *parameter) +{ + int id = (int)parameter; + int ndx = id - 1; + int i; + + for (nloops[ndx] = 0; nloops[ndx] < NLOOPS; nloops[ndx]++) + { + int status = pthread_mutex_lock(&mut); + if (status != 0) + { + printf("ERROR thread %d: pthread_mutex_lock failed, status=%d\n", + id, status); + } + + if (my_mutex == 1) + { + printf("ERROR thread=%d: " + "my_mutex should be zero, instead my_mutex=%d\n", + id, my_mutex); + nerrors[ndx]++; + } + + my_mutex = 1; + for (i = 0; i < 10; i++) + { + pthread_yield(); + } + my_mutex = 0; + + status = pthread_mutex_unlock(&mut); + if (status != 0) + { + printf("ERROR thread %d: pthread_mutex_unlock failed, status=%d\n", + id, status); + } + } + pthread_exit(NULL); + return NULL; /* Non-reachable -- needed for some compilers */ +} + +void mutex_test(void) +{ + pthread_t thread1, thread2; +#ifdef SDCC + pthread_addr_t result1, result2; + pthread_attr_t attr; +#endif + int status; + + /* Initialize the mutex */ + + printf("Initializing mutex\n"); + pthread_mutex_init(&mut, NULL); + + /* Start two thread instances */ + + printf("Starting thread 1\n"); +#ifdef SDCC + (void)pthread_attr_init(&attr); + status = pthread_create(&thread1, &attr, thread_func, (pthread_addr_t)1); +#else + status = pthread_create(&thread1, NULL, thread_func, (pthread_addr_t)1); +#endif + if (status != 0) + { + printf("Error in thread#1 creation\n"); + } + + printf("Starting thread 2\n"); +#ifdef SDCC + status = pthread_create(&thread2, &attr, thread_func, (pthread_addr_t)2); +#else + status = pthread_create(&thread2, NULL, thread_func, (pthread_addr_t)2); +#endif + if (status != 0) + { + printf("Error in thread#2 creation\n"); + } + +#ifdef SDCC + pthread_join(thread1, &result1); + pthread_join(thread2, &result2); +#else + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); +#endif + + printf("\t\tThread1\tThread2\n"); + printf("\tLoops\t%ld\t%ld\n", nloops[0], nloops[1]); + printf("\tErrors\t%ld\t%ld\n", nerrors[0], nerrors[1]); +} diff --git a/apps/examples/ostest/ostest.h b/apps/examples/ostest/ostest.h new file mode 100644 index 000000000..a4af37f05 --- /dev/null +++ b/apps/examples/ostest/ostest.h @@ -0,0 +1,178 @@ +/**************************************************************************** + * apps/examples/ostest/ostest.h + * + * 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 + * 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_OSTEST_OSTEST_H +#define __APPS_EXAMPLES_OSTEST_OSTEST_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The task_create task size can be specified in the defconfig file */ + +#ifdef CONFIG_EXAMPLES_OSTEST_STACKSIZE +# define STACKSIZE CONFIG_EXAMPLES_OSTEST_STACKSIZE +#else +# define STACKSIZE 8192 +#endif + +/* The number of times to execute the test can be specified in the defconfig + * file. + */ + +#ifndef CONFIG_EXAMPLES_OSTEST_LOOPS +# define CONFIG_EXAMPLES_OSTEST_LOOPS 1 +#endif + +/* This is the number of threads that are created in the barrier test. + * A smaller number should be selected on systems without sufficient memory + * to start so many threads. + */ + +#ifndef CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS +# define CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS 8 +#endif + +/* Priority inheritance */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG) +# define dump_nfreeholders(s) printf(s " nfreeholders: %d\n", sem_nfreeholders()) +#else +# define dump_nfreeholders(s) +#endif + +/* If CONFIG_STDIO_LINEBUFFER is defined, the STDIO buffer will be flushed + * on each new line. Otherwise, STDIO needs to be explicitly flushed to + * see the output in context. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && \ + CONFIG_STDIO_BUFFER_SIZE > 0 && !defined(CONFIG_STDIO_LINEBUFFER) +# define FFLUSH() fflush(stdout) +#else +# define FFLUSH() +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* dev_null.c ***************************************************************/ + +extern int dev_null(void); + +/* fpu.c ********************************************************************/ + +extern void fpu_test(void); + +/* mutex.c ******************************************************************/ + +extern void mutex_test(void); + +/* rmutex.c ******************************************************************/ + +extern void recursive_mutex_test(void); + +/* sem.c ********************************************************************/ + +extern void sem_test(void); + +/* cond.c *******************************************************************/ + +extern void cond_test(void); + +/* mqueue.c *****************************************************************/ + +extern void mqueue_test(void); + +/* timedmqueue.c ************************************************************/ + +extern void timedmqueue_test(void); + +/* cancel.c *****************************************************************/ + +extern void cancel_test(void); + +/* timedwait.c **************************************************************/ + +extern void timedwait_test(void); + +/* sighand.c ****************************************************************/ + +extern void sighand_test(void); + +/* posixtimers.c ************************************************************/ + +extern void timer_test(void); + +/* roundrobin.c *************************************************************/ + +extern void rr_test(void); + +/* barrier.c ****************************************************************/ + +extern void barrier_test(void); + +/* prioinherit.c ************************************************************/ + +extern void priority_inheritance(void); + +/* APIs exported (conditionally) by the OS specifically for testing of + * priority inheritance + */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG) +extern void sem_enumholders(FAR sem_t *sem); +extern int sem_nfreeholders(void); +#else +# define sem_enumholders(sem) +# define sem_nfreeholders() +#endif + +#endif /* __APPS_EXAMPLES_OSTEST_OSTEST_H */ diff --git a/apps/examples/ostest/posixtimer.c b/apps/examples/ostest/posixtimer.c new file mode 100644 index 000000000..3560c712b --- /dev/null +++ b/apps/examples/ostest/posixtimer.c @@ -0,0 +1,262 @@ +/*********************************************************************** + * examples/ostest/posixtimer.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <unistd.h> +#include <semaphore.h> +#include <signal.h> +#include <sched.h> +#include <errno.h> +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define MY_TIMER_SIGNAL 17 +#define SIGVALUE_INT 42 + +/************************************************************************** + * Private Data + **************************************************************************/ + +static sem_t sem; +static int g_nsigreceived = 0; + +/************************************************************************** + * Private Functions + **************************************************************************/ + +static void timer_expiration(int signo, siginfo_t *info, void *ucontext) +{ + sigset_t oldset; + sigset_t allsigs; + int status; + + printf("timer_expiration: Received signal %d\n" , signo); + + g_nsigreceived++; + + /* Check signo */ + + if (signo != MY_TIMER_SIGNAL) + { + printf("timer_expiration: ERROR expected signo=%d\n" , MY_TIMER_SIGNAL); + } + + /* Check siginfo */ + + if (info->si_value.sival_int != SIGVALUE_INT) + { + printf("timer_expiration: ERROR sival_int=%d expected %d\n", + info->si_value.sival_int, SIGVALUE_INT); + } + else + { + printf("timer_expiration: sival_int=%d\n" , info->si_value.sival_int); + } + + if (info->si_signo != MY_TIMER_SIGNAL) + { + printf("timer_expiration: ERROR expected si_signo=%d, got=%d\n", + MY_TIMER_SIGNAL, info->si_signo); + } + + if (info->si_code == SI_TIMER) + { + printf("timer_expiration: si_code=%d (SI_TIMER)\n" , info->si_code); + } + else + { + printf("timer_expiration: ERROR si_code=%d, expected SI_TIMER=%d\n", + info->si_code, SI_TIMER); + } + + /* Check ucontext_t */ + + printf("timer_expiration: ucontext=%p\n" , ucontext); + + /* Check sigprocmask */ + + (void)sigfillset(&allsigs); + status = sigprocmask(SIG_SETMASK, NULL, &oldset); + if (status != OK) + { + printf("timer_expiration: ERROR sigprocmask failed, status=%d\n", + status); + } + + if (oldset != allsigs) + { + printf("timer_expiration: ERROR sigprocmask=%x expected=%x\n", + oldset, allsigs); + } + +} + +/************************************************************************** + * Public Functions + **************************************************************************/ + +void timer_test(void) +{ + sigset_t sigset; + struct sigaction act; + struct sigaction oact; + struct sigevent notify; + struct itimerspec timer; + timer_t timerid; + int status; + int i; + + printf("timer_test: Initializing semaphore to 0\n" ); + sem_init(&sem, 0, 0); + + /* Start waiter thread */ + + printf("timer_test: Unmasking signal %d\n" , MY_TIMER_SIGNAL); + + (void)sigemptyset(&sigset); + (void)sigaddset(&sigset, MY_TIMER_SIGNAL); + status = sigprocmask(SIG_UNBLOCK, &sigset, NULL); + if (status != OK) + { + printf("timer_test: ERROR sigprocmask failed, status=%d\n", + status); + } + + printf("timer_test: Registering signal handler\n" ); + act.sa_sigaction = timer_expiration; + act.sa_flags = SA_SIGINFO; + + (void)sigfillset(&act.sa_mask); + (void)sigdelset(&act.sa_mask, MY_TIMER_SIGNAL); + + status = sigaction(MY_TIMER_SIGNAL, &act, &oact); + if (status != OK) + { + printf("timer_test: ERROR sigaction failed, status=%d\n" , status); + } + +#ifndef SDCC + printf("timer_test: oact.sigaction=%p oact.sa_flags=%x oact.sa_mask=%x\n", + oact.sa_sigaction, oact.sa_flags, oact.sa_mask); +#endif + + /* Create the POSIX timer */ + + printf("timer_test: Creating timer\n" ); + + notify.sigev_notify = SIGEV_SIGNAL; + notify.sigev_signo = MY_TIMER_SIGNAL; + notify.sigev_value.sival_int = SIGVALUE_INT; + + status = timer_create(CLOCK_REALTIME, ¬ify, &timerid); + if (status != OK) + { + printf("timer_test: timer_create failed, errno=%d\n", errno); + goto errorout; + } + + /* Start the POSIX timer */ + + printf("timer_test: Starting timer\n" ); + + timer.it_value.tv_sec = 2; + timer.it_value.tv_nsec = 0; + timer.it_interval.tv_sec = 2; + timer.it_interval.tv_nsec = 0; + + status = timer_settime(timerid, 0, &timer, NULL); + if (status != OK) + { + printf("timer_test: timer_settime failed, errno=%d\n", errno); + goto errorout; + } + + /* Take the semaphore */ + + for (i = 0; i < 5; i++) + { + printf("timer_test: Waiting on semaphore\n" ); + FFLUSH(); + status = sem_wait(&sem); + if (status != 0) + { + int error = errno; + if (error == EINTR) + { + printf("timer_test: sem_wait() successfully interrupted by signal\n" ); + } + else + { + printf("timer_test: ERROR sem_wait failed, errno=%d\n" , error); + } + } + else + { + printf("timer_test: ERROR awakened with no error!\n" ); + } + printf("timer_test: g_nsigreceived=%d\n", g_nsigreceived); + } + +errorout: + sem_destroy(&sem); + + /* Then delete the timer */ + + printf("timer_test: Deleting timer\n" ); + status = timer_delete(timerid); + if (status != OK) + { + printf("timer_test: timer_create failed, errno=%d\n", errno); + } + + /* Detach the signal handler */ + + act.sa_sigaction = SIG_DFL; + status = sigaction(MY_TIMER_SIGNAL, &act, &oact); + + printf("timer_test: done\n" ); + FFLUSH(); +} diff --git a/apps/examples/ostest/prioinherit.c b/apps/examples/ostest/prioinherit.c new file mode 100644 index 000000000..993c9e14a --- /dev/null +++ b/apps/examples/ostest/prioinherit.c @@ -0,0 +1,541 @@ +/**************************************************************************** + * examples/ostest/prioinherit.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <unistd.h> +#include <semaphore.h> +#include <pthread.h> +#include <errno.h> + +#ifdef CONFIG_ARCH_SIM +# include <nuttx/arch.h> +#endif + +#include "ostest.h" + +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifndef CONFIG_SEM_PREALLOCHOLDERS +# define CONFIG_SEM_PREALLOCHOLDERS 0 +#endif +#define NLOWPRI_THREADS (CONFIG_SEM_PREALLOCHOLDERS+1) + +#ifndef CONFIG_SEM_NNESTPRIO +# define CONFIG_SEM_NNESTPRIO 0 +#endif +#define NHIGHPRI_THREADS (CONFIG_SEM_NNESTPRIO+1) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +enum thstate_e +{ + NOTSTARTED = 0, + RUNNING, + WAITING, + DONE +}; + +static sem_t g_sem; +static volatile enum thstate_e g_middlestate; +static volatile enum thstate_e g_highstate[NHIGHPRI_THREADS]; +static volatile enum thstate_e g_lowstate[NLOWPRI_THREADS]; +static int g_highpri; +static int g_medpri; +static int g_lowpri; + +/**************************************************************************** + * Name: nhighpri_waiting + ****************************************************************************/ + +static int nhighpri_waiting(void) +{ + int n = 0; + int i; + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + if (g_highstate[i] == WAITING) + { + n++; + } + } + return n; +} + +/**************************************************************************** + * Name: nhighpri_running + ****************************************************************************/ + +static int nhighpri_running(void) +{ + int n = 0; + int i; + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + if (g_highstate[i] != DONE) + { + n++; + } + } + return n; +} + +/**************************************************************************** + * Name: highpri_thread + ****************************************************************************/ + +static void *highpri_thread(void *parameter) +{ + int threadno = (int)parameter; + int ret; + + g_highstate[threadno-1] = RUNNING; + + printf("highpri_thread-%d: Started\n", threadno); + FFLUSH(); + sleep(1); + + printf("highpri_thread-%d: Calling sem_wait()\n", threadno); + g_highstate[threadno-1] = WAITING; + ret = sem_wait(&g_sem); + g_highstate[threadno-1] = DONE; + + if (ret != 0) + { + printf("highpri_thread-%d: sem_take failed: %d\n", threadno, ret); + } + else if (g_middlestate == RUNNING) + { + printf("highpri_thread-%d: SUCCESS midpri_thread is still running!\n", threadno); + } + else + { + printf("highpri_thread-%d: ERROR -- midpri_thread has already exited!\n", threadno); + } + + sem_post(&g_sem); + printf("highpri_thread-%d: Okay... I'm done!\n", threadno); + FFLUSH(); + return NULL; +} + +/**************************************************************************** + * Name: hog_cpu + ****************************************************************************/ + +static inline void hog_cpu(void) +{ +#ifdef CONFIG_ARCH_SIM + /* The simulator doesn't have any mechanism to do asynchronous pre-emption + * (basically because it doesn't have any interupts/asynchronous events). + * The simulator does "fake" a timer interrupt in up_idle() -- the idle + * thread that only executes when nothing else is running. In the simulator, + * we cannot suspend the middle priority task, or we wouldn't have the + * test that we want. So, we have no option but to pump the fake clock + * here by calling up_idle(). Sigh! + */ + + up_idle(); +#else + /* On real platforms with a real timer interrupt, we really can hog the + * CPU. When the sleep() goes off in priority_inheritance(), it will + * wake up and start the high priority thread. + */ + + volatile int i; + for (i = 0; i < INT_MAX; i++); +#endif +} + +/**************************************************************************** + * Name: medpri_thread + ****************************************************************************/ + +static void *medpri_thread(void *parameter) +{ + printf("medpri_thread: Started ... I won't let go of the CPU!\n"); + g_middlestate = RUNNING; + FFLUSH(); + + /* The following loop will completely block lowpri_thread from running. + * UNLESS priority inheritance is working. In that case, its priority + * will be boosted. + */ + + while (nhighpri_running() > 0) + { + hog_cpu(); + } + + printf("medpri_thread: Okay... I'm done!\n"); + FFLUSH(); + g_middlestate = DONE; + return NULL; +} + +/**************************************************************************** + * Name: lowpri_thread + ****************************************************************************/ + +static void *lowpri_thread(void *parameter) +{ + void *retval = (void*)-1; + struct sched_param sparam; + int threadno = (int)parameter; + int expected; + int count; + int policy; + int ret; + int nwaiting; + int i; + + g_lowstate[threadno-1] = RUNNING; + printf("lowpri_thread-%d: Started\n", threadno); + + ret = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (ret != 0) + { + printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret); + } + else + { + printf("lowpri_thread-%d: initial priority: %d\n", threadno, sparam.sched_priority); + if (sparam.sched_priority != g_lowpri) + { + printf(" ERROR should have been %d\n", g_lowpri); + } + } + + g_lowstate[threadno-1] = WAITING; + ret = sem_wait(&g_sem); + if (ret != 0) + { + printf("lowpri_thread-%d: sem_take failed: %d\n", threadno, ret); + } + else + { + /* Hang on to the thread until the middle priority thread runs */ + + while (g_middlestate == NOTSTARTED && nhighpri_waiting() < NHIGHPRI_THREADS) + { + printf("lowpri_thread-%d: Waiting for the midle pri task to run\n", threadno); + printf(" g_middlestate: %d\n", (int)g_middlestate); + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + printf(" g_highstate[%d]: %d\n", i, (int)g_highstate[i]); + } + printf(" I still have a count on the semaphore\n"); + sem_enumholders(&g_sem); + FFLUSH(); + sleep(1); + } + + /* Account for all of the semaphore counts. At any given time if there are 'n' + * running hight prioity tasks, then the semaphore count should be '-n' + */ + + sched_lock(); /* Needs to be atomic */ + ret = sem_getvalue(&g_sem, &count); + nwaiting = nhighpri_waiting(); + sched_unlock(); + + if (ret < 0) + { + printf("lowpri_thread-%d: ERROR sem_getvalue failed: %d\n", threadno, errno); + } + printf("lowpri_thread-%d: Sem count: %d, No. highpri thread: %d\n", threadno, count, nwaiting); + + /* The middle priority task is running, let go of the semaphore */ + + if (g_middlestate == RUNNING && nwaiting == -count) + { + /* Good.. the middle priority task is still running and the counts are okay. */ + + retval = NULL; + } + else + { + /* If the sem count is positive, then there all of the higher priority threads + * should have already completed. + */ + + printf("lowpri_thread-%d: %s the middle priority task has already exitted!\n", + threadno, count >= 0 ? "SUCCESS" : "ERROR" ); + printf(" g_middlestate: %d sem count=%d\n", (int)g_middlestate, count); + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + printf(" g_highstate[%d]: %d\n", i, (int)g_highstate[i]); + } + } + } + + ret = pthread_getschedparam(pthread_self(), &policy, &sparam); + sem_enumholders(&g_sem); + sem_post(&g_sem); + if (ret != 0) + { + printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret); + } + else + { + if (nwaiting > 0) + { + expected = g_highpri; + } + else + { + expected = g_lowpri; + } + + printf("lowpri_thread-%d: %s priority before sem_post: %d\n", + threadno, + sparam.sched_priority != expected ? "ERROR" : "SUCCESS", + sparam.sched_priority); + + if (sparam.sched_priority != expected) + { + printf(" ERROR should have been %d\n", expected); + } + } + + ret = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (ret != 0) + { + printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret); + } + else + { + printf("lowpri_thread-%d: %s final priority: %d\n", + threadno, + sparam.sched_priority != g_lowpri ? "ERROR" : "SUCCESS", + sparam.sched_priority); + + if (sparam.sched_priority != g_lowpri) + { + printf(" ERROR should have been %d\n", g_lowpri); + } + } + sem_enumholders(&g_sem); + + printf("lowpri_thread-%d: Okay... I'm done!\n", threadno); + FFLUSH(); + g_lowstate[threadno-1] = DONE; + return retval; +} +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: priority_inheritance + ****************************************************************************/ + +void priority_inheritance(void) +{ +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + pthread_t lowpri[NLOWPRI_THREADS]; + pthread_t medpri; + pthread_t highpri[NHIGHPRI_THREADS]; + pthread_addr_t result; + pthread_attr_t attr; + struct sched_param sparam; + int my_pri; + int status; + int i; + + printf("priority_inheritance: Started\n"); + + g_middlestate = NOTSTARTED; + for (i = 0; i < NHIGHPRI_THREADS; i++) g_highstate[i] = NOTSTARTED; + for (i = 0; i < NLOWPRI_THREADS; i++) g_lowstate[i] = NOTSTARTED; + + status = sched_getparam (getpid(), &sparam); + if (status != 0) + { + printf("priority_inheritance: sched_getparam failed\n"); + sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY; + } + my_pri = sparam.sched_priority; + + g_highpri = sched_get_priority_max(SCHED_FIFO); + g_lowpri = sched_get_priority_min(SCHED_FIFO); + g_medpri = my_pri - 1; + + sem_init(&g_sem, 0, NLOWPRI_THREADS); + dump_nfreeholders("priority_inheritance:"); + + /* Start the low priority threads */ + + for (i = 0; i < NLOWPRI_THREADS; i++) + { + int threadno = i+1; + printf("priority_inheritance: Starting lowpri_thread-%d (of %d) at %d\n", + threadno, NLOWPRI_THREADS, g_lowpri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + sparam.sched_priority = g_lowpri; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set lowpri_thread-%d priority to %d\n", + threadno, sparam.sched_priority); + } + + status = pthread_create(&lowpri[i], &attr, lowpri_thread, (void*)threadno); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + } + printf("priority_inheritance: Waiting...\n"); + sleep(2); + dump_nfreeholders("priority_inheritance:"); + + /* Start the medium priority thread */ + + printf("priority_inheritance: Starting medpri_thread at %d\n", g_medpri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = g_medpri; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set medpri_thread priority to %d\n", sparam.sched_priority); + } + FFLUSH(); + + status = pthread_create(&medpri, &attr, medpri_thread, NULL); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + printf("priority_inheritance: Waiting...\n"); + sleep(1); + dump_nfreeholders("priority_inheritance:"); + + /* Start the high priority threads */ + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + int threadno = i+1; + printf("priority_inheritance: Starting highpri_thread-%d (of %d) at %d\n", + threadno, NHIGHPRI_THREADS, g_highpri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = g_highpri - i; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set highpri_thread-%d priority to %d\n", + threadno, sparam.sched_priority); + } + FFLUSH(); + + status = pthread_create(&highpri[i], &attr, highpri_thread, (void*)threadno); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + } + dump_nfreeholders("priority_inheritance:"); + FFLUSH(); + + /* Wait for all thread instances to complete */ + + for (i = 0; i < NHIGHPRI_THREADS; i++) + { + printf("priority_inheritance: Waiting for highpri_thread-%d to complete\n", i+1); + FFLUSH(); + (void)pthread_join(highpri[i], &result); + dump_nfreeholders("priority_inheritance:"); + } + printf("priority_inheritance: Waiting for medpri_thread to complete\n"); + FFLUSH(); + (void)pthread_join(medpri, &result); + dump_nfreeholders("priority_inheritance:"); + for (i = 0; i < NLOWPRI_THREADS; i++) + { + printf("priority_inheritance: Waiting for lowpri_thread-%d to complete\n", i+1); + FFLUSH(); + (void)pthread_join(lowpri[i], &result); + dump_nfreeholders("priority_inheritance:"); + } + + printf("priority_inheritance: Finished\n"); + sem_destroy(&g_sem); + dump_nfreeholders("priority_inheritance:"); + FFLUSH(); +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ +} diff --git a/apps/examples/ostest/rmutex.c b/apps/examples/ostest/rmutex.c new file mode 100644 index 000000000..44eb4bb3b --- /dev/null +++ b/apps/examples/ostest/rmutex.c @@ -0,0 +1,166 @@ +/*********************************************************************** + * rmutex.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <pthread.h> +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define NTHREADS 3 +#define NLOOPS 3 +#define NRECURSIONS 3 + +static pthread_mutex_t mut; + +static void thread_inner(int id, int level) +{ + int status; + if (level < NRECURSIONS) + { + /* Take the mutex */ + + printf("thread_inner[%d, %d]: Locking\n", id, level); + status = pthread_mutex_lock(&mut); + if (status != 0) + { + printf("thread_inner[%d, %d]: ERROR pthread_mutex_lock failed: %d\n", + id, level, status); + } + printf("thread_inner[%d, %d]: Locked\n", id, level); + + /* Give the other threads a chance */ + + pthread_yield(); + thread_inner(id, level+1); + pthread_yield(); + + /* Unlock the mutex */ + + printf("thread_inner[%d, %d]: Unlocking\n", id, level); + status = pthread_mutex_unlock(&mut); + if (status != 0) + { + printf("thread_inner[%d, %d]: ERROR pthread_mutex_unlock failed: %d\n", + id, level, status); + } + printf("thread_inner[%d, %d]: Unlocked\n", id, level); + pthread_yield(); + } +} + +static void *thread_outer(void *parameter) +{ + int i; + printf("thread_outer[%d]: Started\n", (int)parameter); + for (i = 0; i < NLOOPS; i++) + { + printf("thread_outer[%d]: Loop %d\n", (int)parameter, i); + thread_inner((int)parameter, 0); + } + printf("thread_outer[%d]: Exitting\n", (int)parameter); + pthread_exit(NULL); + return NULL; /* Non-reachable -- needed for some compilers */ +} + +void recursive_mutex_test(void) +{ + pthread_t thread[NTHREADS]; +#ifdef SDCC + pthread_addr_t result[NTHREADS]; + pthread_attr_t attr; +#endif + pthread_mutexattr_t mattr; + int type; + int status; + int i; + + /* Initialize the mutex attributes */ + + pthread_mutexattr_init(&mattr); + status = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); + if (status != 0) + { + printf("recursive_mutex_test: ERROR pthread_mutexattr_settype failed, status=%d\n", status); + } + + status = pthread_mutexattr_gettype(&mattr, &type); + if (status != 0) + { + printf("recursive_mutex_test: ERROR pthread_mutexattr_gettype failed, status=%d\n", status); + } + if (type != PTHREAD_MUTEX_RECURSIVE) + { + printf("recursive_mutex_test: ERROR pthread_mutexattr_gettype return type=%d\n", type); + } + + /* Initialize the mutex */ + + printf("recursive_mutex_test: Initializing mutex\n"); + pthread_mutex_init(&mut, &mattr); + + /* Start the threads -- all at the same, default priority */ + + for (i = 0; i < NTHREADS; i++) + { + printf("recursive_mutex_test: Starting thread %d\n", i+1); +#ifdef SDCC + (void)pthread_attr_init(&attr); + status = pthread_create(&thread[i], &attr, thread_outer, (pthread_addr_t)i+1); +#else + status = pthread_create(&thread[i], NULL, thread_outer, (pthread_addr_t)i+1); +#endif + if (status != 0) + { + printf("recursive_mutex_test: ERRROR thread#%d creation: %d\n", i+1, status); + } + } + + /* Wait for all; of the threads to complete */ + + for (i = 0; i < NTHREADS; i++) + { + printf("recursive_mutex_test: Waiting for thread %d\n", i+1); +#ifdef SDCC + pthread_join(thread[i], &result1); +#else + pthread_join(thread[i], NULL); +#endif + } + + printf("recursive_mutex_test: Complete\n"); +} diff --git a/apps/examples/ostest/roundrobin.c b/apps/examples/ostest/roundrobin.c new file mode 100644 index 000000000..061d51f3d --- /dev/null +++ b/apps/examples/ostest/roundrobin.c @@ -0,0 +1,232 @@ +/******************************************************************************** + * examples/ostest/roundrobin.c + * + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include "ostest.h" + +#if CONFIG_RR_INTERVAL > 0 + +/******************************************************************************** + * Definitions + ********************************************************************************/ + +/* This number may need to be tuned for different processor speeds. Since these + * arrays must be large to very correct SCHED_RR behavior, this test may require + * too much memory on many targets. + */ + +/* #define CONFIG_NINTEGERS 32768 Takes forever on 60Mhz ARM7 */ + +#define CONFIG_NINTEGERS 2048 + +/******************************************************************************** + * Private Data + ********************************************************************************/ + +static int prime1[CONFIG_NINTEGERS]; +static int prime2[CONFIG_NINTEGERS]; + +/******************************************************************************** + * Private Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: dosieve + * + * Description + * This implements a "sieve of aristophanes" algorithm for finding prime number. + * Credit for this belongs to someone, but I am not sure who anymore. Anyway, + * the only purpose here is that we need some algorithm that takes a long period + * of time to execute. + * + ********************************************************************************/ + +static void dosieve(int *prime) +{ + int a,d; + int i; + int j; + + a = 2; + d = a; + + for (i = 0; i < CONFIG_NINTEGERS; i++) + { + prime[i] = i+2; + } + + for (i = 1; i < 10; i++) + { + for (j = 0; j < CONFIG_NINTEGERS; j++) + { + d = a + d; + if (d < CONFIG_NINTEGERS) + { + prime[d]=0; + } + } + a++; + d = a; + i++; + } + +#if 0 /* We don't really care what the numbers are */ + for (i = 0, j= 0; i < CONFIG_NINTEGERS; i++) + { + if (prime[i] != 0) + { + printf(" Prime %d: %d\n", j, prime[i]); + j++; + } + } +#endif +} + +/******************************************************************************** + * Name: sieve1 + ********************************************************************************/ + +static void *sieve1(void *parameter) +{ + int i; + + printf("sieve1 started\n"); + + for (i = 0; i < 1000; i++) + { + dosieve(prime1); + } + + printf("sieve1 finished\n"); + + pthread_exit(NULL); + return NULL; /* To keep some compilers happy */ +} + +/******************************************************************************** + * Name: sieve2 + ********************************************************************************/ + +static void *sieve2(void *parameter) +{ + int i; + + printf("sieve2 started\n"); + + for (i = 0; i < 1000; i++) + { + dosieve(prime2); + } + + printf("sieve2 finished\n"); + + pthread_exit(NULL); + return NULL; /* To keep some compilers happy */ +} + +/******************************************************************************** + * Public Functions + ********************************************************************************/ + +/******************************************************************************** + * Name: rr_test + ********************************************************************************/ + +void rr_test(void) +{ + pthread_t sieve1_thread; + pthread_t sieve2_thread; + struct sched_param sparam; + pthread_attr_t attr; + pthread_addr_t result; + int status; + + printf("rr_test: Starting sieve1 thread \n"); + status = pthread_attr_init(&attr); + if (status != OK) + { + printf("rr_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = sched_get_priority_min(SCHED_FIFO); + status = pthread_attr_setschedparam(&attr, &sparam); + if (status != OK) + { + printf("rr_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("rr_test: Set thread priority to %d\n", sparam.sched_priority); + } + + status = pthread_attr_setschedpolicy(&attr, SCHED_RR); + if (status != OK) + { + printf("rr_test: pthread_attr_setschedpolicy failed, status=%d\n", status); + } + else + { + printf("rr_test: Set thread policty to SCHED_RR\n"); + } + + status = pthread_create(&sieve1_thread, &attr, sieve1, NULL); + if (status != 0) + { + printf("rr_test: Error in thread 1 creation, status=%d\n", status); + } + + printf("rr_test: Starting sieve1 thread \n"); + + status = pthread_create(&sieve2_thread, &attr, sieve2, NULL); + if (status != 0) + { + printf("rr_test: Error in thread 2 creation, status=%d\n", status); + } + + printf("rr_test: Waiting for sieves to complete -- this should take awhile\n"); + printf("rr_test: If RR scheduling is working, they should start and complete at\n"); + printf("rr_test: about the same time\n"); + + pthread_join(sieve2_thread, &result); + pthread_join(sieve1_thread, &result); + printf("rr_test: Done\n"); +} + +#endif /* CONFIG_RR_INTERVAL */ diff --git a/apps/examples/ostest/sem.c b/apps/examples/ostest/sem.c new file mode 100644 index 000000000..850cf8040 --- /dev/null +++ b/apps/examples/ostest/sem.c @@ -0,0 +1,246 @@ +/*********************************************************************** + * sem.c + * + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <pthread.h> +#include <semaphore.h> +#include <sched.h> +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +static sem_t sem; + +static void *waiter_func(void *parameter) +{ + int id = (int)parameter; + int status; + int value; + + printf("waiter_func: Thread %d Started\n", id); + + /* Take the semaphore */ + + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("waiter_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("waiter_func: Thread %d initial semaphore value = %d\n", id, value); + } + + printf("waiter_func: Thread %d waiting on semaphore\n", id); + status = sem_wait(&sem); + if (status != 0) + { + printf("waiter_func: ERROR thread %d sem_wait failed\n", id); + } + printf("waiter_func: Thread %d awakened\n", id); + + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("waiter_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("waiter_func: Thread %d new semaphore value = %d\n", id, value); + } + + printf("waiter_func: Thread %d done\n", id); + return NULL; +} + +static void *poster_func(void *parameter) +{ + int id = (int)parameter; + int status; + int value; + + printf("poster_func: Thread %d started\n", id); + + /* Take the semaphore */ + + do + { + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("poster_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("poster_func: Thread %d semaphore value = %d\n", id, value); + } + + if (value < 0) + { + printf("poster_func: Thread %d posting semaphore\n", id); + status = sem_post(&sem); + if (status != 0) + { + printf("poster_func: ERROR thread %d sem_wait failed\n", id); + } + + pthread_yield(); + + status = sem_getvalue(&sem, &value); + if (status < 0) + { + printf("poster_func: ERROR thread %d could not get semaphore value\n", id); + } + else + { + printf("poster_func: Thread %d new semaphore value = %d\n", id, value); + } + } + } + while (value < 0); + + printf("poster_func: Thread %d done\n", id); + return NULL; + +} + +void sem_test(void) +{ + pthread_t waiter_thread1; + pthread_t waiter_thread2; + pthread_t poster_thread; +#ifdef SDCC + pthread_addr_t result; +#endif + struct sched_param sparam; + int prio_min; + int prio_max; + int prio_mid; + pthread_attr_t attr; + int status; + + printf("sem_test: Initializing semaphore to 0\n"); + sem_init(&sem, 0, 0); + + /* Start two waiter thread instances */ + + printf("sem_test: Starting waiter thread 1\n"); + status = pthread_attr_init(&attr); + if (status != OK) + { + printf("sem_test: pthread_attr_init failed, status=%d\n", status); + } + + prio_min = sched_get_priority_min(SCHED_FIFO); + prio_max = sched_get_priority_max(SCHED_FIFO); + prio_mid = (prio_min + prio_max) / 2; + + sparam.sched_priority = (prio_mid + prio_max) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("sem_test: Set thread 1 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter_thread1, &attr, waiter_func, (pthread_addr_t)1); + if (status != 0) + { + printf("sem_test: Error in thread 1 creation, status=%d\n", status); + } + + printf("sem_test: Starting waiter thread 2\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("sem_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = prio_mid; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("sem_test: Set thread 2 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter_thread2, &attr, waiter_func, (pthread_addr_t)2); + if (status != 0) + { + printf("sem_test: Error in thread 2 creation, status=%d\n", status); + } + + printf("sem_test: Starting poster thread 3\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("sem_test: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = (prio_min + prio_mid) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("sem_test: Set thread 3 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&poster_thread, &attr, poster_func, (pthread_addr_t)3); + if (status != 0) + { + printf("sem_test: Error in thread 3 creation, status=%d\n", status); + } + +#ifdef SDCC + pthread_join(waiter_thread1, &result); + pthread_join(waiter_thread2, &result); + pthread_join(poster_thread, &result); +#else + pthread_join(waiter_thread1, NULL); + pthread_join(waiter_thread2, NULL); + pthread_join(poster_thread, NULL); +#endif +} diff --git a/apps/examples/ostest/sighand.c b/apps/examples/ostest/sighand.c new file mode 100644 index 000000000..681531639 --- /dev/null +++ b/apps/examples/ostest/sighand.c @@ -0,0 +1,267 @@ +/*********************************************************************** + * apps/examples/ostest/sighand.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <sys/types.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <semaphore.h> +#include <signal.h> +#include <sched.h> +#include <errno.h> +#include "ostest.h" + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define WAKEUP_SIGNAL 17 +#define SIGVALUE_INT 42 + +static sem_t sem; +static bool sigreceived = false; +static bool threadexited = false; + +static void wakeup_action(int signo, siginfo_t *info, void *ucontext) +{ + sigset_t oldset; + sigset_t allsigs; + int status; + + printf("wakeup_action: Received signal %d\n" , signo); + + sigreceived = true; + + /* Check signo */ + + if (signo != WAKEUP_SIGNAL) + { + printf("wakeup_action: ERROR expected signo=%d\n" , WAKEUP_SIGNAL); + } + + /* Check siginfo */ + + if (info->si_value.sival_int != SIGVALUE_INT) + { + printf("wakeup_action: ERROR sival_int=%d expected %d\n", + info->si_value.sival_int, SIGVALUE_INT); + } + else + { + printf("wakeup_action: sival_int=%d\n" , info->si_value.sival_int); + } + + if (info->si_signo != WAKEUP_SIGNAL) + { + printf("wakeup_action: ERROR expected si_signo=%d, got=%d\n", + WAKEUP_SIGNAL, info->si_signo); + } + + printf("wakeup_action: si_code=%d\n" , info->si_code); + + /* Check ucontext_t */ + + printf("wakeup_action: ucontext=%p\n" , ucontext); + + /* Check sigprocmask */ + + (void)sigfillset(&allsigs); + status = sigprocmask(SIG_SETMASK, NULL, &oldset); + if (status != OK) + { + printf("wakeup_action: ERROR sigprocmask failed, status=%d\n", + status); + } + + if (oldset != allsigs) + { + printf("wakeup_action: ERROR sigprocmask=%x expected=%x\n", + oldset, allsigs); + } +} + +static int waiter_main(int argc, char *argv[]) +{ + sigset_t sigset; + struct sigaction act; + struct sigaction oact; + int status; + + printf("waiter_main: Waiter started\n" ); + + printf("waiter_main: Unmasking signal %d\n" , WAKEUP_SIGNAL); + (void)sigemptyset(&sigset); + (void)sigaddset(&sigset, WAKEUP_SIGNAL); + status = sigprocmask(SIG_UNBLOCK, &sigset, NULL); + if (status != OK) + { + printf("waiter_main: ERROR sigprocmask failed, status=%d\n", + status); + } + + printf("waiter_main: Registering signal handler\n" ); + act.sa_sigaction = wakeup_action; + act.sa_flags = SA_SIGINFO; + + (void)sigfillset(&act.sa_mask); + (void)sigdelset(&act.sa_mask, WAKEUP_SIGNAL); + + status = sigaction(WAKEUP_SIGNAL, &act, &oact); + if (status != OK) + { + printf("waiter_main: ERROR sigaction failed, status=%d\n" , status); + } + +#ifndef SDCC + printf("waiter_main: oact.sigaction=%p oact.sa_flags=%x oact.sa_mask=%x\n", + oact.sa_sigaction, oact.sa_flags, oact.sa_mask); +#endif + + /* Take the semaphore */ + + printf("waiter_main: Waiting on semaphore\n" ); + FFLUSH(); + + status = sem_wait(&sem); + if (status != 0) + { + int error = errno; + if (error == EINTR) + { + printf("waiter_main: sem_wait() successfully interrupted by signal\n" ); + } + else + { + printf("waiter_main: ERROR sem_wait failed, errno=%d\n" , error); + } + } + else + { + printf("waiter_main: ERROR awakened with no error!\n" ); + } + + /* Detach the signal handler */ + + act.sa_sigaction = SIG_DFL; + status = sigaction(WAKEUP_SIGNAL, &act, &oact); + + printf("waiter_main: done\n" ); + FFLUSH(); + + threadexited = true; + return 0; +} + +void sighand_test(void) +{ + struct sched_param param; + union sigval sigvalue; + pid_t waiterpid; + int policy; + int status; + + printf("sighand_test: Initializing semaphore to 0\n" ); + sem_init(&sem, 0, 0); + + /* Start waiter thread */ + + printf("sighand_test: Starting waiter task\n" ); + status = sched_getparam (0, ¶m); + if (status != OK) + { + printf("sighand_test: ERROR sched_getparam() failed\n" ); + param.sched_priority = PTHREAD_DEFAULT_PRIORITY; + } + + policy = sched_getscheduler(0); + if (policy == ERROR) + { + printf("sighand_test: ERROR sched_getscheduler() failed\n" ); + policy = SCHED_FIFO; + } + + waiterpid = task_create("waiter", param.sched_priority, + PTHREAD_STACK_DEFAULT, waiter_main, NULL); + if (waiterpid == ERROR) + { + printf("sighand_test: ERROR failed to start waiter_main\n" ); + } + else + { + printf("sighand_test: Started waiter_main pid=%d\n", waiterpid); + } + + /* Wait a bit */ + + FFLUSH(); + sleep(2); + + /* Then signal the waiter thread. */ + + printf("sighand_test: Signaling pid=%d with signo=%d sigvalue=%d\n", + waiterpid, WAKEUP_SIGNAL, SIGVALUE_INT); + + sigvalue.sival_int = SIGVALUE_INT; +#ifdef CONFIG_CAN_PASS_STRUCTS + status = sigqueue(waiterpid, WAKEUP_SIGNAL, sigvalue); +#else + status = sigqueue(waiterpid, WAKEUP_SIGNAL, sigvalue.sival_ptr); +#endif + if (status != OK) + { + printf("sighand_test: ERROR sigqueue failed\n" ); + task_delete(waiterpid); + } + + /* Wait a bit */ + + FFLUSH(); + sleep(2); + + /* Then check the result */ + + if (!threadexited) + { + printf("sighand_test: ERROR waiter task did not exit\n" ); + } + + if (!sigreceived) + { + printf("sighand_test: ERROR signal handler did not run\n" ); + } + + printf("sighand_test: done\n" ); + FFLUSH(); +} diff --git a/apps/examples/ostest/timedmqueue.c b/apps/examples/ostest/timedmqueue.c new file mode 100644 index 000000000..807d8537b --- /dev/null +++ b/apps/examples/ostest/timedmqueue.c @@ -0,0 +1,387 @@ +/************************************************************************** + * apps/examples/ostest/mqueue.c + * + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <pthread.h> +#include <mqueue.h> +#include <sched.h> +#include <errno.h> + +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +#define TEST_MESSAGE "This is a test and only a test" +#if defined(SDCC) || defined(__ZILOG__) + /* Cannot use strlen in array size */ + +# define TEST_MSGLEN (31) +#else + /* Message lenght is the size of the message plus the null terminator */ + +# define TEST_MSGLEN (strlen(TEST_MESSAGE)+1) +#endif + +#define TEST_SEND_NMSGS (10) +#define TEST_RECEIVE_NMSGS (10) + +/************************************************************************** + * Private Types + **************************************************************************/ + +/************************************************************************** + * Private Function Prototypes + **************************************************************************/ + +/************************************************************************** + * Global Variables + **************************************************************************/ + +/************************************************************************** + * Private Variables + **************************************************************************/ + +/************************************************************************** + * Private Functions + **************************************************************************/ + +/************************************************************************** + * Public Functions + **************************************************************************/ + +static void *sender_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int status = 0; + int nerrors = 0; + int i; + + printf("sender_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = TEST_SEND_NMSGS-1; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this process tries to send to the queue and the queue is full. + * + * O_CREAT - the queue will get created if it does not already exist. + * O_WRONLY - we are only planning to write to the queue. + * + * Open the queue, and create it if the receiving process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_WRONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("sender_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Fill in a test message buffer to send */ + + memcpy(msg_buffer, TEST_MESSAGE, TEST_MSGLEN); + + /* Perform the send TEST_SEND_NMSGS times */ + + for (i = 0; i < TEST_SEND_NMSGS; i++) + { + struct timespec ts; + status = clock_gettime(CLOCK_REALTIME, &ts); + if (status != 0) + { + printf("sender_thread: ERROR clock_gettime failed\n"); + } + ts.tv_sec += 5; + + /* The first TEST_SEND_NMSGS-1 send should succeed. The last + * one should fail with errno == ETIMEDOUT + */ + + status = mq_timedsend(mqfd, msg_buffer, TEST_MSGLEN, 42, &ts); + if (status < 0) + { + if (i == TEST_SEND_NMSGS-1 && errno == ETIMEDOUT) + { + printf("sender_thread: mq_timedsend %d timed out as expected\n", i); + } + else + { + printf("sender_thread: ERROR mq_timedsend failure=%d on msg %d\n", errno, i); + nerrors++; + } + } + else + { + if (i == TEST_SEND_NMSGS-1) + { + printf("sender_thread: ERROR mq_timedsend of msg %d succeeded\n", i); + nerrors++; + } + else + { + printf("sender_thread: mq_timedsend succeeded on msg %d\n", i); + } + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("sender_thread: ERROR mq_close failed\n"); + } + + printf("sender_thread: returning nerrors=%d\n", nerrors); + FFLUSH(); + return (pthread_addr_t)nerrors; +} + +static void *receiver_thread(void *arg) +{ + mqd_t mqfd; + char msg_buffer[TEST_MSGLEN]; + struct mq_attr attr; + int nbytes; + int nerrors = 0; + int i; + + printf("receiver_thread: Starting\n"); + + /* Fill in attributes for message queue */ + + attr.mq_maxmsg = TEST_SEND_NMSGS-1; + attr.mq_msgsize = TEST_MSGLEN; + attr.mq_flags = 0; + + /* Set the flags for the open of the queue. + * Make it a blocking open on the queue, meaning it will block if + * this process tries to* send to the queue and the queue is full. + * + * O_CREAT - the queue will get created if it does not already exist. + * O_RDONLY - we are only planning to write to the queue. + * + * Open the queue, and create it if the sending process hasn't + * already created it. + */ + + mqfd = mq_open("testmq", O_RDONLY|O_CREAT, 0666, &attr); + if (mqfd < 0) + { + printf("receiver_thread: ERROR mq_open failed\n"); + pthread_exit((pthread_addr_t)1); + } + + /* Perform the receive TEST_RECEIVE_NMSGS times */ + + for (i = 0; i < TEST_RECEIVE_NMSGS; i++) + { + struct timespec ts; + int status = clock_gettime(CLOCK_REALTIME, &ts); + if (status != 0) + { + printf("sender_thread: ERROR clock_gettime failed\n"); + } + ts.tv_sec += 5; + + /* The first TEST_SEND_NMSGS-1 send should succeed. The last + * one should fail with errno == ETIMEDOUT + */ + + memset(msg_buffer, 0xaa, TEST_MSGLEN); + nbytes = mq_timedreceive(mqfd, msg_buffer, TEST_MSGLEN, 0, &ts); + if (nbytes < 0) + { + if (i == TEST_SEND_NMSGS-1 && errno == ETIMEDOUT) + { + printf("receiver_thread: Receive %d timed out as expected\n", i); + } + else + { + printf("receiver_thread: ERROR mq_timedreceive failure=%d on msg %d\n", errno, i); + nerrors++; + } + } + else if (nbytes != TEST_MSGLEN) + { + printf("receiver_thread: mq_timedreceive return bad size %d on msg %d\n", nbytes, i); + nerrors++; + } + else if (memcmp(TEST_MESSAGE, msg_buffer, nbytes) != 0) + { + int j; + + printf("receiver_thread: mq_timedreceive returned corrupt message on msg %d\n", i); + printf("receiver_thread: i Expected Received\n"); + + for (j = 0; j < TEST_MSGLEN-1; j++) + { + if (isprint(msg_buffer[j])) + { + printf("receiver_thread: %2d %02x (%c) %02x (%c)\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j], msg_buffer[j]); + } + else + { + printf("receiver_thread: %2d %02x (%c) %02x\n", + j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j]); + } + } + printf("receiver_thread: %2d 00 %02x\n", + j, msg_buffer[j]); + } + else if (i == TEST_SEND_NMSGS-1) + { + printf("receiver_thread: ERROR mq_timedreceive of msg %d succeeded\n", i); + nerrors++; + } + else + { + printf("receiver_thread: mq_timedreceive succeeded on msg %d\n", i); + } + } + + /* Close the queue and return success */ + + if (mq_close(mqfd) < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + /* Destroy the queue */ + + if (mq_unlink("testmq") < 0) + { + printf("receiver_thread: ERROR mq_close failed\n"); + nerrors++; + } + + printf("receiver_thread: returning nerrors=%d\n", nerrors); + FFLUSH(); + pthread_exit((pthread_addr_t)nerrors); + return (pthread_addr_t)nerrors; +} + +void timedmqueue_test(void) +{ + pthread_t sender; + pthread_t receiver; + void *result; + pthread_attr_t attr; + int status; + + /* Start the sending thread at the default priority */ + + printf("timedmqueue_test: Starting sender\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + status = pthread_create(&sender, &attr, sender_thread, NULL); + if (status != 0) + { + printf("timedmqueue_test: pthread_create failed, status=%d\n", status); + } + + /* Wait for the sending thread to complete */ + + printf("timedmqueue_test: Waiting for sender to complete\n"); + pthread_join(sender, &result); + if (result != (void*)0) + { + printf("timedmqueue_test: ERROR sender thread exited with %d errors\n", (int)result); + } + + /* Start the receiving thread at the default priority */ + + printf("timedmqueue_test: Starting receiver\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status); + } + + status = pthread_attr_setstacksize(&attr, STACKSIZE); + if (status != 0) + { + printf("timedmqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + } + + status = pthread_create(&receiver, &attr, receiver_thread, NULL); + if (status != 0) + { + printf("timedmqueue_test: pthread_create failed, status=%d\n", status); + } + + /* Wait for the receiving thread to complete */ + + printf("timedmqueue_test: Waiting for receiver to complete\n"); + pthread_join(receiver, &result); + if (result != (void*)0) + { + printf("timedmqueue_test: ERROR receiver thread exited with %d errors\n", (int)result); + } + + printf("timedmqueue_test: Test complete\n"); +} + + diff --git a/apps/examples/ostest/timedwait.c b/apps/examples/ostest/timedwait.c new file mode 100644 index 000000000..fc381ddda --- /dev/null +++ b/apps/examples/ostest/timedwait.c @@ -0,0 +1,195 @@ +/*********************************************************************** + * examples/ostest/timedwait.c + * + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <time.h> +#include <pthread.h> +#include <unistd.h> +#include <errno.h> + +#include "ostest.h" + +/************************************************************************** + * Private Definitions + **************************************************************************/ + +/************************************************************************** + * Private Data + **************************************************************************/ + +static pthread_mutex_t mutex; +static pthread_cond_t cond; + +/************************************************************************** + * Private Functions + **************************************************************************/ + +static void *thread_waiter(void *parameter) +{ + struct timespec ts; + int status; + + /* Take the mutex */ + + printf("thread_waiter: Taking mutex\n"); + status = pthread_mutex_lock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_lock failed, status=%d\n", status); + } + + printf("thread_waiter: Starting 5 second wait for condition\n"); + + status = clock_gettime(CLOCK_REALTIME, &ts); + if (status != 0) + { + printf("thread_waiter: ERROR clock_gettime failed\n"); + } + ts.tv_sec += 5; + + /* The wait -- no-one is ever going to awaken us */ + + status = pthread_cond_timedwait(&cond, &mutex, &ts); + if (status != 0) + { + if (status == ETIMEDOUT) + { + printf("thread_waiter: pthread_cond_timedwait timed out\n"); + } + else + { + printf("thread_waiter: ERROR pthread_cond_timedwait failed, status=%d\n", status); + } + } + else + { + printf("thread_waiter: ERROR pthread_cond_timedwait returned without timeout, status=%d\n", status); + } + + /* Release the mutex */ + + printf("thread_waiter: Releasing mutex\n"); + status = pthread_mutex_unlock(&mutex); + if (status != 0) + { + printf("thread_waiter: ERROR pthread_mutex_unlock failed, status=%d\n", status); + } + + printf("thread_waiter: Exit with status 0x12345678\n"); + pthread_exit((pthread_addr_t)0x12345678); + return NULL; +} + +/************************************************************************** + * Public Definitions + **************************************************************************/ + +void timedwait_test(void) +{ + pthread_t waiter; + pthread_attr_t attr; + struct sched_param sparam; + void *result; + int prio_max; + int status; + + /* Initialize the mutex */ + + printf("thread_waiter: Initializing mutex\n"); + status = pthread_mutex_init(&mutex, NULL); + if (status != 0) + { + printf("timedwait_test: ERROR pthread_mutex_init failed, status=%d\n", status); + } + + /* Initialize the condition variable */ + + printf("timedwait_test: Initializing cond\n"); + status = pthread_cond_init(&cond, NULL); + if (status != 0) + { + printf("timedwait_test: ERROR pthread_condinit failed, status=%d\n", status); + } + + /* Start the waiter thread at higher priority */ + + printf("timedwait_test: Starting waiter\n"); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("timedwait_test: pthread_attr_init failed, status=%d\n", status); + } + + prio_max = sched_get_priority_max(SCHED_FIFO); + status = sched_getparam (getpid(), &sparam); + if (status != 0) + { + printf("timedwait_test: sched_getparam failed\n"); + sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY; + } + + sparam.sched_priority = (prio_max + sparam.sched_priority) / 2; + status = pthread_attr_setschedparam(&attr,&sparam); + if (status != OK) + { + printf("timedwait_test: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("timedwait_test: Set thread 2 priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&waiter, &attr, thread_waiter, NULL); + if (status != 0) + { + printf("timedwait_test: pthread_create failed, status=%d\n", status); + } + + printf("timedwait_test: Joining\n"); + FFLUSH(); + status = pthread_join(waiter, &result); + if (status != 0) + { + printf("timedwait_test: ERROR pthread_join failed, status=%d\n", status); + } + else + { + printf("timedwait_test: waiter exited with result=%p\n", result); + } +} diff --git a/apps/examples/pipe/Kconfig b/apps/examples/pipe/Kconfig new file mode 100644 index 000000000..26bc92fcc --- /dev/null +++ b/apps/examples/pipe/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_PIPE + bool "Pipe example" + default n + ---help--- + Enable the pipe example + +if EXAMPLES_PIPE +endif diff --git a/apps/examples/pipe/Makefile b/apps/examples/pipe/Makefile new file mode 100644 index 000000000..3bcc9b5f7 --- /dev/null +++ b/apps/examples/pipe/Makefile @@ -0,0 +1,93 @@ +############################################################################ +# apps/examples/pipe/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# Pipe Example + +ASRCS = +CSRCS = pipe_main.c transfer_test.c interlock_test.c redirect_test.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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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: + +.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 diff --git a/apps/examples/pipe/interlock_test.c b/apps/examples/pipe/interlock_test.c new file mode 100644 index 000000000..e049a65f6 --- /dev/null +++ b/apps/examples/pipe/interlock_test.c @@ -0,0 +1,224 @@ +/**************************************************************************** + * examples/pipe/interlock_test.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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/stat.h> + +#include <sys/types.h> + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "pipe.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: null_writer + ****************************************************************************/ + +static void *null_writer(pthread_addr_t pvarg) +{ + int fd; + + /* Wait a bit */ + + printf("null_writer: started -- sleeping\n"); + sleep(5); + + /* Then open the FIFO for write access */ + + printf("null_writer: Opening FIFO for write access\n"); + fd = open(FIFO_PATH2, O_WRONLY); + if (fd < 0) + { + fprintf(stderr, "null_writer: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH2, errno); + return (void*)1; + } + + /* Wait a bit more */ + + printf("null_writer: Opened %s for writing -- sleeping\n", FIFO_PATH2); + sleep(5); + + /* Then close the FIFO */ + + printf("null_writer: Closing %s\n", FIFO_PATH2); + if (close(fd) != 0) + { + fprintf(stderr, "null_writer: close failed: %d\n", errno); + } + sleep(5); + + printf("null_writer: Returning success\n"); + return (void*)0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: interlock_test + ****************************************************************************/ + +int interlock_test(void) +{ + pthread_t writerid; + void *value; + char data[16]; + ssize_t nbytes; + int fd; + int ret; + + /* Create a FIFO */ + + ret = mkfifo(FIFO_PATH2, 0666); + if (ret < 0) + { + fprintf(stderr, "interlock_test: mkfifo failed with errno=%d\n", errno); + return 1; + } + + /* Start the null_writer_thread */ + + printf("interlock_test: Starting null_writer thread\n"); + ret = pthread_create(&writerid, NULL, null_writer, (pthread_addr_t)NULL); + if (ret != 0) + { + fprintf(stderr, "interlock_test: Failed to create null_writer thread, error=%d\n", ret); + ret = 2; + goto errout_with_fifo; + } + + /* Open one end of the FIFO for reading. This open call should block until the + * null_writer thread opens the other end of the FIFO for writing. + */ + + printf("interlock_test: Opening FIFO for read access\n"); + fd = open(FIFO_PATH2, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "interlock_test: Failed to open FIFO %s for reading, errno=%d\n", + FIFO_PATH2, errno); + ret = 3; + goto errout_with_thread; + } + + /* Attempt to read one byte from the FIFO. This should return end-of-file because + * the null_writer closes the FIFO without writing anything. + */ + + printf("interlock_test: Reading from %s\n", FIFO_PATH2); + nbytes = read(fd, data, 16); + if (nbytes < 0 ) + { + fprintf(stderr, "interlock_test: read failed, errno=%d\n", errno); + ret = 4; + goto errout_with_file; + } + else if (ret != 0) + { + fprintf(stderr, "interlock_test: Read %d bytes of data -- aborting: %d\n", nbytes); + ret = 5; + goto errout_with_file; + } + + /* Close the file */ + + printf("interlock_test: Closing %s\n", FIFO_PATH2); + if (close(fd) != 0) + { + fprintf(stderr, "interlock_test: close failed: %d\n", errno); + } + + /* Wait for null_writer thread to complete */ + + printf("interlock_test: Waiting for null_writer thread\n"); + ret = pthread_join(writerid, &value); + if (ret != 0) + { + fprintf(stderr, "interlock_test: pthread_join failed, error=%d\n", ret); + ret = 6; + goto errout_with_fifo; + } + else + { + printf("interlock_test: writer returned %d\n", (int)value); + if (value != (void*)0) + { + ret = 7; + goto errout_with_fifo; + } + } + + /* unlink(FIFO_PATH2); */ + printf("interlock_test: Returning success\n"); + return 0; + +errout_with_file: + if (close(fd) != 0) + { + fprintf(stderr, "interlock_test: close failed: %d\n", errno); + } +errout_with_thread: + pthread_detach(writerid); + pthread_cancel(writerid); +errout_with_fifo: + /* unlink(FIFO_PATH2); */ + printf("interlock_test: Returning %d\n", ret); + return ret; +} diff --git a/apps/examples/pipe/pipe.h b/apps/examples/pipe/pipe.h new file mode 100644 index 000000000..2c18fd868 --- /dev/null +++ b/apps/examples/pipe/pipe.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * examples/pipe/pipe.h + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 __EXAMPLES_PIPE_PIPE_H +#define __EXAMPLES_PIPE_PIPE_H + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define FIFO_PATH1 "/tmp/testfifo-1" +#define FIFO_PATH2 "/tmp/testfifo-2" + +#ifndef CONFIG_EXAMPLES_PIPE_STACKSIZE +# define CONFIG_EXAMPLES_PIPE_STACKSIZE 1024 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern int transfer_test(int fdin, int fdout); +extern int interlock_test(void); +extern int redirection_test(void); + +#endif /* __EXAMPLES_PIPE_PIPE_H */ diff --git a/apps/examples/pipe/pipe_main.c b/apps/examples/pipe/pipe_main.c new file mode 100644 index 000000000..1f0f73032 --- /dev/null +++ b/apps/examples/pipe/pipe_main.c @@ -0,0 +1,189 @@ +/**************************************************************************** + * examples/pipe/pipe_main.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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/stat.h> +#include <stdio.h> +#include <unistd.h> +#include <sched.h> +#include <fcntl.h> +#include <errno.h> + +#include "pipe.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int filedes[2]; + int ret; + + /* Test FIFO logic */ + + printf("\nuser_start: Performing FIFO test\n"); + ret = mkfifo(FIFO_PATH1, 0666); + if (ret < 0) + { + fprintf(stderr, "user_start: mkfifo failed with errno=%d\n", errno); + return 1; + } + + /* Open one end of the FIFO for reading and the other end for writing. NOTE: + * the following might not work on most FIFO implementations because the attempt + * to open just one end of the FIFO for writing might block. The NuttX FIFOs block + * only on open for read-only (see interlock_test()). + */ + + filedes[1] = open(FIFO_PATH1, O_WRONLY); + if (filedes[1] < 0) + { + fprintf(stderr, "user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH1, errno); + return 2; + } + + filedes[0] = open(FIFO_PATH1, O_RDONLY); + if (filedes[0] < 0) + { + fprintf(stderr, "user_start: Failed to open FIFO %s for reading, errno=%d\n", + FIFO_PATH1, errno); + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + return 3; + } + + /* Then perform the test using those file descriptors */ + + ret = transfer_test(filedes[0], filedes[1]); + if (close(filedes[0]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + /* unlink(FIFO_PATH1); fails */ + + if (ret != 0) + { + fprintf(stderr, "user_start: FIFO test FAILED (%d)\n", ret); + return 4; + } + printf("user_start: FIFO test PASSED\n"); + + /* Test PIPE logic */ + + printf("\nuser_start: Performing pipe test\n"); + ret = pipe(filedes); + if (ret < 0) + { + fprintf(stderr, "user_start: pipe failed with errno=%d\n", errno); + return 5; + } + + /* Then perform the test using those file descriptors */ + + ret = transfer_test(filedes[0], filedes[1]); + if (close(filedes[0]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + + if (ret != 0) + { + fprintf(stderr, "user_start: PIPE test FAILED (%d)\n", ret); + return 6; + } + printf("user_start: PIPE test PASSED\n"); + + /* Perform the FIFO interlock test */ + + printf("\nuser_start: Performing pipe interlock test\n"); + ret = interlock_test(); + if (ret != 0) + { + fprintf(stderr, "user_start: FIFO interlock test FAILED (%d)\n", ret); + return 7; + } + printf("user_start: PIPE interlock test PASSED\n"); + + /* Perform the pipe redirection test */ + + printf("\nuser_start: Performing redirection test\n"); + ret = redirection_test(); + if (ret != 0) + { + fprintf(stderr, "user_start: FIFO redirection test FAILED (%d)\n", ret); + return 7; + } + printf("user_start: PIPE redirection test PASSED\n"); + + fflush(stdout); + return 0; +} diff --git a/apps/examples/pipe/redirect_test.c b/apps/examples/pipe/redirect_test.c new file mode 100644 index 000000000..45e86c356 --- /dev/null +++ b/apps/examples/pipe/redirect_test.c @@ -0,0 +1,326 @@ +/**************************************************************************** + * examples/pipe/redirect_test.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sched.h> +#include <semaphore.h> +#include <errno.h> + +#include "pipe.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define READ_SIZE 37 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static sem_t g_rddone; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: redirect_reader + ****************************************************************************/ + +static int redirect_reader(int argc, char *argv[]) +{ + char buffer[READ_SIZE]; + int fdin; + int fdout; + int ret; + int nbytes = 0; + + printf("redirect_reader: started with fdin=%s\n", argv[1]); + + /* Convert the fdin to binary */ + + fdin = atoi(argv[1]); + fdout = atoi(argv[2]); + + /* Close fdout -- we don't need it */ + + ret = close(fdout); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdout=%d\n", fdout); + return 1; + } + + /* Re-direct the fdin to stdin */ + + ret = dup2(fdin, 0); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: dup2 failed: %d\n", errno); + close(fdin); + return 2; + } + + /* Close the original file descriptor */ + + ret = close(fdin); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdin=%d\n", fdin); + return 3; + } + + /* Then read from stdin until we hit the end of file */ + + fflush(stdout); + for (;;) + { + /* Read from stdin */ + + ret = read(0, buffer, READ_SIZE); + if (ret < 0 ) + { + fprintf(stderr, "redirect_reader: read failed, errno=%d\n", errno); + return 4; + } + else if (ret == 0) + { + break; + } + nbytes += ret; + + /* Echo to stdout */ + + ret = write(1, buffer, ret); + if (ret < 0) + { + fprintf(stderr, "redirect_reader: read failed, errno=%d\n", errno); + return 5; + } + } + + printf("redirect_reader: %d bytes read\n", nbytes); + ret = close(0); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fd=0\n"); + return 6; + } + + sem_post(&g_rddone); + printf("redirect_reader: Returning success\n"); + return 0; +} + +/**************************************************************************** + * Name: redirect_writer + ****************************************************************************/ + +static int redirect_writer(int argc, char *argv[]) +{ + int fdin; + int fdout; + int nbytes = 0; + int ret; + + fprintf(stderr, "redirect_writer: started with fdout=%s\n", argv[2]); + + /* Convert the fdout to binary */ + + fdin = atoi(argv[1]); + fdout = atoi(argv[2]); + + /* Close fdin -- we don't need it */ + + ret = close(fdin); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdin=%d\n", fdin); + return 1; + } + + /* Re-direct the fdout to stdout */ + + ret = dup2(fdout, 1); + if (ret != 0) + { + fprintf(stderr, "redirect_writer: dup2 failed: %d\n", errno); + return 2; + } + + /* Close the original file descriptor */ + + ret = close(fdout); + if (ret != 0) + { + fprintf(stderr, "redirect_reader: failed to close fdout=%d\n", fdout); + return 3; + } + + /* Then write a bunch of stuff to stdout */ + + fflush(stderr); + nbytes += printf("\nFour score and seven years ago our fathers brought forth on this continent a new nation,\n"); + nbytes += printf("conceived in Liberty, and dedicated to the proposition that all men are created equal.\n"); + nbytes += printf("\nNow we are engaged in a great civil war, testing whether that nation, or any nation, so\n"); + nbytes += printf("conceived and so dedicated, can long endure. We are met on a great battle-field of that war.\n"); + nbytes += printf("We have come to dedicate a portion of that field, as a final resting place for those who here\n"); + nbytes += printf("gave their lives that that nation might live. It is altogether fitting and proper that we\n"); + nbytes += printf("should do this.\n"); + nbytes += printf("\nBut, in a larger sense, we can not dedicate - we can not consecrate - we can not hallow - this ground.\n"); + nbytes += printf("The brave men, living and dead, who struggled here, have consecrated it, far above our poor power\n"); + nbytes += printf("to add or detract. The world will little note, nor long remember what we say here, but it can\n"); + nbytes += printf("never forget what they did here. It is for us the living, rather, to be dedicated here to the\n"); + nbytes += printf("unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to\n"); + nbytes += printf("be here dedicated to the great task remaining before us - that from these honored dead we take\n"); + nbytes += printf("increased devotion to that cause for which they gave the last full measure of devotion - that we\n"); + nbytes += printf("here highly resolve that these dead shall not have died in vain - that this nation, under God,\n"); + nbytes += printf("shall have a new birth of freedom - and that government of the people, by the people, for the\n"); + nbytes += printf("people, shall not perish from the earth.\n\n"); + fflush(stdout); + + fprintf(stderr, "redirect_writer: %d bytes written\n", nbytes); + + ret = close(1); + if (ret != 0) + { + fprintf(stderr, "redirect_writer: failed to close fd=1\n"); + return 4; + } + + fprintf(stderr, "redirect_writer: Returning success\n"); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: redirection_test + ****************************************************************************/ + +int redirection_test(void) +{ + const char *argv[3]; + char buffer1[8]; + char buffer2[8]; + int readerid; + int writerid; + int filedes[2]; + int ret; + + sem_init(&g_rddone, 0, 0); + + /* Create the pipe */ + + ret = pipe(filedes); + if (ret < 0) + { + fprintf(stderr, "redirection_test: pipe failed with errno=%d\n", errno); + return 5; + } + + sprintf(buffer1, "%d", filedes[0]); + argv[0] = buffer1; + sprintf(buffer2, "%d", filedes[1]); + argv[1] = buffer2; + argv[2] = NULL; + + /* Start redirect_reader thread */ + + printf("redirection_test: Starting redirect_reader task with fd=%d\n", filedes[0]); + readerid = task_create("redirect_reader", 50, CONFIG_EXAMPLES_PIPE_STACKSIZE, redirect_reader, argv); + if (readerid < 0) + { + fprintf(stderr, "redirection_test: Failed to create redirect_writer task: %d\n", errno); + return 1; + } + + /* Start redirect_writer task */ + + printf("redirection_test: Starting redirect_writer task with fd=%d\n", filedes[1]); + writerid = task_create("redirect_writer", 50, CONFIG_EXAMPLES_PIPE_STACKSIZE, redirect_writer, argv); + if (writerid < 0) + { + fprintf(stderr, "redirection_test: Failed to create redirect_writer task: %d\n", errno); + ret = task_delete(readerid); + if (ret != 0) + { + fprintf(stderr, "redirection_test: Failed to delete redirect_reader task %d\n", errno); + } + return 2; + } + + /* We should be able to close the pipe file descriptors now. */ + + if (close(filedes[0]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + if (close(filedes[1]) != 0) + { + fprintf(stderr, "user_start: close failed: %d\n", errno); + } + + if (ret != 0) + { + fprintf(stderr, "user_start: PIPE test FAILED (%d)\n", ret); + return 6; + } + + /* Wait for redirect_writer thread to complete */ + + printf("redirection_test: Waiting...\n"); + fflush(stdout); + sem_wait(&g_rddone); + + printf("redirection_test: returning %d\n", ret); + return ret; +} + diff --git a/apps/examples/pipe/transfer_test.c b/apps/examples/pipe/transfer_test.c new file mode 100644 index 000000000..cb8cad04a --- /dev/null +++ b/apps/examples/pipe/transfer_test.c @@ -0,0 +1,242 @@ +/**************************************************************************** + * examples/pipe/transfer_test.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include "pipe.h" + +/**************************************************************************** + * Pre-proecessor Definitions + ****************************************************************************/ + +#define MAX_BYTE 13 + +#define WRITE_SIZE MAX_BYTE +#define NWRITES 1400 +#define NWRITE_BYTES (NWRITES * WRITE_SIZE) + +#define READ_SIZE (2*MAX_BYTE) +#define NREADS (NWRITES / 2) +#define NREAD_BYTES NWRITE_BYTES + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: transfer_reader + ****************************************************************************/ + +static void *transfer_reader(pthread_addr_t pvarg) +{ + char buffer[READ_SIZE]; + int fd = (int)pvarg; + int ret; + int nbytes; + int value; + int ndx; + + printf("transfer_reader: started\n"); + for (nbytes = 0, value = 0; nbytes < NREAD_BYTES;) + { + ret = read(fd, buffer, READ_SIZE); + if (ret < 0 ) + { + fprintf(stderr, "transfer_reader: read failed, errno=%d\n", errno); + return (void*)1; + } + else if (ret == 0) + { + if (nbytes < NREAD_BYTES) + { + fprintf(stderr, "transfer_reader: Too few bytes read -- aborting: %d\n", nbytes); + return (void*)2; + } + break; + } + for (ndx = 0; ndx < ret; ndx++) + { + if (value >= WRITE_SIZE) + { + value = 0; + } + if (buffer[ndx] != value) + { + fprintf(stderr, "transfer_reader: Byte %d, expected %d, found %d\n", + nbytes + ndx, value, buffer[ndx]); + return (void*)3; + } + value++; + } + nbytes += ret; + if (nbytes > NREAD_BYTES) + { + fprintf(stderr, "transfer_reader: Too many bytes read -- aborting: %d\n", nbytes); + return (void*)4; + } + } + printf("transfer_reader: %d bytes read\n", nbytes); + return (void*)0; +} + +/**************************************************************************** + * Name: transfer_writer + ****************************************************************************/ + +static void *transfer_writer(pthread_addr_t pvarg) +{ + char buffer[WRITE_SIZE]; + int fd = (int)pvarg; + int ret; + int i; + + printf("transfer_writer: started\n"); + for (i = 0; i < WRITE_SIZE; i++) + { + buffer[i] = i; + } + + for (i = 0; i < NWRITES; i++) + { + ret = write(fd, buffer, WRITE_SIZE); + if (ret < 0 ) + { + fprintf(stderr, "transfer_writer: write failed, errno=%d\n", errno); + return (void*)1; + } + else if (ret != WRITE_SIZE) + { + fprintf(stderr, "transfer_writer: Unexpected write size=%d\n", ret); + return (void*)2; + } + } + printf("transfer_writer: %d bytes written\n", NWRITE_BYTES); + return (void*)0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: transfer_test + ****************************************************************************/ + +int transfer_test(int fdin, int fdout) +{ + pthread_t readerid; + pthread_t writerid; + void *value; + int tmp; + int ret; + + /* Start transfer_reader thread */ + + printf("transfer_test: Starting transfer_reader thread\n"); + ret = pthread_create(&readerid, NULL, transfer_reader, (pthread_addr_t)fdin); + if (ret != 0) + { + fprintf(stderr, "transfer_test: Failed to create transfer_reader thread, error=%d\n", ret); + return 1; + } + + /* Start transfer_writer thread */ + + printf("transfer_test: Starting transfer_writer thread\n"); + ret = pthread_create(&writerid, NULL, transfer_writer, (pthread_addr_t)fdout); + if (ret != 0) + { + fprintf(stderr, "transfer_test: Failed to create transfer_writer thread, error=%d\n", ret); + pthread_detach(readerid); + ret = pthread_cancel(readerid); + if (ret != 0) + { + fprintf(stderr, "transfer_test: Failed to cancel transfer_reader thread, error=%d\n", ret); + } + return 2; + } + + /* Wait for transfer_writer thread to complete */ + + printf("transfer_test: Waiting for transfer_writer thread\n"); + ret = pthread_join(writerid, &value); + if (ret != 0) + { + fprintf(stderr, "transfer_test: pthread_join failed, error=%d\n", ret); + } + else + { + ret = (int)value; + printf("transfer_test: transfer_writer returned %d\n", ret); + } + + /* Wait for transfer_reader thread to complete */ + + printf("transfer_test: Waiting for transfer_reader thread\n"); + tmp = pthread_join(readerid, &value); + if (tmp != 0) + { + fprintf(stderr, "transfer_test: pthread_join failed, error=%d\n", ret); + } + else + { + tmp = (int)value; + printf("transfer_test: transfer_reader returned %d\n", tmp); + } + + if (ret == 0) + { + ret = tmp; + } + printf("transfer_test: returning %d\n", ret); + return ret; +} + diff --git a/apps/examples/poll/Kconfig b/apps/examples/poll/Kconfig new file mode 100644 index 000000000..c52827496 --- /dev/null +++ b/apps/examples/poll/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_POLL + bool "Poll example" + default n + ---help--- + Enable the poll example + +if EXAMPLES_POLL +endif diff --git a/apps/examples/poll/Makefile b/apps/examples/poll/Makefile new file mode 100644 index 000000000..1c85d6f36 --- /dev/null +++ b/apps/examples/poll/Makefile @@ -0,0 +1,94 @@ +############################################################################ +# apps/examples/poll/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# Device Driver poll()/select() Example + +ASRCS = +CSRCS = poll_main.c poll_listener.c select_listener.c net_listener.c net_reader.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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend host + +-include Make.dep diff --git a/apps/examples/poll/Makefile.host b/apps/examples/poll/Makefile.host new file mode 100644 index 000000000..9d9daee27 --- /dev/null +++ b/apps/examples/poll/Makefile.host @@ -0,0 +1,54 @@ +############################################################################ +# apps/examples/poll/Makefile.host +# +# Copyright (C) 2008, 2009, 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. +# +############################################################################ + +# TOPDIR must be defined on the make command line + +include $(TOPDIR)/.config +include $(TOPDIR)/Make.defs + +SRC = host.c +BIN = host + +DEFINES = -DTARGETIP=\"$(TARGETIP)\" + +all: $(BIN) + +$(BIN): $(SRC) + $(HOSTCC) $(HOSTCFLAGS) $(DEFINES) $^ -o $@ + +clean: + @rm -f $(BIN) *~ .*.swp *.o + $(call CLEAN) + diff --git a/apps/examples/poll/host.c b/apps/examples/poll/host.c new file mode 100644 index 000000000..302cceb0f --- /dev/null +++ b/apps/examples/poll/host.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * examples/poll/host.c + * + * Copyright (C) 2008-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 + * 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 <sys/socket.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <errno.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#define pthread_addr_t void * +#include "poll_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef TARGETIP +# error TARGETIP not defined +#endif + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * main + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + struct sockaddr_in myaddr; + char outbuf[IOBUFFER_SIZE]; + char inbuf[IOBUFFER_SIZE]; + int sockfd; + int len; + int nbytessent; + int nbytesrecvd; + int i; + + /* Create a new TCP socket */ + + sockfd = socket(PF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + message("client socket failure %d\n", errno); + goto errout_with_outbufs; + } + + /* Connect the socket to the server */ + + myaddr.sin_family = AF_INET; + myaddr.sin_port = htons(LISTENER_PORT); + myaddr.sin_addr.s_addr = inet_addr(TARGETIP); + + message("client: Connecting to %s...\n", TARGETIP); + if (connect( sockfd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0) + { + message("client: connect failure: %d\n", errno); + goto errout_with_socket; + } + message("client: Connected\n"); + + /* Then send and receive messages */ + + for (i = 0; ; i++) + { + sprintf(outbuf, "Remote message %d", i); + len = strlen(outbuf); + + message("client: Sending '%s' (%d bytes)\n", outbuf, len); + nbytessent = send(sockfd, outbuf, len, 0); + message("client: Sent %d bytes\n", nbytessent); + + if (nbytessent < 0) + { + message("client: send failed: %d\n", errno); + goto errout_with_socket; + } + else if (nbytessent != len) + { + message("client: Bad send length: %d Expected: %d\n", nbytessent, len); + goto errout_with_socket; + } + + message("client: Receiving...\n"); + nbytesrecvd = recv(sockfd, inbuf, IOBUFFER_SIZE, 0); + + if (nbytesrecvd < 0) + { + message("client: recv failed: %d\n", errno); + goto errout_with_socket; + } + else if (nbytesrecvd == 0) + { + message("client: The server broke the connections\n"); + goto errout_with_socket; + } + + inbuf[nbytesrecvd] = '\0'; + message("client: Received '%s' (%d bytes)\n", inbuf, nbytesrecvd); + + if (nbytesrecvd != len) + { + message("client: Bad recv length: %d Expected: %d\n", nbytesrecvd, len); + goto errout_with_socket; + } + else if (memcmp(inbuf, outbuf, len) != 0) + { + message("client: Received outbuf does not match sent outbuf\n"); + goto errout_with_socket; + } + + message("client: Sleeping\n"); + sleep(8); + } + + close(sockfd); + return 0; + +errout_with_socket: + close(sockfd); +errout_with_outbufs: + exit(1); +} diff --git a/apps/examples/poll/net_listener.c b/apps/examples/poll/net_listener.c new file mode 100644 index 000000000..81ad7cdcc --- /dev/null +++ b/apps/examples/poll/net_listener.c @@ -0,0 +1,428 @@ +/**************************************************************************** + * examples/poll/net_listener.c + * + * Copyright (C) 2008-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 + * 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/stat.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/ioctl.h> + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <errno.h> +#include <debug.h> + +#include <net/if.h> +#include <apps/netutils/uiplib.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct net_listener_s +{ + struct sockaddr_in addr; + fd_set master; + fd_set working; + char buffer[IOBUFFER_SIZE]; + int listensd; + int mxsd; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_closeclient + ****************************************************************************/ + +static bool net_closeclient(struct net_listener_s *nls, int sd) +{ + message("net_listener: Closing host side connection sd=%d\n", sd); + close(sd); + FD_CLR(sd, &nls->master); + + /* If we just closed the max SD, then search downward for the next biggest SD. */ + + while (FD_ISSET(nls->mxsd, &nls->master) == false) + { + nls->mxsd -= 1; + } + return true; +} + +/**************************************************************************** + * Name: net_incomingdata + ****************************************************************************/ + +static inline bool net_incomingdata(struct net_listener_s *nls, int sd) +{ + char *ptr; + int nbytes; + int ret; + + /* Read data from the socket */ + +#ifdef FIONBIO + for (;;) +#endif + { + message("net_listener: Read data from sd=%d\n", sd); + ret = recv(sd, nls->buffer, IOBUFFER_SIZE, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_listener: recv failed sd=%d: %d\n", sd, errno); + if (errno != EAGAIN) + { + net_closeclient(nls, sd); + return false; + } + } + } + else if (ret == 0) + { + message("net_listener: Client connection lost sd=%d\n", sd); + net_closeclient(nls, sd); + return false; + } + else + { + nls->buffer[ret]='\0'; + message("poll_listener: Read '%s' (%d bytes)\n", nls->buffer, ret); + + /* Echo the data back to the client */ + + for (nbytes = ret, ptr = nls->buffer; nbytes > 0; ) + { + ret = send(sd, ptr, nbytes, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_listener: Send failed sd=%d: \n", sd, errno); + net_closeclient(nls, sd); + return false; + } + } + else + { + nbytes -= ret; + ptr += ret; + } + } + } + } + return 0; +} + +/**************************************************************************** + * Name: net_connection + ****************************************************************************/ + +static inline bool net_connection(struct net_listener_s *nls) +{ + int sd; + + /* Loop until all connections have been processed */ + +#ifdef FIONBIO + for (;;) +#endif + { + message("net_listener: Accepting new connection on sd=%d\n", nls->listensd); + + sd = accept(nls->listensd, NULL, NULL); + if (sd < 0) + { + message("net_listener: accept failed: %d\n", errno); + + if (errno != EINTR) + { + return false; + } + } + else + { + /* Add the new connection to the master set */ + + message("net_listener: Connection accepted for sd=%d\n", sd); + + FD_SET(sd, &nls->master); + if (sd > nls->mxsd) + { + nls->mxsd = sd; + } + return true; + } + } + return false; +} + +/**************************************************************************** + * Name: net_mksocket + ****************************************************************************/ + +static inline bool net_mksocket(struct net_listener_s *nls) +{ + int value; + int ret; + + /* Create a listening socket */ + + message("net_listener: Initializing listener socket\n"); + nls->listensd = socket(AF_INET, SOCK_STREAM, 0); + if (nls->listensd < 0) + { + message("net_listener: socket failed: %d\n", errno); + return false; + } + + /* Configure the socket */ + + value = 1; + ret = setsockopt(nls->listensd, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(int)); + if (ret < 0) + { + message("net_listener: setsockopt failed: %d\n", errno); + close(nls->listensd); + return false; + } + + /* Set the socket to non-blocking */ + +#ifdef FIONBIO + ret = ioctl(nls->listensd, FIONBIO, (char *)&value); + if (ret < 0) + { + message("net_listener: ioctl failed: %d\n", errno); + close(nls->listensd); + return false; + } +#endif + + /* Bind the socket */ + + memset(&nls->addr, 0, sizeof(struct sockaddr_in)); + nls->addr.sin_family = AF_INET; + nls->addr.sin_addr.s_addr = htonl(INADDR_ANY); + nls->addr.sin_port = htons(LISTENER_PORT); + ret = bind(nls->listensd, (struct sockaddr *)&nls->addr, sizeof(struct sockaddr_in)); + if (ret < 0) + { + message("net_listener: bind failed: %d\n", errno); + close(nls->listensd); + return false; + } + + /* Mark the socket as a listener */ + + ret = listen(nls->listensd, 32); + if (ret < 0) + { + message("net_listener: bind failed: %d\n", errno); + close(nls->listensd); + return false; + } + + return true; +} + +/**************************************************************************** + * Name: net_configure + ****************************************************************************/ + +static void net_configure(void) +{ + struct in_addr addr; +#if defined(CONFIG_EXAMPLE_POLL_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif + + /* Configure uIP */ + /* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLE_POLL_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xde; + mac[3] = 0xad; + mac[4] = 0xbe; + mac[5] = 0xef; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + uip_setnetmask("eth0", &addr); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_listener + ****************************************************************************/ + +void *net_listener(pthread_addr_t pvarg) +{ + struct net_listener_s nls; + struct timeval timeout; + int nsds; + int ret; + int i; + + /* Configure uIP */ + + net_configure(); + + /* Set up a listening socket */ + + memset(&nls, 0, sizeof(struct net_listener_s)); + if (!net_mksocket(&nls)) + { + return (void*)1; + } + + /* Initialize the 'master' file descriptor set */ + + FD_ZERO(&nls.master); + nls.mxsd = nls.listensd; + FD_SET(nls.listensd, &nls.master); + + /* Set up a 3 second timeout */ + + timeout.tv_sec = NET_LISTENER_DELAY; + timeout.tv_usec = 0; + + /* Loop waiting for incoming connections or for incoming data + * on any of the connect sockets. + */ + + for (;;) + { + /* Wait on select */ + + message("net_listener: Calling select(), listener sd=%d\n", nls.listensd); + memcpy(&nls.working, &nls.master, sizeof(fd_set)); + ret = select(nls.mxsd + 1, (FAR fd_set*)&nls.working, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout); + if (ret < 0) + { + message("net_listener: select failed: %d\n", errno); + break; + } + + /* Check for timeout */ + + if (ret == 0) + { + message("net_listener: Timeout\n"); + continue; + } + + /* Find which descriptors caused the wakeup */ + + nsds = ret; + for (i = 0; i <= nls.mxsd && nsds > 0; i++) + { + /* Is this descriptor ready? */ + + if (FD_ISSET(i, &nls.working)) + { + /* Yes, is it our listener? */ + + message("net_listener: Activity on sd=%d\n", i); + + nsds--; + if (i == nls.listensd) + { + (void)net_connection(&nls); + } + else + { + net_incomingdata(&nls, i); + } + } + } + } + + /* Cleanup */ + +#if 0 /* Don't get here */ + for (i = 0; i <= nls.mxsd; +i++) + { + if (FD_ISSET(i, &nls.master)) + { + close(i); + } + } +#endif + return NULL; /* Keeps some compilers from complaining */ +} diff --git a/apps/examples/poll/net_reader.c b/apps/examples/poll/net_reader.c new file mode 100644 index 000000000..8a13618c3 --- /dev/null +++ b/apps/examples/poll/net_reader.c @@ -0,0 +1,317 @@ +/**************************************************************************** + * examples/poll/net_reader.c + * + * Copyright (C) 2008-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 + * 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/stat.h> +#include <sys/select.h> +#include <sys/socket.h> + +#include <stdint.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include <net/if.h> +#include <apps/netutils/uiplib.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define IOBUFFER_SIZE 80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_configure + ****************************************************************************/ + +static void net_configure(void) +{ + struct in_addr addr; +#if defined(CONFIG_EXAMPLE_POLL_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif + + /* Configure uIP */ + /* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLE_POLL_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xde; + mac[3] = 0xad; + mac[4] = 0xbe; + mac[5] = 0xef; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + uip_setnetmask("eth0", &addr); +} + +/**************************************************************************** + * Name: net_receive + ****************************************************************************/ + +static void net_receive(int sd) +{ + struct timeval timeout; + char buffer[IOBUFFER_SIZE]; + char *ptr; + fd_set readset; + int nbytes; + int ret; + + /* Set up the timeout */ + + timeout.tv_sec = NET_LISTENER_DELAY; + timeout.tv_usec = 0; + + /* Loop while we have the connection */ + + for (;;) + { + /* Wait for incoming message */ + + do + { + FD_ZERO(&readset); + FD_SET(sd, &readset); + ret = select(sd + 1, (FAR fd_set*)&readset, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout); + } + while (ret < 0 && errno == EINTR); + + /* Something has happened */ + + if (ret < 0) + { + message("net_reader: select failed: %d\n", errno); + return; + } + else if (ret == 0) + { + message("net_reader: Timeout\n"); + } + else + { + message("net_reader: Read data from sd=%d\n", sd); + memset(buffer, '?', IOBUFFER_SIZE); /* Just to make sure we really receive something */ + ret = recv(sd, buffer, IOBUFFER_SIZE, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_reader: recv failed sd=%d: %d\n", sd, errno); + if (errno != EAGAIN) + { + return; + } + } + } + else if (ret == 0) + { + message("net_reader: Client connection lost sd=%d\n", sd); + return; + } + else + { + buffer[ret]='\0'; + message("net_reader: Read '%s' (%d bytes)\n", buffer, ret); + + /* Echo the data back to the client */ + + for (nbytes = ret, ptr = buffer; nbytes > 0; ) + { + ret = send(sd, ptr, nbytes, 0); + if (ret < 0) + { + if (errno != EINTR) + { + message("net_reader: Send failed sd=%d: %d\n", sd, errno); + return; + } + } + else + { + nbytes -= ret; + ptr += ret; + } + } + } + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_reader + ****************************************************************************/ + +void *net_reader(pthread_addr_t pvarg) +{ + struct sockaddr_in addr; +#ifdef POLL_HAVE_SOLINGER + struct linger ling; +#endif + int listensd; + int acceptsd; + socklen_t addrlen; + int optval; + + /* Configure uIP */ + + net_configure(); + + /* Create a new TCP socket */ + + listensd = socket(PF_INET, SOCK_STREAM, 0); + if (listensd < 0) + { + message("net_reader: socket failure: %d\n", errno); + goto errout; + } + + /* Set socket to reuse address */ + + optval = 1; + if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) + { + message("net_reader: setsockopt SO_REUSEADDR failure: %d\n", errno); + goto errout_with_listensd; + } + + /* Bind the socket to a local address */ + + addr.sin_family = AF_INET; + addr.sin_port = HTONS(LISTENER_PORT); + addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(listensd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) + { + message("net_reader: bind failure: %d\n", errno); + goto errout_with_listensd; + } + + /* Listen for connections on the bound TCP socket */ + + if (listen(listensd, 5) < 0) + { + message("net_reader: listen failure %d\n", errno); + goto errout_with_listensd; + } + + /* Connection loop */ + + for (;;) + { + /* Accept only one connection */ + + message("net_reader: Accepting new connections on port %d\n", LISTENER_PORT); + addrlen = sizeof(struct sockaddr_in); + acceptsd = accept(listensd, (struct sockaddr*)&addr, &addrlen); + if (acceptsd < 0) + { + message("net_reader: accept failure: %d\n", errno); + continue; + } + message("net_reader: Connection accepted on sd=%d\n", acceptsd); + + /* Configure to "linger" until all data is sent when the socket is closed */ + +#ifdef POLL_HAVE_SOLINGER + ling.l_onoff = 1; + ling.l_linger = 30; /* timeout is seconds */ + if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0) + { + message("net_reader: setsockopt SO_LINGER failure: %d\n", errno); + goto errout_with_acceptsd; + } +#endif + + /* Handle incoming messsages on the connection. */ + + net_receive(acceptsd); + + message("net_reader: Closing sd=%d\n", acceptsd); + close(acceptsd); + } + +#ifdef POLL_HAVE_SOLINGER +errout_with_acceptsd: + close(acceptsd); +#endif +errout_with_listensd: + close(listensd); +errout: + return NULL; +} diff --git a/apps/examples/poll/poll_internal.h b/apps/examples/poll/poll_internal.h new file mode 100644 index 000000000..cbf42ac56 --- /dev/null +++ b/apps/examples/poll/poll_internal.h @@ -0,0 +1,128 @@ +/**************************************************************************** + * examples/poll/poll_internal.h + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 __EXAMPLES_PIPE_PIPE_H +#define __EXAMPLES_PIPE_PIPE_H + +/**************************************************************************** + * Compilation Switches + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <pthread.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#ifdef CONFIG_DISABLE_POLL +# error "The polling API is disabled" +#endif + +/* Here are all of the configuration settings that must be met to have TCP/IP + * poll/select support. This kind of looks like overkill. + * + * CONFIG_NET - Network support must be enabled + * CONFIG_NSOCKET_DESCRIPTORS - Socket descriptors must be allocated + * CONFIG_NET_TCP - Only support on TCP (because read-ahead + * ibuffering s not yet support for UDP) + * CONFIG_NET_NTCP_READAHEAD_BUFFERS - TCP/IP read-ahead buffering must be enabled + */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \ + defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 +# define HAVE_NETPOLL 1 +#else +# undef HAVE_NETPOLL +#endif + +/* If debug is enabled, then use lib_rawprintf so that OS debug output and + * the test output are synchronized. + * + * These macros will differ depending upon if the toolchain supports + * macros with a variable number of arguments or not. + */ + +#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 + +#define FIFO_PATH1 "/dev/fifo0" +#define FIFO_PATH2 "/dev/fifo1" + +#define POLL_LISTENER_DELAY 2000 /* 2 seconds */ +#define SELECT_LISTENER_DELAY 4 /* 4 seconds */ +#define NET_LISTENER_DELAY 3 /* 3 seconds */ +#define WRITER_DELAY 6 /* 6 seconds */ + +#define LISTENER_PORT 5471 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern void *poll_listener(pthread_addr_t pvarg); +extern void *select_listener(pthread_addr_t pvarg); + +#ifdef HAVE_NETPOLL +extern void *net_listener(pthread_addr_t pvarg); +extern void *net_reader(pthread_addr_t pvarg); +#endif +#endif /* __EXAMPLES_PIPE_PIPE_H */ diff --git a/apps/examples/poll/poll_listener.c b/apps/examples/poll/poll_listener.c new file mode 100644 index 000000000..816647e34 --- /dev/null +++ b/apps/examples/poll/poll_listener.c @@ -0,0 +1,262 @@ +/**************************************************************************** + * examples/poll/poll_listener.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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/stat.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <poll.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#if defined(CONFIG_DEV_CONSOLE) && !defined(CONFIG_DEV_LOWCONSOLE) +# define HAVE_CONSOLE +# define NPOLLFDS 2 +# define CONSNDX 0 +# define FIFONDX 1 +#else +# undef HAVE_CONSOLE +# define NPOLLFDS 1 +# define FIFONDX 0 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: poll_listener + ****************************************************************************/ + +void *poll_listener(pthread_addr_t pvarg) +{ + struct pollfd fds[NPOLLFDS]; + char buffer[64]; + ssize_t nbytes; + bool timeout; + bool pollin; + int nevents; + int fd; + int ret; + int i; + + /* Open the FIFO for non-blocking read */ + + message("poll_listener: Opening %s for non-blocking read\n", FIFO_PATH1); + fd = open(FIFO_PATH1, O_RDONLY|O_NONBLOCK); + if (fd < 0) + { + message("poll_listener: ERROR Failed to open FIFO %s: %d\n", + FIFO_PATH1, errno); + (void)close(fd); + return (void*)-1; + } + + /* Loop forever */ + + for (;;) + { + message("poll_listener: Calling poll()\n"); + + memset(fds, 0, sizeof(struct pollfd)*NPOLLFDS); +#ifdef HAVE_CONSOLE + fds[CONSNDX].fd = 0; + fds[CONSNDX].events = POLLIN; + fds[CONSNDX].revents = 0; +#endif + fds[FIFONDX].fd = fd; + fds[FIFONDX].events = POLLIN; + fds[FIFONDX].revents = 0; + + timeout = false; + pollin = false; + + ret = poll(fds, NPOLLFDS, POLL_LISTENER_DELAY); + + message("\npoll_listener: poll returned: %d\n", ret); + if (ret < 0) + { + message("poll_listener: ERROR poll failed: %d\n", errno); + } + else if (ret == 0) + { + message("poll_listener: Timeout\n"); + timeout = true; + } + else if (ret > NPOLLFDS) + { + message("poll_listener: ERROR poll reported: %d\n"); + } + else + { + pollin = true; + } + + nevents = 0; + for (i = 0; i < NPOLLFDS; i++) + { + message("poll_listener: FIFO revents[%d]=%02x\n", i, fds[i].revents); + if (timeout) + { + if (fds[i].revents != 0) + { + message("poll_listener: ERROR? expected revents=00, received revents[%d]=%02x\n", + fds[i].revents, i); + } + } + else if (pollin) + { + if (fds[i].revents == POLLIN) + { + nevents++; + } + else if (fds[i].revents != 0) + { + message("poll_listener: ERROR unexpected revents[i]=%02x\n", + i, fds[i].revents); + } + } + } + + if (pollin && nevents != ret) + { + message("poll_listener: ERROR found %d events, poll reported %d\n", nevents, ret); + } + + /* In any event, read until the pipe/serial is empty */ + + for (i = 0; i < NPOLLFDS; i++) + { + do + { +#ifdef HAVE_CONSOLE + /* Hack to work around the fact that the console driver on the + * simulator is always non-blocking. + */ + + if (i == CONSNDX) + { + if ((fds[CONSNDX].revents & POLLIN) != 0) + { + buffer[0] = getchar(); + nbytes = 1; + } + else + { + nbytes = 0; + } + } + else +#endif + { + /* The pipe works differently, it returns whatever data + * it has available without blocking. + */ + + nbytes = read(fds[i].fd, buffer, 63); + } + + if (nbytes <= 0) + { + if (nbytes == 0 || errno == EAGAIN) + { + if ((fds[i].revents & POLLIN) != 0) + { + message("poll_listener: ERROR no read data[%d]\n", i); + } + } + else if (errno != EINTR) + { + message("poll_listener: read[%d] failed: %d\n", i, errno); + } + nbytes = 0; + } + else + { + if (timeout) + { + message("poll_listener: ERROR? Poll timeout, but data read[%d]\n", i); + message(" (might just be a race condition)\n"); + } + + buffer[nbytes] = '\0'; + message("poll_listener: Read[%d] '%s' (%d bytes)\n", i, buffer, nbytes); + } + + /* Suppress error report if no read data on the next time through */ + + fds[i].revents = 0; + } + while (nbytes > 0); + } + + /* Make sure that everything is displayed */ + + msgflush(); + } + + /* Won't get here */ + + (void)close(fd); + return NULL; +} diff --git a/apps/examples/poll/poll_main.c b/apps/examples/poll/poll_main.c new file mode 100644 index 000000000..3db0150e7 --- /dev/null +++ b/apps/examples/poll/poll_main.c @@ -0,0 +1,221 @@ +/**************************************************************************** + * examples/poll/poll_main.c + * + * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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/stat.h> + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <poll.h> +#include <errno.h> +#include <debug.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + char buffer[64]; + ssize_t nbytes; + pthread_t tid1; + pthread_t tid2; +#ifdef HAVE_NETPOLL + pthread_t tid3; +#endif + int count; + int fd1 = -1; + int fd2 = -1; + int ret; + int exitcode = 0; + + /* Open FIFOs */ + + message("\nuser_start: Creating FIFO %s\n", FIFO_PATH1); + ret = mkfifo(FIFO_PATH1, 0666); + if (ret < 0) + { + message("user_start: mkfifo failed: %d\n", errno); + exitcode = 1; + goto errout; + } + + message("\nuser_start: Creating FIFO %s\n", FIFO_PATH2); + ret = mkfifo(FIFO_PATH2, 0666); + if (ret < 0) + { + message("user_start: mkfifo failed: %d\n", errno); + exitcode = 2; + goto errout; + } + + /* Open the FIFOs for blocking, write */ + + fd1 = open(FIFO_PATH1, O_WRONLY); + if (fd1 < 0) + { + message("user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH1, errno); + exitcode = 3; + goto errout; + } + + fd2 = open(FIFO_PATH2, O_WRONLY); + if (fd2 < 0) + { + message("user_start: Failed to open FIFO %s for writing, errno=%d\n", + FIFO_PATH2, errno); + exitcode = 4; + goto errout; + } + + /* Start the listeners */ + + message("user_start: Starting poll_listener thread\n"); + + ret = pthread_create(&tid1, NULL, poll_listener, NULL); + if (ret != 0) + { + message("user_start: Failed to create poll_listener thread: %d\n", ret); + exitcode = 5; + goto errout; + } + + message("user_start: Starting select_listener thread\n"); + + ret = pthread_create(&tid2, NULL, select_listener, NULL); + if (ret != 0) + { + message("user_start: Failed to create select_listener thread: %d\n", ret); + exitcode = 6; + goto errout; + } + +#ifdef HAVE_NETPOLL +#ifdef CONFIG_NET_TCPBACKLOG + message("user_start: Starting net_listener thread\n"); + + ret = pthread_create(&tid3, NULL, net_listener, NULL); +#else + message("user_start: Starting net_reader thread\n"); + + ret = pthread_create(&tid3, NULL, net_reader, NULL); +#endif + if (ret != 0) + { + message("user_start: Failed to create net_listener thread: %d\n", ret); + } +#endif + + /* Loop forever */ + + for (count = 0; ; count++) + { + /* Send a message to the listener... this should wake the listener + * from the poll. + */ + + sprintf(buffer, "Message %d", count); + nbytes = write(fd1, buffer, strlen(buffer)); + if (nbytes < 0) + { + message("user_start: Write to fd1 failed: %d\n", errno); + exitcode = 7; + goto errout; + } + + nbytes = write(fd2, buffer, strlen(buffer)); + if (nbytes < 0) + { + message("user_start: Write fd2 failed: %d\n", errno); + exitcode = 8; + goto errout; + } + + message("\nuser_start: Sent '%s' (%d bytes)\n", buffer, nbytes); + msgflush(); + + /* Wait awhile. This delay should be long enough that the + * listener will timeout. + */ + + sleep(WRITER_DELAY); + } + +errout: + if (fd1 >= 0) + { + close(fd1); + } + + if (fd2 >= 0) + { + close(fd2); + } + + fflush(stdout); + return exitcode; +} diff --git a/apps/examples/poll/select_listener.c b/apps/examples/poll/select_listener.c new file mode 100644 index 000000000..80039ada3 --- /dev/null +++ b/apps/examples/poll/select_listener.c @@ -0,0 +1,193 @@ +/**************************************************************************** + * examples/poll/select_listener.c + * + * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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/stat.h> +#include <sys/select.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <errno.h> +#include <debug.h> + +#include "poll_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: select_listener + ****************************************************************************/ + +void *select_listener(pthread_addr_t pvarg) +{ + fd_set rfds; + struct timeval tv; + char buffer[64]; + ssize_t nbytes; + bool timeout; + bool ready; + int fd; + int ret; + + /* Open the FIFO for non-blocking read */ + + message("select_listener: Opening %s for non-blocking read\n", FIFO_PATH2); + fd = open(FIFO_PATH2, O_RDONLY|O_NONBLOCK); + if (fd < 0) + { + message("select_listener: ERROR Failed to open FIFO %s: %d\n", + FIFO_PATH2, errno); + (void)close(fd); + return (void*)-1; + } + + /* Loop forever */ + + for (;;) + { + message("select_listener: Calling select()\n"); + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + tv.tv_sec = SELECT_LISTENER_DELAY; + tv.tv_usec = 0; + + timeout = false; + ready = false; + + ret = select(fd+1, (FAR fd_set*)&rfds, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &tv); + message("\nselect_listener: select returned: %d\n", ret); + + if (ret < 0) + { + message("select_listener: ERROR select failed: %d\n"); + } + else if (ret == 0) + { + message("select_listener: Timeout\n"); + timeout = true; + } + else + { + if (ret != 1) + { + message("select_listener: ERROR poll reported: %d\n"); + } + else + { + ready = true; + } + + if (!FD_ISSET(fd, rfds)) + { + message("select_listener: ERROR fd=%d not in fd_set\n"); + } + } + + /* In any event, read until the pipe is empty */ + + do + { + nbytes = read(fd, buffer, 63); + if (nbytes <= 0) + { + if (nbytes == 0 || errno == EAGAIN) + { + if (ready) + { + message("select_listener: ERROR no read data\n"); + } + } + else if (errno != EINTR) + { + message("select_listener: read failed: %d\n", errno); + } + nbytes = 0; + } + else + { + if (timeout) + { + message("select_listener: ERROR? Poll timeout, but data read\n"); + message(" (might just be a race condition)\n"); + } + + buffer[nbytes] = '\0'; + message("select_listener: Read '%s' (%d bytes)\n", buffer, nbytes); + } + + timeout = false; + ready = false; + } + while (nbytes > 0); + + /* Make sure that everything is displayed */ + + msgflush(); + } + + /* Won't get here */ + + (void)close(fd); + return NULL; +} diff --git a/apps/examples/pwm/Kconfig b/apps/examples/pwm/Kconfig new file mode 100644 index 000000000..78edd2178 --- /dev/null +++ b/apps/examples/pwm/Kconfig @@ -0,0 +1,48 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_PWM + bool "Pulse width modulation (PWM) example" + default n + depends on PWM && NSH_BUILTIN_APPS + ---help--- + Enable the Pulse width modulation (PWM) example + +if EXAMPLES_PWM + +config EXAMPLES_PWM_DEVPATH + string "PWM device path" + default "/dev/pwm0" + ---help--- + The path to the PWM device. Default: /dev/pwm0 + +config EXAMPLES_PWM_FREQUENCY + int "Default PWM freququency" + default 100 + ---help--- + The default PWM frequency. Default: 100 Hz + +config EXAMPLES_PWM_DUTYPCT + int "Default PWM duty percentage" + default 50 + ---help--- + The default PWM duty as a percentage. Default: 50% + +config EXAMPLES_PWM_DURATION + int "Default PWM duration" + default 5 if !EXAMPLES_PWM_PULSECOUNT + ---help--- + The default PWM pulse train duration in seconds. Used only if the current + pulse count is zero (pulse countis only supported if CONFIG_PWM_PULSECOUNT + is defined). Default: 5 seconds + +config EXAMPLES_PWM_PULSECOUNT + int "Default pulse count" + default 0 + ---help--- + The initial PWM pulse count. This option is only available if CONFIG_PWM_PULSECOUNT + is nonzero. Default: 0 (i.e., use the duration, not the count). + +endif diff --git a/apps/examples/pwm/Makefile b/apps/examples/pwm/Makefile new file mode 100644 index 000000000..efbdb048e --- /dev/null +++ b/apps/examples/pwm/Makefile @@ -0,0 +1,103 @@ +############################################################################ +# apps/examples/pwm/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# PWM Example. + +ASRCS = +CSRCS = pwm_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 . + +# PWM built-in application info + +APPNAME = pwm +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: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ + +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 diff --git a/apps/examples/pwm/pwm.h b/apps/examples/pwm/pwm.h new file mode 100644 index 000000000..5c049a8f8 --- /dev/null +++ b/apps/examples/pwm/pwm.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * examples/examples/pwm/pwm.h + * + * 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 + * 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_PWM_PWM_H +#define __APPS_EXAMPLES_PWM_PWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_NSH_BUILTIN_APPS - Build the PWM test as an NSH built-in function. + * Default: Not built! The example can only be used as an NSH built-in + * application + * CONFIG_EXAMPLES_PWM_DEVPATH - The path to the PWM device. Default: /dev/pwm0 + * CONFIG_EXAMPLES_PWM_FREQUENCY - The initial PWM frequency. Default: 100 Hz + * CONFIG_EXAMPLES_PWM_DUTYPCT - The initial PWM duty as a percentage. Default: 50% + * CONFIG_EXAMPLES_PWM_DURATION - The initial PWM pulse train duration in seconds. + * Used only if the current pulse count is zero (pulse count is only supported + * if CONFIG_PWM_PULSECOUNT is defined). Default: 5 seconds + * CONFIG_EXAMPLES_PWM_PULSECOUNT - The initial PWM pulse count. This option is + * only available if CONFIG_PWM_PULSECOUNT is defined. Default: 0 (i.e., use + * the duration, not the count). + */ + +#ifndef CONFIG_PWM +# error "PWM device support is not enabled (CONFIG_PWM)" +#endif + +#ifndef CONFIG_NSH_BUILTIN_APPS +# warning "The PWM example only works as an NSH built-in application (CONFIG_NSH_BUILTIN_APPS)" +#endif + +#ifndef CONFIG_EXAMPLES_PWM_DEVPATH +# define CONFIG_EXAMPLES_PWM_DEVPATH "/dev/pwm0" +#endif + +#ifndef CONFIG_EXAMPLES_PWM_FREQUENCY +# define CONFIG_EXAMPLES_PWM_FREQUENCY 100 +#endif + +#ifndef CONFIG_EXAMPLES_PWM_DUTYPCT +# define CONFIG_EXAMPLES_PWM_DUTYPCT 50 +#endif + +#ifndef CONFIG_EXAMPLES_PWM_DURATION +# define CONFIG_EXAMPLES_PWM_DURATION 5 +#endif + +#ifndef CONFIG_EXAMPLES_PWM_COUNT +# define CONFIG_EXAMPLES_PWM_COUNT 0 +#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 + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_devinit() + * + * Description: + * Perform architecuture-specific initialization of the PWM hardware. This + * interface must be provided by all configurations using apps/examples/pwm + * + ****************************************************************************/ + +int pwm_devinit(void); + +#endif /* __APPS_EXAMPLES_PWM_PWM_H */ diff --git a/apps/examples/pwm/pwm_main.c b/apps/examples/pwm/pwm_main.c new file mode 100644 index 000000000..64c5dfb2c --- /dev/null +++ b/apps/examples/pwm/pwm_main.c @@ -0,0 +1,394 @@ +/**************************************************************************** + * examples/pwm/pwm_main.c + * + * 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 + * 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 <errno.h> +#include <debug.h> + +#include <nuttx/pwm.h> + +#include "pwm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct pwm_state_s +{ + bool initialized; + FAR char *devpath; + uint8_t duty; + uint32_t freq; +#ifdef CONFIG_PWM_PULSECOUNT + uint32_t count; +#endif + int duration; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct pwm_state_s g_pwmstate; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_devpath + ****************************************************************************/ + +static void pwm_devpath(FAR struct pwm_state_s *pwm, FAR const char *devpath) +{ + /* Get rid of any old device path */ + + if (pwm->devpath) + { + free(pwm->devpath); + } + + /* Then set-up the new device path by copying the string */ + + pwm->devpath = strdup(devpath); +} + +/**************************************************************************** + * Name: pwm_help + ****************************************************************************/ + +static void pwm_help(FAR struct pwm_state_s *pwm) +{ + message("Usage: pwm [OPTIONS]\n"); + message("\nArguments are \"sticky\". For example, once the PWM frequency is\n"); + message("specified, that frequency will be re-used until it is changed.\n"); + message("\n\"sticky\" OPTIONS include:\n"); + message(" [-p devpath] selects the PWM device. " + "Default: %s Current: %s\n", + CONFIG_EXAMPLES_PWM_DEVPATH, pwm->devpath ? pwm->devpath : "NONE"); + message(" [-f addr] selects the pulse frequency. " + "Default: %d Hz Current: %d Hz\n", + CONFIG_EXAMPLES_PWM_FREQUENCY, pwm->freq); + message(" [-d duty] selcts the pulse duty as a percentage. " + "Default: %d %% Current: %d %%\n", + CONFIG_EXAMPLES_PWM_DUTYPCT, pwm->duty); +#ifdef CONFIG_PWM_PULSECOUNT + message(" [-n count] selects the pulse count. " + "Default: %d Current: %d\n", + CONFIG_EXAMPLES_PWM_COUNT, pwm->count); +#endif + message(" [-t duration] is the duration of the pulse train in seconds. " + "Default: %d Current: %d\n", + CONFIG_EXAMPLES_PWM_DURATION, pwm->duration); + message(" [-h] shows this message and exits\n"); +} + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +static 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; + } +} + +/**************************************************************************** + * Name: arg_decimal + ****************************************************************************/ + +static 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; +} + +/**************************************************************************** + * Name: parse_args + ****************************************************************************/ + +static void parse_args(FAR struct pwm_state_s *pwm, int argc, FAR char **argv) +{ + FAR char *ptr; + FAR char *str; + long value; + int index; + int nargs; + + for (index = 1; index < argc; ) + { + ptr = argv[index]; + if (ptr[0] != '-') + { + message("Invalid options format: %s\n", ptr); + exit(0); + } + + switch (ptr[1]) + { + case 'f': + nargs = arg_decimal(&argv[index], &value); + if (value < 1) + { + message("Frequency out of range: %ld\n", value); + exit(1); + } + + pwm->freq = (uint32_t)value; + index += nargs; + break; + + case 'd': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > 99) + { + message("Duty out of range: %ld\n", value); + exit(1); + } + + pwm->duty = (uint8_t)value; + index += nargs; + break; + +#ifdef CONFIG_PWM_PULSECOUNT + case 'n': + nargs = arg_decimal(&argv[index], &value); + if (value < 0) + { + message("Count must be non-negative: %ld\n", value); + exit(1); + } + + pwm->count = (uint32_t)value; + index += nargs; + break; + +#endif + case 'p': + nargs = arg_string(&argv[index], &str); + pwm_devpath(pwm, str); + index += nargs; + break; + + case 't': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > INT_MAX) + { + message("Duration out of range: %ld\n", value); + exit(1); + } + + pwm->duration = (int)value; + index += nargs; + break; + + case 'h': + pwm_help(pwm); + exit(0); + + default: + message("Unsupported option: %s\n", ptr); + pwm_help(pwm); + exit(1); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/pwm_main + ****************************************************************************/ + +int pwm_main(int argc, char *argv[]) +{ + struct pwm_info_s info; + int fd; + int ret; + + /* Initialize the state data */ + + if (!g_pwmstate.initialized) + { + g_pwmstate.duty = CONFIG_EXAMPLES_PWM_DUTYPCT; + g_pwmstate.freq = CONFIG_EXAMPLES_PWM_FREQUENCY; + g_pwmstate.duration = CONFIG_EXAMPLES_PWM_DURATION; +#ifdef CONFIG_PWM_PULSECOUNT + g_pwmstate.count = CONFIG_EXAMPLES_PWM_COUNT; +#endif + g_pwmstate.initialized = true; + } + + /* Parse the command line */ + + parse_args(&g_pwmstate, argc, argv); + + /* Has a device been assigned? */ + + if (!g_pwmstate.devpath) + { + /* No.. use the default device */ + + pwm_devpath(&g_pwmstate, CONFIG_EXAMPLES_PWM_DEVPATH); + } + + /* Initialization of the PWM hardware is performed by logic external to + * this test. + */ + + ret = pwm_devinit(); + if (ret != OK) + { + message("pwm_main: pwm_devinit failed: %d\n", ret); + goto errout; + } + + /* Open the PWM device for reading */ + + fd = open(g_pwmstate.devpath, O_RDONLY); + if (fd < 0) + { + message("pwm_main: open %s failed: %d\n", g_pwmstate.devpath, errno); + goto errout; + } + + /* Configure the characteristics of the pulse train */ + + info.frequency = g_pwmstate.freq; + info.duty = ((uint32_t)g_pwmstate.duty << 16) / 100; +#ifdef CONFIG_PWM_PULSECOUNT + info.count = g_pwmstate.count; + + message("pwm_main: starting output with frequency: %d duty: %08x count: %d\n", + info.frequency, info.duty, info.count); + +#else + message("pwm_main: starting output with frequency: %d duty: %08x\n", + info.frequency, info.duty); + +#endif + + ret = ioctl(fd, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&info)); + if (ret < 0) + { + message("pwm_main: ioctl(PWMIOC_SETCHARACTERISTICS) failed: %d\n", errno); + goto errout_with_dev; + } + + /* Then start the pulse train. Since the driver was opened in blocking + * mode, this call will block if the count value is greater than zero. + */ + + ret = ioctl(fd, PWMIOC_START, 0); + if (ret < 0) + { + message("pwm_main: ioctl(PWMIOC_START) failed: %d\n", errno); + goto errout_with_dev; + } + + /* It a non-zero count was not specified, then wait for the selected + * duration, then stop the PWM output. + */ + +#ifdef CONFIG_PWM_PULSECOUNT + if (info.count == 0) +#endif + { + /* Wait for the specified duration */ + + sleep(g_pwmstate.duration); + + /* Then stop the pulse train */ + + message("pwm_main: stopping output\n", info.frequency, info.duty); + + ret = ioctl(fd, PWMIOC_STOP, 0); + if (ret < 0) + { + message("pwm_main: ioctl(PWMIOC_STOP) failed: %d\n", errno); + goto errout_with_dev; + } + } + + close(fd); + msgflush(); + return OK; + +errout_with_dev: + close(fd); +errout: + msgflush(); + return ERROR; +} diff --git a/apps/examples/qencoder/Kconfig b/apps/examples/qencoder/Kconfig new file mode 100644 index 000000000..e0026d08c --- /dev/null +++ b/apps/examples/qencoder/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_QENCODER + bool "Quadrature encoder example" + default n + ---help--- + Enable the quadrature encoder example + +if EXAMPLES_QENCODER +endif diff --git a/apps/examples/qencoder/Makefile b/apps/examples/qencoder/Makefile new file mode 100644 index 000000000..3f3fc9def --- /dev/null +++ b/apps/examples/qencoder/Makefile @@ -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 diff --git a/apps/examples/qencoder/qe.h b/apps/examples/qencoder/qe.h new file mode 100644 index 000000000..4c03689ab --- /dev/null +++ b/apps/examples/qencoder/qe.h @@ -0,0 +1,134 @@ +/**************************************************************************** + * 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. + * CONFIG_EXAMPLES_QENCODER_DELAY - This value provides the delay (in + * milliseonds) between each sample. If CONFIG_NSH_BUILTIN_APPS + * is defined, then this value is the default delay if no other delay is + * provided on the command line. Default: 100 milliseconds + */ + +#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 + +#ifndef CONFIG_EXAMPLES_QENCODER_DELAY +# define CONFIG_EXAMPLES_QENCODER_DELAY 100 +#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 initialized; /* True: QE devices have been initialized */ + bool reset; /* True: set the count back to zero */ + FAR char *devpath; /* Path to the QE device */ + unsigned int nloops; /* Collect this number of samples */ + unsigned int delay; /* Delay this number of seconds between samples */ +}; +#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 */ diff --git a/apps/examples/qencoder/qe_main.c b/apps/examples/qencoder/qe_main.c new file mode 100644 index 000000000..c58a2b0ad --- /dev/null +++ b/apps/examples/qencoder/qe_main.c @@ -0,0 +1,370 @@ +/**************************************************************************** + * 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 <string.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_devpath + ****************************************************************************/ + +static void qe_devpath(FAR const char *devpath) +{ + /* Get rid of any old device path */ + + if (g_qeexample.devpath) + { + free(g_qeexample.devpath); + } + + /* The set-up the new device path by copying the string */ + + g_qeexample.devpath = strdup(devpath); +} + +/**************************************************************************** + * Name: qe_help + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static void qe_help(void) +{ + message("\nUsage: qe [OPTIONS]\n\n"); + message("OPTIONS include:\n"); + message(" [-p devpath] QE device path\n"); + message(" [-n samples] Number of samples\n"); + message(" [-t msec] Delay between samples (msec)\n"); + message(" [-r] Reset the position to zero\n"); + message(" [-h] Shows this message and exits\n\n"); +} +#endif + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +#ifdef CONFIG_NSH_BUILTIN_APPS +static 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 +static 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 +static void parse_args(int argc, FAR char **argv) +{ + FAR char *ptr; + FAR char *str; + long value; + int index; + int nargs; + + g_qeexample.reset = false; + g_qeexample.nloops = 1; + g_qeexample.delay = CONFIG_EXAMPLES_QENCODER_DELAY; + + 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 = (unsigned int)value; + index += nargs; + break; + + case 'p': + nargs = arg_string(&argv[index], &str); + qe_devpath(str); + index += nargs; + break; + + case 't': + nargs = arg_decimal(&argv[index], &value); + if (value < 0 || value > INT_MAX) + { + message("Sample delay out of range: %ld\n", value); + exit(1); + } + + g_qeexample.delay = (unsigned 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 + + /* Check if we have initialized */ + + if (!g_qeexample.initialized) + { + /* Initialization of the encoder hardware is performed by logic external to + * this test. + */ + + message(MAIN_STRING "Initializing external encoder(s)\n"); + ret = qe_devinit(); + if (ret != OK) + { + message(MAIN_STRING "qe_devinit failed: %d\n", ret); + exitval = EXIT_FAILURE; + goto errout; + } + + /* Set the default values */ + + qe_devpath(CONFIG_EXAMPLES_QENCODER_DEVPATH); + g_qeexample.initialized = true; + } + + /* Parse command line arguments */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + parse_args(argc, argv); +#endif + + /* Open the encoder device for reading */ + + message(MAIN_STRING "Hardware initialized. Opening the encoder device: %s\n", + g_qeexample.devpath); + + fd = open(g_qeexample.devpath, O_RDONLY); + if (fd < 0) + { + message(MAIN_STRING "open %s failed: %d\n", g_qeexample.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 "%3d. %d\n", nloops+1, position); + } + + /* Delay a little bit */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) + usleep(g_qeexample.delay * 1000); +#else + usleep(CONFIG_EXAMPLES_QENCODER_DELAY * 1000); +#endif + } + +errout_with_dev: + close(fd); + +errout: + message("Terminating!\n"); + msgflush(); + return exitval; +} diff --git a/apps/examples/romfs/Kconfig b/apps/examples/romfs/Kconfig new file mode 100644 index 000000000..5a8c824a3 --- /dev/null +++ b/apps/examples/romfs/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_ROMFS + bool "ROMFS example" + default n + ---help--- + Enable the ROMFS example + +if EXAMPLES_ROMFS +endif diff --git a/apps/examples/romfs/Makefile b/apps/examples/romfs/Makefile new file mode 100644 index 000000000..1db45765a --- /dev/null +++ b/apps/examples/romfs/Makefile @@ -0,0 +1,111 @@ +############################################################################ +# apps/examples/romfs/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# ROMFS File System Example + +ASRCS = +CSRCS = romfs_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 . + +# Common build + +VPATH = + +all: .built +.PHONY: checkgenromfs clean depend disclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +checkgenromfs: + @genromfs -h 1>/dev/null 2>&1 || { \ + echo "Host executable genromfs not available in PATH"; \ + echo "You may need to download in from http://romfs.sourceforge.net/"; \ + exit 1; \ + } + +testdir : testdir.tar.gz + @tar zxf $< || { echo "tar zxf $< failed" ; exit 1 ; } + +testdir.img : checkgenromfs testdir + @genromfs -f $@ -d testdir -V "ROMFS_Test" || { echo "genromfs failed" ; exit 1 ; } + +romfs_testdir.h : testdir.img + @xxd -i $< >$@ || { echo "xxd of $< failed" ; exit 1 ; } + +.built: romfs_testdir.h $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +context: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend testdir.img + +-include Make.dep + diff --git a/apps/examples/romfs/romfs_main.c b/apps/examples/romfs/romfs_main.c new file mode 100644 index 000000000..32b3d2654 --- /dev/null +++ b/apps/examples/romfs/romfs_main.c @@ -0,0 +1,498 @@ +/**************************************************************************** + * examples/romfs/romfs_main.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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. + * + ****************************************************************************/ + +/* Mount the ROMFS image, Verifty that it contains the + * following: + * + * testdir + * |---------- [drwxr-xr-x 4096] adir + * | |------ [-rw-r--r-- 21] anotherfile.txt + * | |------ [drwxr-xr-x 4096] subdir + * | | `-- [-rw-r--r-- 21] subdirfile.txt + * | `------ [-rw-r--r-- 25] yafile.txt + * |---------- [-rw-r--r-- 15] afile.txt + * |---------- [-rw-r--r-- 21] hfile + * `---------- [lrwxrwxrwx 11] ldir -> adir/subdir + * + * testdir/ldir is a soft-link and should not be detectable. + * hfile is a hardlink to subdirfile and should be identical + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> + +#include <nuttx/ramdisk.h> + +#include "romfs_testdir.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* Configuration settings */ + +#ifndef CONFIG_EXAMPLES_ROMFS_RAMDEVNO +# define CONFIG_EXAMPLES_ROMFS_RAMDEVNO 1 +#endif + +#ifndef CONFIG_EXAMPLES_ROMFS_SECTORSIZE +# define CONFIG_EXAMPLES_ROMFS_SECTORSIZE 64 +#endif + +#ifndef CONFIG_EXAMPLES_ROMFS_MOUNTPOINT +# define CONFIG_EXAMPLES_ROMFS_MOUNTPOINT "/usr/local/share" +#endif + +#ifdef CONFIG_DISABLE_MOUNTPOINT +# error "Mountpoint support is disabled" +#endif + +#if CONFIG_NFILE_DESCRIPTORS < 4 +# error "Not enough file descriptors" +#endif + +#ifndef CONFIG_FS_ROMFS +# error "ROMFS support not enabled" +#endif + +#define NSECTORS(b) (((b)+CONFIG_EXAMPLES_ROMFS_SECTORSIZE-1)/CONFIG_EXAMPLES_ROMFS_SECTORSIZE) +#define STR_RAMDEVNO(m) #m +#define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m) +#define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_EXAMPLES_ROMFS_RAMDEVNO) + +#define SCRATCHBUFFER_SIZE 1024 + +/* Test directory stuff */ + +#define WRITABLE_MODE (S_IWOTH|S_IWGRP|S_IWUSR) +#define READABLE_MODE (S_IROTH|S_IRGRP|S_IRUSR) +#define EXECUTABLE_MODE (S_IXOTH|S_IXGRP|S_IXUSR) + +#define DIRECTORY_MODE (S_IFDIR|READABLE_MODE|EXECUTABLE_MODE) +#define FILE_MODE (S_IFREG|READABLE_MODE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct node_s +{ + struct node_s *peer; /* Next node in this directory */ + bool directory; /* True: directory */ + bool found; /* True: found and verified */ + const char *name; /* Node name */ + mode_t mode; /* Expected permissions */ + size_t size; /* Expected size */ + union + { + const char *filecontent; /* Context of text file */ + struct node_s *child; /* Subdirectory start */ + } u; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_afilecontent[] = "This is a file\n"; +static const char g_anotherfilecontent[] = "This is another file\n"; +static const char g_yafilecontent[] = "This is yet another file\n"; +static const char g_subdirfilecontent[] = "File in subdirectory\n"; + +#define g_hfilecontent g_subdirfilecontent + +static struct node_s g_adir; +static struct node_s g_afile; +static struct node_s g_hfile; + +static struct node_s g_anotherfile; +static struct node_s g_subdir; +static struct node_s g_yafile; + +static struct node_s g_subdirfile; + +static int g_nerrors = 0; + +static char g_scratchbuffer[SCRATCHBUFFER_SIZE]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: + ****************************************************************************/ + +static void connectem(void) +{ + g_adir.peer = &g_afile; + g_adir.directory = true; + g_adir.found = false; + g_adir.name = "adir"; + g_adir.mode = DIRECTORY_MODE; + g_adir.size = 0; + g_adir.u.child = &g_anotherfile; + + g_afile.peer = &g_hfile; + g_afile.directory = false; + g_afile.found = false; + g_afile.name = "afile.txt"; + g_afile.mode = FILE_MODE; + g_afile.size = strlen(g_afilecontent); + g_afile.u.filecontent = g_afilecontent; + + g_hfile.peer = NULL; + g_hfile.directory = false; /* Actually a hard link */ + g_hfile.found = false; + g_hfile.name = "hfile"; + g_hfile.mode = FILE_MODE; + g_hfile.size = strlen(g_hfilecontent); + g_hfile.u.filecontent = g_hfilecontent; + + g_anotherfile.peer = &g_yafile; + g_anotherfile.directory = false; + g_anotherfile.found = false; + g_anotherfile.name = "anotherfile.txt"; + g_anotherfile.mode = FILE_MODE; + g_anotherfile.size = strlen(g_anotherfilecontent); + g_anotherfile.u.filecontent = g_anotherfilecontent; + + g_yafile.peer = &g_subdir; + g_yafile.directory = false; + g_yafile.found = false; + g_yafile.name = "yafile.txt"; + g_yafile.mode = FILE_MODE; + g_yafile.size = strlen(g_yafilecontent); + g_yafile.u.filecontent = g_yafilecontent; + + g_subdir.peer = NULL; + g_subdir.directory = true; + g_subdir.found = false; + g_subdir.name = "subdir"; + g_subdir.mode = DIRECTORY_MODE; + g_subdir.size = 0; + g_subdir.u.child = &g_subdirfile; + + g_subdirfile.peer = NULL; + g_subdirfile.directory = false; + g_subdirfile.found = false; + g_subdirfile.name = "subdirfile.txt"; + g_subdirfile.mode = FILE_MODE; + g_subdirfile.size = strlen(g_subdirfilecontent); + g_subdirfile.u.filecontent = g_subdirfilecontent; +} + +/**************************************************************************** + * Name: findindirectory + ****************************************************************************/ + +static struct node_s *findindirectory(struct node_s *entry, const char *name) +{ + for (; entry; entry = entry->peer) + { + if (!entry->found && strcmp(entry->name, name) == 0) + { + entry->found = true; + return entry; + } + } + return NULL; +} + +/**************************************************************************** + * Name: checkattributes + ****************************************************************************/ + +static void checkattributes(const char *path, mode_t mode, size_t size) +{ + struct stat buf; + int ret; + + ret = stat(path, &buf); + if (ret != 0) + { + printf(" -- ERROR: Failed to stat %s: %d\n", path, errno); + g_nerrors++; + return; + } + + if (mode != buf.st_mode) + { + printf(" -- ERROR: Expected mode %08x, got %08x\n", mode, buf.st_mode); + g_nerrors++; + } + + if (size != buf.st_size) + { + printf(" -- ERROR: Expected size %d, got %d\n", mode, buf.st_size); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: checkfile + ****************************************************************************/ + +static void checkfile(const char *path, struct node_s *node) +{ + ssize_t nbytesread; + char *filedata; + int fd; + + /* Open the file */ + + fd = open(path, O_RDONLY); + if (fd < 0) + { + printf(" -- ERROR: Failed to open %s: %d\n", path, errno); + g_nerrors++; + return; + } + + /* Read and verify the file contents */ + + nbytesread = read(fd, g_scratchbuffer, SCRATCHBUFFER_SIZE); + if (nbytesread < 0) + { + printf(" -- ERROR: Failed to read from %s: %d\n", path, errno); + g_nerrors++; + } + else if (nbytesread != node->size) + { + printf(" -- ERROR: Read %d bytes, expected %d\n", nbytesread, node->size); + g_nerrors++; + } + else if (memcmp(g_scratchbuffer, node->u.filecontent, node->size) != 0) + { + g_scratchbuffer[nbytesread] = '\0'; + printf(" -- ERROR: File content read does not match expectation:\n"); + printf(" -- Read: [%s]\n", g_scratchbuffer); + printf(" -- Expected: [%s]\n", node->u.filecontent); + g_nerrors++; + } + + /* Memory map and verify the file contents */ + + filedata = (char*)mmap(NULL, node->size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); + if (!filedata || filedata == (char*)MAP_FAILED) + { + printf(" -- ERROR: mmap of %s failed: %d\n", path, errno); + g_nerrors++; + } + else + { + if (memcmp(filedata, node->u.filecontent, node->size) != 0) + { + memcpy(g_scratchbuffer, filedata, node->size); + g_scratchbuffer[node->size] = '\0'; + printf(" -- ERROR: Mapped file content read does not match expectation:\n"); + printf(" -- Memory: [%s]\n", filedata); + printf(" -- Expected: [%s]\n", node->u.filecontent); + g_nerrors++; + } + munmap(filedata, node->size); + } + + /* Close the file */ + + if (close(fd) != OK) + { + printf(" -- ERROR: Failed to close %s: %d\n", path, errno); + g_nerrors++; + } +} + +/**************************************************************************** + * Name: readdirectories + ****************************************************************************/ + +static void readdirectories(const char *path, struct node_s *entry) +{ + DIR *dirp; + struct node_s *node; + struct dirent *direntry; + char *fullpath; + + printf("Traversing directory: %s\n", path); + dirp = opendir(path); + if (!dirp) + { + printf(" ERROR opendir(\"%s\") failed: %d\n", path, errno); + g_nerrors++; + return; + } + + for (direntry = readdir(dirp); direntry; direntry = readdir(dirp)) + { + if (strcmp(direntry->d_name, ".") == 0 || strcmp(direntry->d_name, "..") == 0) + { + printf(" Skipping %s\n", direntry->d_name); + continue; + } + + node = findindirectory(entry, direntry->d_name); + if (!node) + { + printf(" ERROR: No node found for %s\n", direntry->d_name); + g_nerrors++; + continue; + } + + /* Get the full path to the entry */ + + sprintf(g_scratchbuffer, "%s/%s", path, direntry->d_name); + fullpath = strdup(g_scratchbuffer); + + if (DIRENT_ISDIRECTORY(direntry->d_type)) + { + printf(" DIRECTORY: %s/\n", fullpath); + if (!node->directory) + { + printf(" -- ERROR: Expected type directory\n"); + g_nerrors++; + } + else + { + checkattributes(fullpath, node->mode, 0); + readdirectories(fullpath, node->u.child); + printf("Continuing directory: %s\n", path); + } + } + else + { + printf(" FILE: %s/\n", fullpath); + if (node->directory) + { + printf(" -- ERROR: Expected type file\n"); + g_nerrors++; + } + else + { + checkattributes(fullpath, node->mode, node->size); + checkfile(fullpath, node); + } + } + free(fullpath); + } + + closedir(dirp); +} + +/**************************************************************************** + * Name: checkdirectories + ****************************************************************************/ + +static void checkdirectories(struct node_s *entry) +{ + for (; entry; entry = entry->peer) + { + if (!entry->found ) + { + printf("ERROR: %s never found\n", entry->name); + g_nerrors++; + } + + if (entry->directory) + { + checkdirectories(entry->u.child); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ + int ret; + + /* Create a RAM disk for the test */ + + ret = romdisk_register(CONFIG_EXAMPLES_ROMFS_RAMDEVNO, testdir_img, + NSECTORS(testdir_img_len), CONFIG_EXAMPLES_ROMFS_SECTORSIZE); + if (ret < 0) + { + printf("ERROR: Failed to create RAM disk\n"); + return 1; + } + + /* Mount the test file system */ + + printf("Mounting ROMFS filesystem at target=%s with source=%s\n", + CONFIG_EXAMPLES_ROMFS_MOUNTPOINT, MOUNT_DEVNAME); + + ret = mount(MOUNT_DEVNAME, CONFIG_EXAMPLES_ROMFS_MOUNTPOINT, "romfs", MS_RDONLY, NULL); + if (ret < 0) + { + printf("ERROR: Mount failed: %d\n", errno); + return 1; + } + + /* Perform the test */ + + connectem(); + readdirectories(CONFIG_EXAMPLES_ROMFS_MOUNTPOINT, &g_adir); + checkdirectories(&g_adir); + + if (g_nerrors) + { + printf("Finished with %d errors\n", g_nerrors); + return g_nerrors; + } + + printf("PASSED\n"); + return 0; +} diff --git a/apps/examples/romfs/romfs_testdir.h b/apps/examples/romfs/romfs_testdir.h new file mode 100644 index 000000000..53f93105c --- /dev/null +++ b/apps/examples/romfs/romfs_testdir.h @@ -0,0 +1,89 @@ +unsigned char testdir_img[] = { + 0x2d, 0x72, 0x6f, 0x6d, 0x31, 0x66, 0x73, 0x2d, 0x00, 0x00, 0x02, 0x60, + 0x27, 0x43, 0x4a, 0x8a, 0x52, 0x4f, 0x4d, 0x46, 0x53, 0x5f, 0x54, 0x65, + 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x97, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x80, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x93, 0x9b, 0x95, 0xf0, 0x6c, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x64, 0x69, 0x72, + 0x2f, 0x73, 0x75, 0x62, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x9e, 0x9b, 0x93, 0xc5, 0x61, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x58, 0x47, 0x43, 0xf1, + 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x2e, + 0x74, 0x78, 0x74, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, + 0xa1, 0xc5, 0x69, 0xd8, 0x79, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, + 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x79, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x90, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xfe, 0x20, 0x2e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0xd1, 0xd1, 0xfe, 0x70, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x23, 0x18, 0x9c, 0x03, + 0x73, 0x75, 0x62, 0x64, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd2, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x15, 0x3e, 0x3f, 0x06, 0xd8, 0x73, 0x75, 0x62, 0x64, + 0x69, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x00, + 0x46, 0x69, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x75, 0x62, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, + 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xfc, 0xa0, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x70, 0x2e, 0x2e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x99, 0x92, 0xd4, 0x68, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc5, 0x6b, 0x22, 0x0b, + 0x61, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +unsigned int testdir_img_len = 1024; diff --git a/apps/examples/romfs/testdir.tar.gz b/apps/examples/romfs/testdir.tar.gz Binary files differnew file mode 100644 index 000000000..cd0e9c518 --- /dev/null +++ b/apps/examples/romfs/testdir.tar.gz diff --git a/apps/examples/romfs/testdir.txt b/apps/examples/romfs/testdir.txt new file mode 100644 index 000000000..e321d6ded --- /dev/null +++ b/apps/examples/romfs/testdir.txt @@ -0,0 +1,105 @@ +VOLUME HEADER: Name=ROMFS_Test +0000000: 2d72 6f6d 3166 732d 0000 0260 2743 4a8a -rom1fs-...`'CJ. +0000010: 524f 4d46 535f 5465 7374 0000 0000 0000 ROMFS_Test...... + +FILE HEADER 1: Name=. +0000020: 0000 0049 0000 0020 0000 0000 d1ff ff97 ...I... ........ +0000030: 2e00 0000 0000 0000 0000 0000 0000 0000 ................ + +FILE HEADER 2: Name=.. +0000040: 0000 0060 0000 0020 0000 0000 d1d1 ff80 ...`... ........ +0000050: 2e2e 0000 0000 0000 0000 0000 0000 0000 ................ + +FILE HEADER 3: Name=ldir +0000060: 0000 0093 0000 0000 0000 000b 939b 95f0 ................ +0000070: 6c64 6972 0000 0000 0000 0000 0000 0000 ldir............ + + FILE CONTENT: + 0000080: 6164 6972 2f73 7562 6469 7200 0000 0000 adir/subdir..... + +FILE HEADER 4: Name=adir +0000090: 0000 0219 0000 00b0 0000 0000 9e9b 93c5 ................ +00000a0: 6164 6972 0000 0000 0000 0000 0000 0000 adir............ + + FILE HEADER 4.1: Name=anotherfile.txt + 00000b0: 0000 00f2 0000 0000 0000 0015 5847 43f1 ............XGC. + 00000c0: 616e 6f74 6865 7266 696c 652e 7478 7400 anotherfile.txt. + + FILE CONTENT: + 00000d0: 5468 6973 2069 7320 616e 6f74 6865 7220 This is another + 00000e0: 6669 6c65 0a00 0000 0000 0000 0000 0000 file............ + + FILE HEADER 4.2: Name=yafile.txt + 00000f0: 0000 0132 0000 0000 0000 0019 a1c5 69d8 ...2..........i. + 0000100: 7961 6669 6c65 2e74 7874 0000 0000 0000 yafile.txt...... + + FILE CONTENT: + 0000110: 5468 6973 2069 7320 7965 7420 616e 6f74 This is yet anot + 0000120: 6865 7220 6669 6c65 0a00 0000 0000 0000 her file........ + + FILE HEADER 4.3: Name=. + 0000130: 0000 0150 0000 0090 0000 0000 d1ff fe20 ...P........... + 0000140: 2e00 0000 0000 0000 0000 0000 0000 0000 ................ + + FILE HEADER 4.4: Name=.. + 0000150: 0000 0170 0000 0020 0000 0000 d1d1 fe70 ...p... .......p + 0000160: 2e2e 0000 0000 0000 0000 0000 0000 0000 ................ + + FILE HEADER 4.5: Name=subdir + 0000170: 0000 0009 0000 0190 0000 0000 2318 9c03 ............#... + 0000180: 7375 6264 6972 0000 0000 0000 0000 0000 subdir.......... + + FILE HEADER 4.5.1: Name=subdirfile.txt + 0000190: 0000 01d2 0000 0000 0000 0015 3e3f 06d8 ............>?.. + 00001a0: 7375 6264 6972 6669 6c65 2e74 7874 0000 subdirfile.txt.. + + FILE CONTENT: + 00001b0: 4669 6c65 2069 6e20 7375 6264 6972 6563 File in subdirec + 00001c0: 746f 7279 0a00 0000 0000 0000 0000 0000 tory............ + + FILE HEADER 4.5.2: Name=. + 00001d0: 0000 01f0 0000 0170 0000 0000 d1ff fca0 .......p........ + 00001e0: 2e00 0000 0000 0000 0000 0000 0000 0000 ................ + + FILE HEADER 4.5.3: Name=.. + 00001f0: 0000 0000 0000 0090 0000 0000 d1d1 ff70 ...............p + 0000200: 2e2e 0000 0000 0000 0000 0000 0000 0000 ................ + +FILE HEADER 5: Name=hfile +0000210: 0000 0230 0000 0190 0000 0000 3299 92d4 ...0........2... +0000220: 6866 696c 6500 0000 0000 0000 0000 0000 hfile........... + +FILE HEADER 6: Name=afile.txt +0000230: 0000 0002 0000 0000 0000 000f c56b 220b .............k". +0000240: 6166 696c 652e 7478 7400 0000 0000 0000 afile.txt....... + + FILE CONTENT: + 0000250: 5468 6973 2069 7320 6120 6669 6c65 0a00 This is a file.. + +PADDING +0000260: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000270: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000280: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000290: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00002f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000300: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000310: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000320: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000330: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000340: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000350: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000360: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000370: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000380: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +0000390: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00003f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ diff --git a/apps/examples/serloop/Kconfig b/apps/examples/serloop/Kconfig new file mode 100644 index 000000000..e52d35b3f --- /dev/null +++ b/apps/examples/serloop/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_SERLOOP + bool "Serial loopback example" + default n + ---help--- + Enable the serial loopback example + +if EXAMPLES_SERLOOP +endif diff --git a/apps/examples/serloop/Makefile b/apps/examples/serloop/Makefile new file mode 100644 index 000000000..67c805d46 --- /dev/null +++ b/apps/examples/serloop/Makefile @@ -0,0 +1,95 @@ +############################################################################ +# apps/examples/serloop/Makefile +# +# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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 + +# Mindlessly simple console loopack test + +ASRCS = +CSRCS = 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 . + +# Common build + +VPATH = + +all: .built +.PHONY: 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: + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep + diff --git a/apps/examples/serloop/main.c b/apps/examples/serloop/main.c new file mode 100644 index 000000000..3c635fe88 --- /dev/null +++ b/apps/examples/serloop/main.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * examples/serloop/main.c + * + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <stdint.h> +#include <stdio.h> +#include <unistd.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * user_start + ****************************************************************************/ + +int user_start(int argc, char *argv[]) +{ +#ifdef CONFIG_EXAMPLES_SERLOOP_BUFIO + int ch; + + for (;;) + { + ch = getchar(); + if (ch < 1) + { + ch = '!'; + } + else if ((ch < 0x20 || ch > 0x7e) && ch != '\n') + { + ch = '.'; + } + putchar(ch); + } +#else + uint8_t ch; + int ret; + + for (;;) + { + ret = read(0, &ch, 1); + if (ret < 1) + { + ch = '!'; + } + else if ((ch < 0x20 || ch > 0x7e) && ch != '\n') + { + ch = '.'; + } + ret = write(1, &ch, 1); + } +#endif + return 0; +} + diff --git a/apps/examples/watchdog/Kconfig b/apps/examples/watchdog/Kconfig new file mode 100644 index 000000000..18daf9327 --- /dev/null +++ b/apps/examples/watchdog/Kconfig @@ -0,0 +1,40 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_WATCHDOG + bool "Watchdog Timer example" + default n + ---help--- + Enable the watchdog timer example + +if EXAMPLES_WATCHDOG + +config EXAMPLES_WATCHDOG_DEVPATH + string "Watchdog device path" + default "/dev/watchdog0" + ---help--- + The path to the watchdog device. Default: /dev/watchdog0 + +config CONFIG_EXAMPLES_WATCHDOG_PINGTIME + int "Watchdog ping time" + default 5000 + ---help--- + Time in milliseconds that the example will ping the watchdog before letting the + watchdog expire. Default: 5000 milliseconds. + +config CONFIG_EXAMPLES_WATCHDOG_PINGDELAY + int "Watchdog ping delay" + default 500 + ---help--- + Time delay between pings in milliseconds. Default: 500 milliseconds. + +config EXAMPLES_WATCHDOG_TIMEOUT + int "Watchdog timeout" + default 2000 + ---help--- + The watchdog timeout value in milliseconds before the watchdog timer + expires. Default: 2000 milliseconds. + +endif diff --git a/apps/examples/watchdog/Makefile b/apps/examples/watchdog/Makefile new file mode 100644 index 000000000..d2739dbb0 --- /dev/null +++ b/apps/examples/watchdog/Makefile @@ -0,0 +1,103 @@ +############################################################################ +# apps/examples/watchdog/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 + +# Watchdog Timer Example. + +ASRCS = +CSRCS = watchdog_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 . + +# Touchscreen built-in application info + +APPNAME = wdog +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: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ + +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 diff --git a/apps/examples/watchdog/watchdog.h b/apps/examples/watchdog/watchdog.h new file mode 100644 index 000000000..dc2dea944 --- /dev/null +++ b/apps/examples/watchdog/watchdog.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * examples/examples/watchdog/watchdog.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __APPS_EXAMPLES_WATCHDOG_WATCHDOG_H +#define __APPS_EXAMPLES_WATCHDOG_WATCHDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_NSH_BUILTIN_APPS - Build the WATCHDOG test as an NSH built-in + * function. Default: Not built! The example can only be used as an NSH + * built-in application + * CONFIG_EXAMPLES_WATCHDOG_DEVPATH - The path to the Watchdog device. + * Default: /dev/watchdog0 + * CONFIG_EXAMPLES_WATCHDOG_PINGTIME - Time in milliseconds that the example + * will ping the watchdog before letting the watchdog expire. Default: 5000 + * milliseconds + * CONFIG_EXAMPLES_WATCHDOG_PINGDELAY - Time delay between pings in + * milliseconds. Default: 500 milliseconds. + * CONFIG_EXAMPLES_WATCHDOG_TIMEOUT - The watchdog timeout value in + * milliseconds before the watchdog timer expires. Default: 2000 + * milliseconds. + */ + +#ifndef CONFIG_WATCHDOG +# error "WATCHDOG device support is not enabled (CONFIG_WATCHDOG)" +#endif + +#ifndef CONFIG_NSH_BUILTIN_APPS +# warning "The WATCHDOG example only works as an NSH built-in application (CONFIG_NSH_BUILTIN_APPS)" +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_DEVPATH +# define CONFIG_EXAMPLES_WATCHDOG_DEVPATH "/dev/watchdog0" +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_PINGTIME +# define CONFIG_EXAMPLES_WATCHDOG_PINGTIME 5000 +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_PINGDELAY +# define CONFIG_EXAMPLES_WATCHDOG_PINGDELAY 500 +#endif + +#ifndef CONFIG_EXAMPLES_WATCHDOG_TIMEOUT +# define CONFIG_EXAMPLES_WATCHDOG_TIMEOUT 2000 +#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 + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __APPS_EXAMPLES_WATCHDOG_WATCHDOG_H */ diff --git a/apps/examples/watchdog/watchdog_main.c b/apps/examples/watchdog/watchdog_main.c new file mode 100644 index 000000000..c1341e0fb --- /dev/null +++ b/apps/examples/watchdog/watchdog_main.c @@ -0,0 +1,357 @@ +/**************************************************************************** + * examples/watchdog/watchdog_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 <errno.h> +#include <debug.h> + +#include <nuttx/watchdog.h> + +#include "watchdog.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct wdog_example_s +{ + uint32_t pingtime; + uint32_t pingdelay; + uint32_t timeout; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wdog_help + ****************************************************************************/ + +static void wdog_help(void) +{ + message("Usage: wdog [-h] [-d <pingtime] [-p <pingdelay>] [-t <timeout>]\n"); + message("\nInitialize the watchdog to the <timeout>. Start the watchdog\n"); + message("timer. Ping for the watchdog for <pingtime> seconds, then let it expire.\n"); + message("\nOptions include:\n"); + message(" [-d <pingtime>] = Selects the <delay> time in milliseconds. Default: %d\n", + CONFIG_EXAMPLES_WATCHDOG_PINGTIME); + message(" [-p <pingdelay] = Time delay between pings in milliseconds. Default: %d\n", + CONFIG_EXAMPLES_WATCHDOG_PINGDELAY); + message(" [-t timeout] = Time in milliseconds that the example will ping the watchdog\n"); + message(" before letting the watchdog expire. Default: %d\n", + CONFIG_EXAMPLES_WATCHDOG_TIMEOUT); + message(" [-h] = Shows this message and exits\n"); +} + +/**************************************************************************** + * Name: arg_string + ****************************************************************************/ + +static 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; + } +} + +/**************************************************************************** + * Name: arg_decimal + ****************************************************************************/ + +static 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; +} + +/**************************************************************************** + * Name: parse_args + ****************************************************************************/ + +static void parse_args(FAR struct wdog_example_s *wdog, int argc, FAR char **argv) +{ + FAR char *ptr; + long value; + int index; + int nargs; + + wdog->pingtime = CONFIG_EXAMPLES_WATCHDOG_PINGTIME; + wdog->pingdelay = CONFIG_EXAMPLES_WATCHDOG_PINGDELAY; + wdog->timeout = CONFIG_EXAMPLES_WATCHDOG_TIMEOUT; + + for (index = 1; index < argc; ) + { + ptr = argv[index]; + if (ptr[0] != '-') + { + message("Invalid options format: %s\n", ptr); + exit(EXIT_SUCCESS); + } + + switch (ptr[1]) + { + case 'd': + nargs = arg_decimal(&argv[index], &value); + if (value < 1) + { + message("Ping delay out of range: %ld\n", value); + exit(EXIT_FAILURE); + } + + wdog->pingdelay = (uint32_t)value; + index += nargs; + break; + + case 'p': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > 99) + { + message("Ping time out of range: %ld\n", value); + exit(EXIT_FAILURE); + } + + wdog->pingtime = (uint8_t)value; + index += nargs; + break; + + case 't': + nargs = arg_decimal(&argv[index], &value); + if (value < 1 || value > INT_MAX) + { + message("Duration out of range: %ld\n", value); + exit(EXIT_FAILURE); + } + + wdog->timeout = (int)value; + index += nargs; + break; + + case 'h': + wdog_help(); + exit(EXIT_SUCCESS); + + default: + message("Unsupported option: %s\n", ptr); + wdog_help(); + exit(EXIT_FAILURE); + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: user_start/wdog_main + ****************************************************************************/ + +int wdog_main(int argc, char *argv[]) +{ + struct wdog_example_s wdog; +#ifdef CONFIG_DEBUG_WATCHDOG + struct watchdog_status_s status; +#endif + long elapsed; + int fd; + int ret; + + /* Parse the command line */ + + parse_args(&wdog, argc, argv); + + /* Initialization of the WATCHDOG hardware is performed by logic external to + * this test. + */ + + ret = up_wdginitialize(); + if (ret != OK) + { + message("wdog_main: up_wdginitialize failed: %d\n", ret); + goto errout; + } + + /* Open the watchdog device for reading */ + + fd = open(CONFIG_EXAMPLES_WATCHDOG_DEVPATH, O_RDONLY); + if (fd < 0) + { + message("wdog_main: open %s failed: %d\n", + CONFIG_EXAMPLES_WATCHDOG_DEVPATH, errno); + goto errout; + } + + /* Set the watchdog timeout */ + + ret = ioctl(fd, WDIOC_SETTIMEOUT, (unsigned long)wdog.timeout); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_SETTIMEOUT) failed: %d\n", errno); + goto errout_with_dev; + } + + /* Then start the watchdog timer. */ + + ret = ioctl(fd, WDIOC_START, 0); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_START) failed: %d\n", errno); + goto errout_with_dev; + } + + /* Then ping */ + + for (elapsed = 0; elapsed < wdog.pingtime; elapsed += wdog.pingdelay) + { + /* Sleep for the requested amount of time */ + + usleep(wdog.pingdelay * 1000); + + /* Show watchdog status. Only if debug is enabled because this + * could interfere with the timer. + */ + +#ifdef CONFIG_DEBUG_WATCHDOG + ret = ioctl(fd, WDIOC_GETSTATUS, (unsigned long)&status); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_GETSTATUS) failed: %d\n", errno); + goto errout_with_dev; + } + message("wdog_main: flags=%08x timeout=%d timeleft=%d\n", + status.flags, status.timeout, status.timeleft); +#endif + + /* Then ping */ + + ret = ioctl(fd, WDIOC_KEEPALIVE, 0); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_KEEPALIVE) failed: %d\n", errno); + goto errout_with_dev; + } + + message(" ping elapsed=%ld\n", elapsed); + msgflush(); + } + + /* Then stop pinging */ + + for (; ; elapsed += wdog.pingdelay) + { + /* Sleep for the requested amount of time */ + + usleep(wdog.pingdelay * 1000); + + /* Show watchdog status. Only if debug is enabled because this + * could interfere with the timer. + */ + +#ifdef CONFIG_DEBUG_WATCHDOG + ret = ioctl(fd, WDIOC_GETSTATUS, (unsigned long)&status); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_GETSTATUS) failed: %d\n", errno); + goto errout_with_dev; + } + message("wdog_main: flags=%08x timeout=%d timeleft=%d\n", + status.flags, status.timeout, status.timeleft); +#endif + + message(" NO ping elapsed=%ld\n", elapsed); + msgflush(); + } + + /* We should not get here */ + + ret = ioctl(fd, WDIOC_STOP, 0); + if (ret < 0) + { + message("wdog_main: ioctl(WDIOC_STOP) failed: %d\n", errno); + goto errout_with_dev; + } + + close(fd); + msgflush(); + return OK; + +errout_with_dev: + close(fd); +errout: + msgflush(); + return ERROR; +} |