diff options
author | Doug Weibel <deweibel@gmail.com> | 2012-10-21 14:27:36 -0600 |
---|---|---|
committer | Doug Weibel <deweibel@gmail.com> | 2012-10-21 14:27:36 -0600 |
commit | 64ba024db229a0e64f95a104a822670663a3763d (patch) | |
tree | e081299a68f74195034e67c0f9ec3a37f7941107 /apps | |
parent | 0a0215338a4bd6550805072d036c6cb396e7497a (diff) | |
parent | 73521cbc66fa4fbc350c15cef277fabfce89c150 (diff) | |
download | px4-firmware-64ba024db229a0e64f95a104a822670663a3763d.tar.gz px4-firmware-64ba024db229a0e64f95a104a822670663a3763d.tar.bz2 px4-firmware-64ba024db229a0e64f95a104a822670663a3763d.zip |
Merge branch 'master' of https://github.com/PX4/Firmware
Diffstat (limited to 'apps')
33 files changed, 1221 insertions, 1070 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt index d24494f54..7375adccf 100644 --- a/apps/ChangeLog.txt +++ b/apps/ChangeLog.txt @@ -279,14 +279,14 @@ * apps/*/Make.defs: Numerous fixes needed to use the automated configuration (from Richard Cochran). -6.22 2012-xx-xx Gregory Nutt <gnutt@nuttx.org> +6.22 2012-09-29 Gregory Nutt <gnutt@nuttx.org> * apps/netutils/thttpd/thttpd_cgi.c: Missing NULL in argv[] list (contributed by Kate). * apps/nshlib/nsh_parse.c: CONFIG_NSH_DISABLE_WGET not CONFIG_NSH_DISABLE_GET in one location (found by Kate). * apps/examples/ostest/prioinherit.c: Limit the number of test - threds to no more than 3 of each priority. Bad things happen + threads to no more than 3 of each priority. Bad things happen when the existing logic tried to created several hundred test treads! * apps/nshlib/nsh.h: Both CONFIG_LIBC_STRERROR and CONFIG_NSH_STRERROR @@ -341,7 +341,30 @@ * apps/netutils/webserver/httpd.c: Add support for Keep-alive connections (from Kate). * apps/NxWidget/Kconfig: This is a kludge. I created this NxWidgets - directory that ONLY contains Kconfig. NxWidgets does not like in + directory that ONLY contains Kconfig. NxWidgets does not live in either the nuttx/ or the apps/ source trees. This kludge makes it possible to configure NxWidgets/NxWM without too much trouble (with the tradeoff being a kind ugly structure and some maintenance issues). + * apps/examples/Make.defs: Missing support for apps/examples/watchdog. + * apps/NxWidgets/Kconfig: Add option to turn on the memory monitor + feature of the NxWidgets/NxWM unit tests. + +6.23 2012-xx-xx Gregory Nutt <gnutt@nuttx.org> + + * vsn: Moved all NSH commands from vsn/ to system/. Deleted the vsn/ + directory. + * Makefile: Change order of includes when CONFIG_NEWCONFIG=y. In + that case, namedapp must be included first so that the namedapp + context is established first. If the namedapp context is established + later, it will overwrite any existing namedapp_list.h and nameapp_proto.h + files. + * CONFIG_EXAMPLES_*: To make things consistent, changed all occurrences + of CONFIG_EXAMPLE_* to CONFIG_EXAMPLES_*. + * Kconfig: Fleshed out apps/examples/adc/Kconfig and apps/examples/wget/Kconfig. + There are still a LOT of empty, stub Kconfig files. + * Kconfig: Fleshed out apps/examples/buttons/Kconfig. There are still a LOT + of empty, stub Kconfig files. + * apps/netutils/webserver/httpd.c: Fix a bug that I introduced in + recent check-ins (Darcy Gong). + * apps/netutils/webclient/webclient.c: Fix another but that I introduced + when I was trying to add correct handling for loss of connection (Darcy Gong) diff --git a/apps/Kconfig b/apps/Kconfig index 5543ba72d..ea9bd2d31 100644 --- a/apps/Kconfig +++ b/apps/Kconfig @@ -34,7 +34,3 @@ endmenu menu "System NSH Add-Ons" source "$APPSDIR/system/Kconfig" endmenu - -menu "VSN board Add-Ons" -source "$APPSDIR/vsn/Kconfig" -endmenu diff --git a/apps/Makefile b/apps/Makefile index f087b7c33..19ad1c18b 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -46,10 +46,10 @@ APPDIR = ${shell pwd} # appears in this directory as .config) # SUBDIRS is the list of all directories containing Makefiles. It is used # only for cleaning. namedapp must always be the first in the list. This -# list can be extended by the .config file as well +# list can be extended by the .config file as well. CONFIGURED_APPS = -#SUBDIRS = examples graphics interpreters modbus namedapp nshlib netutils system vsn +#SUBDIRS = examples graphics interpreters modbus namedapp nshlib netutils system ALL_SUBDIRS = $(dir $(shell /usr/bin/find . -name Makefile)) SUBDIRS = namedapp/ $(filter-out ./ ./namedapp/ ./examples/,$(ALL_SUBDIRS)) @@ -73,15 +73,16 @@ SUBDIRS = namedapp/ $(filter-out ./ ./namedapp/ ./examples/,$(ALL_SUBDIRS)) ifeq ($(CONFIG_NUTTX_NEWCONFIG),y) +# namedapp/Make.defs must be included first + +-include namedapp/Make.defs -include examples/Make.defs -include graphics/Make.defs -include interpreters/Make.defs -include modbus/Make.defs --include namedapp/Make.defs -include netutils/Make.defs -include nshlib/Make.defs -include system/Make.defs --include vsn/Make.defs # INSTALLED_APPS is the list of currently available application directories. It # is the same as CONFIGURED_APPS, but filtered to exclude any non-existent diff --git a/apps/README.txt b/apps/README.txt index f9c9ececd..7a379254e 100644 --- a/apps/README.txt +++ b/apps/README.txt @@ -107,7 +107,7 @@ NuttX is configured. .config is included in the toplevel apps/Makefile. As a minimum, this configuration file must define files to add to the CONFIGURED_APPS list like: - CONFIGURED_APPS += examples/hello vsn/poweroff + CONFIGURED_APPS += examples/hello system/poweroff Named Start-Up main() function ------------------------------ diff --git a/apps/drivers/device/cdev.cpp b/apps/drivers/device/cdev.cpp index 6b8bf0c2d..d07d26e82 100644 --- a/apps/drivers/device/cdev.cpp +++ b/apps/drivers/device/cdev.cpp @@ -74,7 +74,7 @@ static int cdev_poll(struct file *filp, struct pollfd *fds, bool setup); * Note that we use the GNU extension syntax here because we don't get designated * initialisers in gcc 4.6. */ -static const struct file_operations cdev_fops = { +const struct file_operations CDev::fops = { open : cdev_open, close : cdev_close, read : cdev_read, @@ -118,7 +118,7 @@ CDev::init() goto out; // now register the driver - ret = register_driver(_devname, &cdev_fops, 0666, (void *)this); + ret = register_driver(_devname, &fops, 0666, (void *)this); if (ret != OK) goto out; diff --git a/apps/drivers/device/device.h b/apps/drivers/device/device.h index 98dbf8bfb..9af678465 100644 --- a/apps/drivers/device/device.h +++ b/apps/drivers/device/device.h @@ -287,6 +287,12 @@ public: protected: /** + * Pointer to the default cdev file operations table; useful for + * registering clone devices etc. + */ + static const struct file_operations fops; + + /** * Check the current state of the device for poll events from the * perspective of the file. * diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs index a6e0ae88e..d03b976d2 100644 --- a/apps/examples/Make.defs +++ b/apps/examples/Make.defs @@ -58,7 +58,7 @@ ifeq ($(CONFIG_EXAMPLES_DHCPD),y) CONFIGURED_APPS += examples/dhcpd endif -ifeq ($(CONFIG_EXAMPLE_DISCOVER),y) +ifeq ($(CONFIG_EXAMPLES_DISCOVER),y) CONFIGURED_APPS += examples/discover endif @@ -218,6 +218,10 @@ ifeq ($(CONFIG_EXAMPLES_USBTERM),y) CONFIGURED_APPS += examples/usbterm endif +ifeq ($(CONFIG_EXAMPLES_WATCHDOG),y) +CONFIGURED_APPS += examples/watchdog +endif + ifeq ($(CONFIG_EXAMPLES_WGET),y) CONFIGURED_APPS += examples/wget endif diff --git a/apps/examples/README.txt b/apps/examples/README.txt index 12d6d3892..763427e32 100644 --- a/apps/examples/README.txt +++ b/apps/examples/README.txt @@ -60,20 +60,20 @@ 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_BUTTONS - Must be defined for button support + CONFIG_EXAMPLES_BUTTONS_MIN - Lowest button number (MIN=0) + CONFIG_EXAMPLES_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) + CONFIG_ARCH_IRQBUTTONS - Must be defined for interrupting button support + CONFIG_EXAMPLES_IRQBUTTONS_MIN - Lowest interrupting button number (MIN=0) + CONFIG_EXAMPLES_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, + CONFIG_EXAMPLES_BUTTONS_NAME0, CONFIG_EXAMPLES_BUTTONS_NAME1, + CONFIG_EXAMPLES_BUTTONS_NAME2, CONFIG_EXAMPLES_BUTTONS_NAME3, + CONFIG_EXAMPLES_BUTTONS_NAME4, CONFIG_EXAMPLES_BUTTONS_NAME5, + CONFIG_EXAMPLES_BUTTONS_NAME6, CONFIG_EXAMPLES_BUTTONS_NAME7, Additional architecture-/board- specific configuration settings may also be required. @@ -260,10 +260,10 @@ examples/dhcpd 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 + CONFIG_EXAMPLES_DHCPD_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLES_DHCPD_IPADDR - Target IP address + CONFIG_EXAMPLES_DHCPD_DRIPADDR - Default router IP addess + CONFIG_EXAMPLES_DHCPD_NETMASK - Network mask See also CONFIG_NETUTILS_DHCPD_* settings described elsewhere and used in netutils/dhcpd/dhcpd.c. These settings are required @@ -291,11 +291,11 @@ examples/discover NuttX configuration settings: - CONFIG_EXAMPLE_DISCOVER_DHCPC - DHCP Client - CONFIG_EXAMPLE_DISCOVER_NOMAC - Use canned MAC address - CONFIG_EXAMPLE_DISCOVER_IPADDR - Target IP address - CONFIG_EXAMPLE_DISCOVER_DRIPADDR - Router IP address - CONFIG_EXAMPLE_DISCOVER_NETMASK - Network Mask + CONFIG_EXAMPLES_DISCOVER_DHCPC - DHCP Client + CONFIG_EXAMPLES_DISCOVER_NOMAC - Use canned MAC address + CONFIG_EXAMPLES_DISCOVER_IPADDR - Target IP address + CONFIG_EXAMPLES_DISCOVER_DRIPADDR - Router IP address + CONFIG_EXAMPLES_DISCOVER_NETMASK - Network Mask examples/ftpc ^^^^^^^^^^^^^ @@ -367,12 +367,12 @@ examples/ftpd 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 + CONFIG_EXAMPLES_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 + CONFIG_EXAMPLES_FTPD_IPADDR - The target IP address. Default 10.0.0.2 + CONFIG_EXAMPLES_FTPD_DRIPADDR - The default router address. Default 10.0.0.1 - CONFIG_EXAMPLE_FTPD_NETMASK - The network mask. Default: 255.255.255.0 + CONFIG_EXAMPLES_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: @@ -465,15 +465,15 @@ examples/igmp does not do much of value -- Much more is needed in order to verify the IGMP features! - * CONFIG_EXAMPLE_IGMP_NOMAC + * CONFIG_EXAMPLES_IGMP_NOMAC Set if the hardware has no MAC address; one will be assigned - * CONFIG_EXAMPLE_IGMP_IPADDR + * CONFIG_EXAMPLES_IGMP_IPADDR Target board IP address - * CONFIG_EXAMPLE_IGMP_DRIPADDR + * CONFIG_EXAMPLES_IGMP_DRIPADDR Default router address - * CONFIG_EXAMPLE_IGMP_NETMASK + * CONFIG_EXAMPLES_IGMP_NETMASK Network mask - * CONFIG_EXAMPLE_IGMP_GRPADDR + * CONFIG_EXAMPLES_IGMP_GRPADDR Multicast group address Applications using this example will need to provide an appconfig @@ -1023,10 +1023,10 @@ examples/poll 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 + CONFIG_EXAMPLES_POLL_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLES_POLL_IPADDR - Target IP address + CONFIG_EXAMPLES_POLL_DRIPADDR - Default router IP addess + CONFIG_EXAMPLES_POLL_NETMASK - Network mask In order to for select to work with incoming connections, you must also select: @@ -1163,14 +1163,14 @@ examples/sendmail 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" + CONFIG_EXAMPLES_SENDMAIL_NOMAC - May be defined to use software assigned MAC (optional) + CONFIG_EXAMPLES_SENDMAIL_IPADDR - Target IP address (required) + CONFIG_EXAMPLES_SENDMAIL_DRIPADDR - Default router IP addess (required) + CONFIG_EXAMPLES_SENDMAILT_NETMASK - Network mask (required) + CONFIG_EXAMPLES_SENDMAIL_RECIPIENT - The recipient of the email (required) + CONFIG_EXAMPLES_SENDMAIL_SENDER - Optional. Default: "nuttx-testing@example.com" + CONFIG_EXAMPLES_SENDMAIL_SUBJECT - Optional. Default: "Testing SMTP from NuttX" + CONFIG_EXAMPLES_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. @@ -1213,12 +1213,12 @@ examples/telnetd 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 + CONFIG_EXAMPLES_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 + CONFIG_EXAMPLES_TELNETD_IPADDR - The target IP address. Default 10.0.0.2 + CONFIG_EXAMPLES_TELNETD_DRIPADDR - The default router address. Default 10.0.0.1 - CONFIG_EXAMPLE_TELNETD_NETMASK - The network mask. Default: 255.255.255.0 + CONFIG_EXAMPLES_TELNETD_NETMASK - The network mask. Default: 255.255.255.0 The appconfig file (apps/.config) should include: @@ -1240,9 +1240,9 @@ examples/thttpd 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 + CONFIG_EXAMPLES_THTTPD_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLES_THTTPD_DRIPADDR - Default router IP addess + CONFIG_EXAMPLES_THTTPD_NETMASK - Network mask Applications using this example will need to provide an appconfig file in the configuration directory with instruction to build applications @@ -1335,11 +1335,11 @@ 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 + CONFIG_EXAMPLES_UIP_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLES_UIP_IPADDR - Target IP address + CONFIG_EXAMPLES_UIP_DRIPADDR - Default router IP addess + CONFIG_EXAMPLES_UIP_NETMASK - Network mask + CONFIG_EXAMPLES_UIP_DHCPC - Select to get IP address via DHCP If you use DHCPC, then some special configuration network options are required. These include: @@ -1637,11 +1637,11 @@ 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 + CONFIG_EXAMPLES_WGET_URL - The URL of the file to get + CONFIG_EXAMPLES_WGET_NOMAC - (May be defined to use software assigned MAC) + CONFIG_EXAMPLES_WGET_IPADDR - Target IP address + CONFIG_EXAMPLES_WGET_DRIPADDR - Default router IP addess + CONFIG_EXAMPLES_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): diff --git a/apps/examples/adc/Kconfig b/apps/examples/adc/Kconfig index b6dca047c..85c875deb 100644 --- a/apps/examples/adc/Kconfig +++ b/apps/examples/adc/Kconfig @@ -6,8 +6,32 @@ config EXAMPLES_ADC bool "ADC example" default n + depends on ADC ---help--- Enable the ADC example if EXAMPLES_ADC + +config EXAMPLES_ADC_DEVPATH + string "ADC device path" + default "/dev/adc0" + ---help--- + The default path to the ADC device. Default: /dev/adc0 + +config EXAMPLES_ADC_NSAMPLES + int "Number of Sample Groups" + default 0 + depends on !NSH_BUILTIN_APPS + ---help--- + If 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: 0 (samples + are collected indefinitely). + +config EXAMPLES_ADC_GROUPSIZE + int "Number of Samples per Group" + default 4 + ---help--- + The number of samples to read at once. Default: 4 + endif diff --git a/apps/examples/adc/adc_main.c b/apps/examples/adc/adc_main.c index 4797265db..404fba8c1 100644 --- a/apps/examples/adc/adc_main.c +++ b/apps/examples/adc/adc_main.c @@ -57,6 +57,14 @@ * Pre-processor Definitions ****************************************************************************/ +/* Use CONFIG_EXAMPLES_ADC_NSAMPLES == 0 to mean to collect samples + * indefinitely. + */ + +#ifndef CONFIG_EXAMPLES_ADC_NSAMPLES +# define CONFIG_EXAMPLES_ADC_NSAMPLES 0 +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -249,7 +257,7 @@ int adc_main(int argc, char *argv[]) adc_devpath(&g_adcstate, CONFIG_EXAMPLES_ADC_DEVPATH); -#ifdef CONFIG_EXAMPLES_ADC_NSAMPLES +#if CONFIG_EXAMPLES_ADC_NSAMPLES > 0 g_adcstate.count = CONFIG_EXAMPLES_ADC_NSAMPLES; #else g_adcstate.count = 1; @@ -267,7 +275,7 @@ int adc_main(int argc, char *argv[]) * samples that we collect before returning. Otherwise, we never return */ -#if defined(CONFIG_NSH_BUILTIN_APPS) || defined(CONFIG_EXAMPLES_ADC_NSAMPLES) +#if defined(CONFIG_NSH_BUILTIN_APPS) || CONFIG_EXAMPLES_ADC_NSAMPLES > 0 message("adc_main: g_adcstate.count: %d\n", g_adcstate.count); #endif @@ -290,7 +298,7 @@ int adc_main(int argc, char *argv[]) #if defined(CONFIG_NSH_BUILTIN_APPS) for (; g_adcstate.count > 0; g_adcstate.count--) -#elif defined(CONFIG_EXAMPLES_ADC_NSAMPLES) +#elif CONFIG_EXAMPLES_ADC_NSAMPLES > 0 for (g_adcstate.count = 0; g_adcstate.count < CONFIG_EXAMPLES_ADC_NSAMPLES; g_adcstate.count++) #else for (;;) diff --git a/apps/examples/buttons/Kconfig b/apps/examples/buttons/Kconfig index 9c34b37bc..d145867fc 100644 --- a/apps/examples/buttons/Kconfig +++ b/apps/examples/buttons/Kconfig @@ -7,7 +7,57 @@ config EXAMPLES_BUTTONS bool "Buttons example" default n ---help--- - Enable the buttons example + Enable the buttons example. May require ARCH_BUTTONS on some boards. if EXAMPLES_BUTTONS +config EXAMPLES_BUTTONS_MIN +int "Lowest Button Number" +default 0 + +config EXAMPLES_BUTTONS_MAX +int "Highest Button Number" +default 7 + +if ARCH_IRQBUTTONS +config EXAMPLES_IRQBUTTONS_MIN +int "Lowest Interrupting Button Number" +default 0 + +config EXAMPLES_IRQBUTTONS_MAX +int "Highest Interrupting Button Number" +default 7 + +config EXAMPLES_BUTTONS_NAME0 +string "Button 0 Name" +default "Button 0" + +config EXAMPLES_BUTTONS_NAME1 +string "Button 1 Name" +default "Button 1" + +config EXAMPLES_BUTTONS_NAME2 +string "Button 2 Name" +default "Button 2" + +config EXAMPLES_BUTTONS_NAME3 +string "Button 3 Name" +default "Button 3" + +config EXAMPLES_BUTTONS_NAME4 +string "Button 4 Name" +default "Button 4" + +config EXAMPLES_BUTTONS_NAME5 +string "Button 5 Name" +default "Button 5" + +config EXAMPLES_BUTTONS_NAME6 +string "Button 6 Name" +default "Button 6" + +config EXAMPLES_BUTTONS_NAME7 +string "Button 7 Name" +default "Button 7" + +endif endif diff --git a/apps/examples/buttons/buttons_main.c b/apps/examples/buttons/buttons_main.c index a3f6449d4..5f25c1ef1 100644 --- a/apps/examples/buttons/buttons_main.c +++ b/apps/examples/buttons/buttons_main.c @@ -61,60 +61,60 @@ # error "CONFIG_ARCH_BUTTONS is not defined in the configuration" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME0 -# define CONFIG_EXAMPLE_BUTTONS_NAME0 "BUTTON0" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME0 +# define CONFIG_EXAMPLES_BUTTONS_NAME0 "BUTTON0" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME1 -# define CONFIG_EXAMPLE_BUTTONS_NAME1 "BUTTON1" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME1 +# define CONFIG_EXAMPLES_BUTTONS_NAME1 "BUTTON1" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME2 -# define CONFIG_EXAMPLE_BUTTONS_NAME2 "BUTTON2" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME2 +# define CONFIG_EXAMPLES_BUTTONS_NAME2 "BUTTON2" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME3 -# define CONFIG_EXAMPLE_BUTTONS_NAME3 "BUTTON3" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME3 +# define CONFIG_EXAMPLES_BUTTONS_NAME3 "BUTTON3" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME4 -# define CONFIG_EXAMPLE_BUTTONS_NAME4 "BUTTON4" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME4 +# define CONFIG_EXAMPLES_BUTTONS_NAME4 "BUTTON4" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME5 -# define CONFIG_EXAMPLE_BUTTONS_NAME5 "BUTTON5" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME5 +# define CONFIG_EXAMPLES_BUTTONS_NAME5 "BUTTON5" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME6 -# define CONFIG_EXAMPLE_BUTTONS_NAME6 "BUTTON6" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME6 +# define CONFIG_EXAMPLES_BUTTONS_NAME6 "BUTTON6" #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_NAME7 -# define CONFIG_EXAMPLE_BUTTONS_NAME7 "BUTTON7" +#ifndef CONFIG_EXAMPLES_BUTTONS_NAME7 +# define CONFIG_EXAMPLES_BUTTONS_NAME7 "BUTTON7" #endif #define BUTTON_MIN 0 #define BUTTON_MAX 7 -#ifndef CONFIG_EXAMPLE_BUTTONS_MIN -# define CONFIG_EXAMPLE_BUTTONS_MIN BUTTON_MIN +#ifndef CONFIG_EXAMPLES_BUTTONS_MIN +# define CONFIG_EXAMPLES_BUTTONS_MIN BUTTON_MIN #endif -#ifndef CONFIG_EXAMPLE_BUTTONS_MAX -# define CONFIG_EXAMPLE_BUTTONS_MAX BUTTON_MAX +#ifndef CONFIG_EXAMPLES_BUTTONS_MAX +# define CONFIG_EXAMPLES_BUTTONS_MAX BUTTON_MAX #endif -#if CONFIG_EXAMPLE_BUTTONS_MIN > CONFIG_EXAMPLE_BUTTONS_MAX -# error "CONFIG_EXAMPLE_BUTTONS_MIN > CONFIG_EXAMPLE_BUTTONS_MAX" +#if CONFIG_EXAMPLES_BUTTONS_MIN > CONFIG_EXAMPLES_BUTTONS_MAX +# error "CONFIG_EXAMPLES_BUTTONS_MIN > CONFIG_EXAMPLES_BUTTONS_MAX" #endif -#if CONFIG_EXAMPLE_BUTTONS_MAX > 7 -# error "CONFIG_EXAMPLE_BUTTONS_MAX > 7" +#if CONFIG_EXAMPLES_BUTTONS_MAX > 7 +# error "CONFIG_EXAMPLES_BUTTONS_MAX > 7" #endif -#ifndef CONFIG_EXAMPLE_IRQBUTTONS_MIN -# define CONFIG_EXAMPLE_IRQBUTTONS_MIN CONFIG_EXAMPLE_BUTTONS_MIN +#ifndef CONFIG_EXAMPLES_IRQBUTTONS_MIN +# define CONFIG_EXAMPLES_IRQBUTTONS_MIN CONFIG_EXAMPLES_BUTTONS_MIN #endif -#ifndef CONFIG_EXAMPLE_IRQBUTTONS_MAX -# define CONFIG_EXAMPLE_IRQBUTTONS_MAX CONFIG_EXAMPLE_BUTTONS_MAX +#ifndef CONFIG_EXAMPLES_IRQBUTTONS_MAX +# define CONFIG_EXAMPLES_IRQBUTTONS_MAX CONFIG_EXAMPLES_BUTTONS_MAX #endif -#if CONFIG_EXAMPLE_IRQBUTTONS_MIN > CONFIG_EXAMPLE_IRQBUTTONS_MAX -# error "CONFIG_EXAMPLE_IRQBUTTONS_MIN > CONFIG_EXAMPLE_IRQBUTTONS_MAX" +#if CONFIG_EXAMPLES_IRQBUTTONS_MIN > CONFIG_EXAMPLES_IRQBUTTONS_MAX +# error "CONFIG_EXAMPLES_IRQBUTTONS_MIN > CONFIG_EXAMPLES_IRQBUTTONS_MAX" #endif -#if CONFIG_EXAMPLE_IRQBUTTONS_MAX > 7 -# error "CONFIG_EXAMPLE_IRQBUTTONS_MAX > 7" +#if CONFIG_EXAMPLES_IRQBUTTONS_MAX > 7 +# error "CONFIG_EXAMPLES_IRQBUTTONS_MAX > 7" #endif #ifndef MIN @@ -124,8 +124,8 @@ # 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 MIN_BUTTON MIN(CONFIG_EXAMPLES_BUTTONS_MIN, CONFIG_EXAMPLES_IRQBUTTONS_MIN) +#define MAX_BUTTON MAX(CONFIG_EXAMPLES_BUTTONS_MAX, CONFIG_EXAMPLES_IRQBUTTONS_MAX) #define NUM_BUTTONS (MAX_BUTTON - MIN_BUTTON + 1) #define BUTTON_INDEX(b) ((b)-MIN_BUTTON) @@ -187,7 +187,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = { #if MIN_BUTTON < 1 { - CONFIG_EXAMPLE_BUTTONS_NAME0, + CONFIG_EXAMPLES_BUTTONS_NAME0, #ifdef CONFIG_ARCH_IRQBUTTONS button0_handler #endif @@ -195,7 +195,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = #endif #if MIN_BUTTON < 2 && MAX_BUTTON > 0 { - CONFIG_EXAMPLE_BUTTONS_NAME1, + CONFIG_EXAMPLES_BUTTONS_NAME1, #ifdef CONFIG_ARCH_IRQBUTTONS button1_handler #endif @@ -203,7 +203,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = #endif #if MIN_BUTTON < 3 && MAX_BUTTON > 1 { - CONFIG_EXAMPLE_BUTTONS_NAME2, + CONFIG_EXAMPLES_BUTTONS_NAME2, #ifdef CONFIG_ARCH_IRQBUTTONS button2_handler #endif @@ -211,7 +211,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = #endif #if MIN_BUTTON < 4 && MAX_BUTTON > 2 { - CONFIG_EXAMPLE_BUTTONS_NAME3, + CONFIG_EXAMPLES_BUTTONS_NAME3, #ifdef CONFIG_ARCH_IRQBUTTONS button3_handler #endif @@ -219,7 +219,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = #endif #if MIN_BUTTON < 5 && MAX_BUTTON > 3 { - CONFIG_EXAMPLE_BUTTONS_NAME4, + CONFIG_EXAMPLES_BUTTONS_NAME4, #ifdef CONFIG_ARCH_IRQBUTTONS button4_handler #endif @@ -227,7 +227,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = #endif #if MIN_BUTTON < 6 && MAX_BUTTON > 4 { - CONFIG_EXAMPLE_BUTTONS_NAME5, + CONFIG_EXAMPLES_BUTTONS_NAME5, #ifdef CONFIG_ARCH_IRQBUTTONS button5_handler #endif @@ -235,7 +235,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = #endif #if MIN_BUTTON < 7 && MAX_BUTTON > 5 { - CONFIG_EXAMPLE_BUTTONS_NAME6, + CONFIG_EXAMPLES_BUTTONS_NAME6, #ifdef CONFIG_ARCH_IRQBUTTONS button6_handler #endif @@ -243,7 +243,7 @@ static const struct button_info_s g_buttoninfo[NUM_BUTTONS] = #endif #if MAX_BUTTON > 6 { - CONFIG_EXAMPLE_BUTTONS_NAME7, + CONFIG_EXAMPLES_BUTTONS_NAME7, #ifdef CONFIG_ARCH_IRQBUTTONS button7_handler #endif @@ -419,7 +419,7 @@ int buttons_main(int argc, char *argv[]) /* Register to recieve button interrupts */ #ifdef CONFIG_ARCH_IRQBUTTONS - for (i = CONFIG_EXAMPLE_IRQBUTTONS_MIN; i <= CONFIG_EXAMPLE_IRQBUTTONS_MAX; i++) + for (i = CONFIG_EXAMPLES_IRQBUTTONS_MIN; i <= CONFIG_EXAMPLES_IRQBUTTONS_MAX; i++) { xcpt_t oldhandler = up_irqbutton(i, g_buttoninfo[BUTTON_INDEX(i)].handler); @@ -488,7 +488,7 @@ int buttons_main(int argc, char *argv[]) /* 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++) + for (i = CONFIG_EXAMPLES_IRQBUTTONS_MIN; i <= CONFIG_EXAMPLES_IRQBUTTONS_MAX; i++) { (void)up_irqbutton(i, NULL); } diff --git a/apps/examples/poll/net_listener.c b/apps/examples/poll/net_listener.c index 81ad7cdcc..2be98673c 100644 --- a/apps/examples/poll/net_listener.c +++ b/apps/examples/poll/net_listener.c @@ -290,14 +290,14 @@ static inline bool net_mksocket(struct net_listener_s *nls) static void net_configure(void) { struct in_addr addr; -#if defined(CONFIG_EXAMPLE_POLL_NOMAC) +#if defined(CONFIG_EXAMPLES_POLL_NOMAC) uint8_t mac[IFHWADDRLEN]; #endif /* Configure uIP */ /* Many embedded network interfaces must have a software assigned MAC */ -#ifdef CONFIG_EXAMPLE_POLL_NOMAC +#ifdef CONFIG_EXAMPLES_POLL_NOMAC mac[0] = 0x00; mac[1] = 0xe0; mac[2] = 0xde; @@ -309,17 +309,17 @@ static void net_configure(void) /* Set up our host address */ - addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + addr.s_addr = HTONL(CONFIG_EXAMPLES_POLL_IPADDR); uip_sethostaddr("eth0", &addr); /* Set up the default router address */ - addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + addr.s_addr = HTONL(CONFIG_EXAMPLES_POLL_DRIPADDR); uip_setdraddr("eth0", &addr); /* Setup the subnet mask */ - addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + addr.s_addr = HTONL(CONFIG_EXAMPLES_POLL_NETMASK); uip_setnetmask("eth0", &addr); } diff --git a/apps/examples/poll/net_reader.c b/apps/examples/poll/net_reader.c index 8a13618c3..2f23bab3c 100644 --- a/apps/examples/poll/net_reader.c +++ b/apps/examples/poll/net_reader.c @@ -83,14 +83,14 @@ static void net_configure(void) { struct in_addr addr; -#if defined(CONFIG_EXAMPLE_POLL_NOMAC) +#if defined(CONFIG_EXAMPLES_POLL_NOMAC) uint8_t mac[IFHWADDRLEN]; #endif /* Configure uIP */ /* Many embedded network interfaces must have a software assigned MAC */ -#ifdef CONFIG_EXAMPLE_POLL_NOMAC +#ifdef CONFIG_EXAMPLES_POLL_NOMAC mac[0] = 0x00; mac[1] = 0xe0; mac[2] = 0xde; @@ -102,17 +102,17 @@ static void net_configure(void) /* Set up our host address */ - addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR); + addr.s_addr = HTONL(CONFIG_EXAMPLES_POLL_IPADDR); uip_sethostaddr("eth0", &addr); /* Set up the default router address */ - addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR); + addr.s_addr = HTONL(CONFIG_EXAMPLES_POLL_DRIPADDR); uip_setdraddr("eth0", &addr); /* Setup the subnet mask */ - addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK); + addr.s_addr = HTONL(CONFIG_EXAMPLES_POLL_NETMASK); uip_setnetmask("eth0", &addr); } diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig index c0f7d6a92..d12a32973 100644 --- a/apps/nshlib/Kconfig +++ b/apps/nshlib/Kconfig @@ -291,19 +291,18 @@ config NSH_CONSOLE console front-end is selected (/dev/console). Normally, the serial console device is a UART and RS-232 - interface. However, if CONFIG_USBDEV is defined, then a USB + interface. However, if USBDEV is defined, then a USB serial device may, instead, be used if the one of the following are defined: - CONFIG_PL2303 and CONFIG_PL2303_CONSOLE - Sets up the - Prolifics PL2303 emulation as a console device at /dev/console. + PL2303 and PL2303_CONSOLE - Set up the Prolifics PL2303 + emulation as a console device at /dev/console. - CONFIG_CDCACM and CONFIG_CDCACM_CONSOLE - Sets up the - CDC/ACM serial device as a console device at dev/console. + CDCACM and CDCACM_CONSOLE - Set up the CDC/ACM serial + device as a console device at dev/console. - CONFIG_NSH_USBCONSOLE and CONFIG_NSH_USBCONDEV - Sets up the - some other USB serial device as the NSH console (not necessarily - dev/console). + NSH_USBCONSOLE and NSH_USBCONDEV - Sets up some other USB + serial device as the NSH console (not necessarily dev/console). config NSH_USBCONSOLE bool "Use a USB console" @@ -311,20 +310,20 @@ config NSH_USBCONSOLE depends on NSH_CONSOLE && USBDEV ---help--- If defined, then the an arbitrary USB device may be used - to as the NSH console. In this case, CONFIG_NSH_USBCONDEV - must be defined to indicate which USB device to use as - the console. + to as the NSH console. In this case, NSH_USBCONDEV must + be defined to indicate which USB device to use as the + console. config NSH_USBCONDEV string "USB console device" default "/dev/ttyACM0" depends on NSH_USBCONSOLE ---help--- - If CONFIG_NSH_USBCONSOLE is set to 'y', then CONFIG_NSH_USBCONDEV - must also be set to select the USB device used to support - the NSH console. This should be set to the quoted name of a + If NSH_USBCONSOLE is set to 'y', then NSH_USBCONDEV must + also be set to select the USB device used to support the + NSH console. This should be set to the quoted name of a readable/write-able USB driver such as: - CONFIG_NSH_USBCONDEV="/dev/ttyACM0". + NSH_USBCONDEV="/dev/ttyACM0". config UBSDEV_MINOR int "USB console device minor number" @@ -448,6 +447,35 @@ config NSH_IOBUFFER_SIZE ---help--- Determines the size of the I/O buffer to use for sending/ receiving TELNET commands/reponses. Default: 512 + +config NSH_TELNET_LOGIN + bool "Telnet Login" + default n + ---help--- + If defined, then the Telnet user will be required to provide a + username and password to start the NSH shell. + +if NSH_TELNET_LOGIN + +config NSH_TELNET_USERNAME + string "Login Username" + default "admin" + ---help--- + Login user name. Default: "admin" + +config NSH_TELNET_PASSWORD + string "Login Password" + default "nuttx" + ---help--- + Login password: Default: "nuttx" + +config NSH_TELNET_FAILCOUNT + int "Login Retry Count" + default 3 + ---help--- + Number of login retry attempts. + +endif endif config NSH_DHCPC diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h index e6dd2683b..7188477ce 100644 --- a/apps/nshlib/nsh.h +++ b/apps/nshlib/nsh.h @@ -164,10 +164,19 @@ * Default: SCHED_PRIORITY_DEFAULT * CONFIG_NSH_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the * Telnet daemon. Default: 2048 - * CONFIG_NSH_TELNETD_CLIENTPRIO- Priority of the Telnet client. + * CONFIG_NSH_TELNETD_CLIENTPRIO - Priority of the Telnet client. * Default: SCHED_PRIORITY_DEFAULT * CONFIG_NSH_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the * Telnet client. Default: 2048 + * CONFIG_NSH_TELNET_LOGIN - Support a simple Telnet login. + * + * If CONFIG_NSH_TELNET_LOGIN is defined, then these additional + * options may be specified: + * + * CONFIG_NSH_TELNET_USERNAME - Login user name. Default: "admin" + * CONFIG_NSH_TELNET_PASSWORD - Login password: Default: "nuttx" + * CONFIG_NSH_TELNET_FAILCOUNT - Number of login retry attempts. + * Default 3. */ #ifndef CONFIG_NSH_TELNETD_PORT @@ -190,6 +199,22 @@ # define CONFIG_NSH_TELNETD_CLIENTSTACKSIZE 2048 #endif +#ifdef CONFIG_NSH_TELNET_LOGIN + +# ifndef CONFIG_NSH_TELNET_USERNAME +# define CONFIG_NSH_TELNET_USERNAME "admin" +# endif + +# ifndef CONFIG_NSH_TELNET_PASSWORD +# define CONFIG_NSH_TELNET_PASSWORD "nuttx" +# endif + +# ifndef CONFIG_NSH_TELNET_FAILCOUNT +# define CONFIG_NSH_TELNET_FAILCOUNT 3 +# endif + +#endif /* CONFIG_NSH_TELNET_LOGIN */ + /* Verify support for ROMFS /etc directory support options */ #ifdef CONFIG_NSH_ROMFSETC @@ -364,6 +389,14 @@ typedef int (*cmd_t)(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); ****************************************************************************/ extern const char g_nshgreeting[]; +#if defined(CONFIG_NSH_TELNET_LOGIN) && defined(CONFIG_NSH_TELNET) +extern const char g_telnetgreeting[]; +extern const char g_userprompt[]; +extern const char g_passwordprompt[]; +extern const char g_loginsuccess[]; +extern const char g_badcredentials[]; +extern const char g_loginfailure[]; +#endif extern const char g_nshprompt[]; extern const char g_nshsyntax[]; extern const char g_fmtargrequired[]; diff --git a/apps/nshlib/nsh_console.c b/apps/nshlib/nsh_console.c index b066e71f5..1b8f5f6ac 100644 --- a/apps/nshlib/nsh_console.c +++ b/apps/nshlib/nsh_console.c @@ -75,12 +75,17 @@ struct serialsave_s static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl); #endif static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl); -static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes); -static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...); +static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, + FAR const void *buffer, size_t nbytes); +static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, + FAR const char *fmt, ...); static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl); -static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save); -static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save); -static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus); +static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, + FAR uint8_t *save); +static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, + FAR uint8_t *save); +static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus) + noreturn_function; /**************************************************************************** * Private Data diff --git a/apps/nshlib/nsh_console.h b/apps/nshlib/nsh_console.h index 53e8c7897..4dc2938cb 100644 --- a/apps/nshlib/nsh_console.h +++ b/apps/nshlib/nsh_console.h @@ -109,7 +109,7 @@ struct nsh_vtbl_s FAR char *(*linebuffer)(FAR struct nsh_vtbl_s *vtbl); void (*redirect)(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save); void (*undirect)(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save); - void (*exit)(FAR struct nsh_vtbl_s *vtbl, int exitstatus); + void (*exit)(FAR struct nsh_vtbl_s *vtbl, int exitstatus) noreturn_function; /* Parser state data */ diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c index ba597a062..df2f7c3e3 100644 --- a/apps/nshlib/nsh_parse.c +++ b/apps/nshlib/nsh_parse.c @@ -395,6 +395,17 @@ const char g_nshgreeting[] = "\nNuttShell (NSH) NuttX-" CONFIG_VERSION_STR const char g_nshgreeting[] = "\nNuttShell (NSH)\n"; #endif +/* Telnet login prompts */ + +#if defined(CONFIG_NSH_TELNET_LOGIN) && defined(CONFIG_NSH_TELNET) +const char g_telnetgreeting[] = "\nWelcome to NuttShell(NSH) Telnet Server...\n"; +const char g_userprompt[] = "login: "; +const char g_passwordprompt[] = "password: "; +const char g_loginsuccess[] = "\nUser Logged-in!\n"; +const char g_badcredentials[] = "\nInvalid username or password\n"; +const char g_loginfailure[] = "Login failed!\n"; +#endif + /* The NSH prompt */ const char g_nshprompt[] = "nsh> "; diff --git a/apps/nshlib/nsh_telnetd.c b/apps/nshlib/nsh_telnetd.c index 0117aad04..478935d7f 100644 --- a/apps/nshlib/nsh_telnetd.c +++ b/apps/nshlib/nsh_telnetd.c @@ -43,6 +43,7 @@ #include <unistd.h> #include <assert.h> #include <debug.h> +#include <string.h> #include <apps/netutils/telnetd.h> @@ -55,6 +56,18 @@ * Pre-processor Definitions ****************************************************************************/ +#ifdef CONFIG_NSH_TELNET_LOGIN + +# define TELNET_IAC 255 +# define TELNET_WILL 251 +# define TELNET_WONT 252 +# define TELNET_DO 253 +# define TELNET_DONT 254 +# define TELNET_USE_ECHO 1 +# define TELNET_NOTUSE_ECHO 0 + +#endif /* CONFIG_NSH_TELNET_LOGIN */ + /**************************************************************************** * Private Types ****************************************************************************/ @@ -76,6 +89,91 @@ ****************************************************************************/ /**************************************************************************** + * Name: nsh_telnetecho + ****************************************************************************/ + +#ifdef CONFIG_NSH_TELNET_LOGIN +void nsh_telnetecho(struct console_stdio_s *pstate, uint8_t is_use) +{ + uint8_t optbuf[4]; + optbuf[0] = TELNET_IAC; + optbuf[1] = (is_use == TELNET_USE_ECHO) ? TELNET_WILL : TELNET_DO; + optbuf[2] = 1; + optbuf[3] = 0; + fputs((char *)optbuf, pstate->cn_outstream); + fflush(pstate->cn_outstream); +} +#endif + +/**************************************************************************** + * Name: nsh_telnetlogin + ****************************************************************************/ + +#ifdef CONFIG_NSH_TELNET_LOGIN +int nsh_telnetlogin(struct console_stdio_s *pstate) +{ + char username[16]; + char password[16]; + uint8_t i; + + /* Present the NSH Telnet greeting */ + + fputs(g_telnetgreeting, pstate->cn_outstream); + fflush(pstate->cn_outstream); + + /* Loop for the configured number of retries */ + + for(i = 0; i < CONFIG_NSH_TELNET_FAILCOUNT; i++) + { + /* Ask for the login username */ + + fputs(g_userprompt, pstate->cn_outstream); + fflush(pstate->cn_outstream); + if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN, INSTREAM(pstate)) != NULL) + { + strcpy(username, pstate->cn_line); + username[strlen(pstate->cn_line) - 1] = 0; + } + + /* Ask for the login password */ + + fputs(g_passwordprompt, pstate->cn_outstream); + fflush(pstate->cn_outstream); + nsh_telnetecho(pstate, TELNET_NOTUSE_ECHO); + if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN, INSTREAM(pstate)) != NULL) + { + /* Verify the username and password */ + + strcpy(password,pstate->cn_line); + password[strlen(pstate->cn_line) - 1] = 0; + + if (strcmp(password, CONFIG_NSH_TELNET_PASSWORD) == 0 && + strcmp(username, CONFIG_NSH_TELNET_USERNAME) == 0) + { + fputs(g_loginsuccess, pstate->cn_outstream); + fflush(pstate->cn_outstream); + nsh_telnetecho(pstate, TELNET_USE_ECHO); + return OK; + } + else + { + fputs(g_badcredentials, pstate->cn_outstream); + fflush(pstate->cn_outstream); + } + } + + nsh_telnetecho(pstate, TELNET_USE_ECHO); + } + + /* Too many failed login attempts */ + + fputs(g_loginfailure, pstate->cn_outstream); + fflush(pstate->cn_outstream); + return -1; +} +#endif /* CONFIG_NSH_TELNET_LOGIN */ + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -90,7 +188,17 @@ int nsh_telnetmain(int argc, char *argv[]) dbg("Session [%d] Started\n", getpid()); - /* Present a greeting */ + /* Login User and Password Check */ + +#ifdef CONFIG_NSH_TELNET_LOGIN + if (nsh_telnetlogin(pstate) != OK) + { + nsh_exit(&pstate->cn_vtbl, 1); + return -1; /* nsh_exit does not return */ + } +#endif /* CONFIG_NSH_TELNET_LOGIN */ + + /* Present the NSH greeting */ fputs(g_nshgreeting, pstate->cn_outstream); fflush(pstate->cn_outstream); diff --git a/apps/px4/fmu/fmu.cpp b/apps/px4/fmu/fmu.cpp index 18f27d49e..6d990c46b 100644 --- a/apps/px4/fmu/fmu.cpp +++ b/apps/px4/fmu/fmu.cpp @@ -79,7 +79,7 @@ public: FMUServo(Mode mode, int update_rate); ~FMUServo(); - virtual int ioctl(struct file *filp, int cmd, unsigned long arg); + virtual int ioctl(file *filp, int cmd, unsigned long arg); virtual int init(); @@ -93,6 +93,7 @@ private: int _t_armed; orb_advert_t _t_outputs; unsigned _num_outputs; + bool _primary_pwm_device; volatile bool _task_should_exit; bool _armed; @@ -118,7 +119,7 @@ FMUServo *g_servo; } // namespace FMUServo::FMUServo(Mode mode, int update_rate) : - CDev("fmuservo", PWM_OUTPUT_DEVICE_PATH), + CDev("fmuservo", "/dev/px4fmu"), _mode(mode), _update_rate(update_rate), _task(-1), @@ -126,6 +127,7 @@ FMUServo::FMUServo(Mode mode, int update_rate) : _t_armed(-1), _t_outputs(0), _num_outputs(0), + _primary_pwm_device(false), _task_should_exit(false), _armed(false), _mixers(nullptr) @@ -135,18 +137,16 @@ FMUServo::FMUServo(Mode mode, int update_rate) : FMUServo::~FMUServo() { if (_task != -1) { - - /* task should wake up every 100ms or so at least */ + /* tell the task we want it to go away */ _task_should_exit = true; - unsigned i = 0; - + unsigned i = 10; do { - /* wait 20ms */ - usleep(20000); + /* wait 50ms - it should wake every 100ms or so worst-case */ + usleep(50000); /* if we have given up, kill it */ - if (++i > 10) { + if (--i == 0) { task_delete(_task); break; } @@ -154,6 +154,10 @@ FMUServo::~FMUServo() } while (_task != -1); } + /* clean up the alternate device node */ + if (_primary_pwm_device) + unregister_driver(PWM_OUTPUT_DEVICE_PATH); + g_servo = nullptr; } @@ -170,6 +174,13 @@ FMUServo::init() if (ret != OK) return ret; + /* try to claim the generic PWM output device node as well - it's OK if we fail at this */ + ret = register_driver(PWM_OUTPUT_DEVICE_PATH, &fops, 0666, (void *)this); + if (ret == OK) { + log("default PWM output device"); + _primary_pwm_device = true; + } + /* start the IO interface task */ _task = task_spawn("fmuservo", SCHED_DEFAULT, @@ -216,8 +227,12 @@ FMUServo::task_main() break; } - /* subscribe to objects that we are interested in watching */ - _t_actuators = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS); + /* + * Subscribe to the appropriate PWM output topic based on whether we are the + * primary PWM output or not. + */ + _t_actuators = orb_subscribe(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS : + ORB_ID(actuator_controls_1)); /* convert the update rate in hz to milliseconds, rounding down if necessary */ int update_rate_in_ms = int(1000 / _update_rate); orb_set_interval(_t_actuators, update_rate_in_ms); @@ -226,11 +241,13 @@ FMUServo::task_main() orb_set_interval(_t_armed, 200); /* 5Hz update rate */ /* advertise the mixed control outputs */ - struct actuator_outputs_s outputs; + actuator_outputs_s outputs; memset(&outputs, 0, sizeof(outputs)); - _t_outputs = orb_advertise(ORB_ID_VEHICLE_CONTROLS, &outputs); + /* advertise the mixed control outputs */ + _t_outputs = orb_advertise(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1), + &outputs); - struct pollfd fds[2]; + pollfd fds[2]; fds[0].fd = _t_actuators; fds[0].events = POLLIN; fds[1].fd = _t_armed; @@ -282,7 +299,7 @@ FMUServo::task_main() /* how about an arming update? */ if (fds[1].revents & POLLIN) { - struct actuator_armed_s aa; + actuator_armed_s aa; /* get new value */ orb_copy(ORB_ID(actuator_armed), _t_armed, &aa); @@ -320,7 +337,7 @@ FMUServo::control_callback(uintptr_t handle, } int -FMUServo::ioctl(struct file *filp, int cmd, unsigned long arg) +FMUServo::ioctl(file *filp, int cmd, unsigned long arg) { int ret = OK; int channel; @@ -569,7 +586,7 @@ fake(int argc, char *argv[]) exit(1); } - struct actuator_controls_s ac; + actuator_controls_s ac; ac.control[0] = strtol(argv[1], 0, 0) / 100.0f; diff --git a/apps/px4/px4io/driver/px4io.cpp b/apps/px4/px4io/driver/px4io.cpp index c3371c138..66db1c360 100644 --- a/apps/px4/px4io/driver/px4io.cpp +++ b/apps/px4/px4io/driver/px4io.cpp @@ -37,8 +37,7 @@ * * PX4IO is connected via serial (or possibly some other interface at a later * point). - * - * XXX current design is racy as all hell; need a locking strategy. + */ #include <nuttx/config.h> @@ -53,6 +52,7 @@ #include <errno.h> #include <string.h> #include <stdio.h> +#include <stdlib.h> #include <unistd.h> #include <fcntl.h> @@ -61,185 +61,122 @@ #include <drivers/device/device.h> #include <drivers/drv_rc_input.h> #include <drivers/drv_pwm_output.h> +#include <systemlib/mixer/mixer.h> +#include <drivers/drv_mixer.h> #include <systemlib/perf_counter.h> #include <systemlib/hx_stream.h> +#include <systemlib/err.h> +#include <systemlib/systemlib.h> + +#include <uORB/topics/actuator_controls.h> +#include <uORB/topics/actuator_outputs.h> +#include <uORB/topics/rc_channels.h> #include "px4io/protocol.h" #include "uploader.h" -class PX4IO; - -namespace -{ - -/* oddly, ERROR is not defined for c++ */ -#ifdef ERROR -# undef ERROR -#endif -const int ERROR = -1; - -PX4IO *g_dev; - -} - - -class PX4IO_RC : public device::CDev +class PX4IO : public device::CDev { public: - PX4IO_RC(); - ~PX4IO_RC(); + PX4IO(); + ~PX4IO(); virtual int init(); - virtual ssize_t read(struct file *filp, char *buffer, size_t buflen); - friend class PX4IO; -protected: - void set_channels(unsigned count, const servo_position_t *data); + virtual int ioctl(file *filp, int cmd, unsigned long arg); private: - orb_advert_t _publication; - struct rc_input_values _input; -}; + static const unsigned _max_actuators = PX4IO_OUTPUT_CHANNELS; -/* XXX this may conflict with the onboard PPM input */ -PX4IO_RC::PX4IO_RC() : - CDev("px4io_rc", RC_INPUT_DEVICE_PATH), - _publication(-1) -{ - for (unsigned i = 0; i < RC_INPUT_MAX_CHANNELS; i++) { - _input.values[i] = 0; - } - _input.channel_count = 0; -} + int _serial_fd; ///< serial interface to PX4IO + hx_stream_t _io_stream; ///< HX protocol stream -PX4IO_RC::~PX4IO_RC() -{ - if (_publication != -1) - ::close(_publication); -} + int _task; ///< worker task + volatile bool _task_should_exit; -int -PX4IO_RC::init() -{ - int ret; + int _t_actuators; ///< actuator output topic + actuator_controls_s _controls; ///< actuator outputs - ret = CDev::init(); + int _t_armed; ///< system armed control topic + actuator_armed_s _armed; ///< system armed state - /* advertise ourselves as the RC input controller */ - if (ret == OK) { - _publication = orb_advertise(ORB_ID(input_rc), &_input); - if (_publication < 0) - ret = -errno; - } + orb_advert_t _t_outputs; ///< mixed outputs topic + actuator_outputs_s _outputs; ///< mixed outputs - return ret; -} + MixerGroup *_mixers; ///< loaded mixers -ssize_t -PX4IO_RC::read(struct file *filp, char *buffer, size_t buflen) -{ - unsigned channels = buflen / sizeof(rc_input_t); - rc_input_t *pdata = (rc_input_t *)buffer; - unsigned i; + bool _primary_pwm_device; ///< true if we are the default PWM output - if (channels > PX4IO_INPUT_CHANNELS) - return -EIO; + volatile bool _switch_armed; ///< PX4IO switch armed state + // XXX how should this work? - lock(); - for (i = 0; i < channels; i++) - pdata[i] = _input.values[i]; - unlock(); + bool _send_needed; ///< If true, we need to send a packet to IO - return i * sizeof(servo_position_t); -} + /** + * Trampoline to the worker task + */ + static void task_main_trampoline(int argc, char *argv[]); -void -PX4IO_RC::set_channels(unsigned count, const servo_position_t *data) -{ + /** + * worker task + */ + void task_main(); - ASSERT(count <= PX4IO_INPUT_CHANNELS); + /** + * Handle receiving bytes from PX4IO + */ + void io_recv(); - /* convert incoming servo position values into 0-100 range */ - lock(); - for (unsigned i = 0; i < count; i++) { - rc_input_t chn; + /** + * HX protocol callback trampoline. + */ + static void rx_callback_trampoline(void *arg, const void *buffer, size_t bytes_received); - if (data[i] < 1000) { - chn = 0; - } else if (data[i] > 2000) { - chn = 100; - } else { - chn = (data[i] - 1000) / 10; - } + /** + * Callback invoked when we receive a whole packet from PX4IO + */ + void rx_callback(const uint8_t *buffer, size_t bytes_received); - _input.values[i] = chn; - } - _input.channel_count = count; - unlock(); + /** + * Send an update packet to PX4IO + */ + void io_send(); - /* publish to anyone that might be listening */ - if (_publication != -1) - orb_publish(ORB_ID(input_rc), _publication, &_input); + /** + * Mixer control callback; invoked to fetch a control from a specific + * group/index during mixing. + */ + static int control_callback(uintptr_t handle, + uint8_t control_group, + uint8_t control_index, + float &input); +}; -} -class PX4IO : public device::CDev +namespace { -public: - PX4IO(); - ~PX4IO(); - - virtual int init(); - - virtual ssize_t write(struct file *filp, const char *buffer, size_t buflen); - virtual int ioctl(struct file *filp, int cmd, unsigned long arg); - -private: - int _fd; - int _task; - PX4IO_RC *_rc; - - /** command to be sent to IO */ - struct px4io_command _next_command; - /** RC channel input from IO */ - servo_position_t _rc_channel[PX4IO_INPUT_CHANNELS]; - int _rc_channel_count; - - volatile bool _armed; - volatile bool _task_should_exit; - - bool _send_needed; - - hx_stream_t _io_stream; - - static void task_main_trampoline(int argc, char *argv[]); - void task_main(); - void io_recv(); - - static void rx_callback_trampoline(void *arg, const void *buffer, size_t bytes_received); - void rx_callback(const uint8_t *buffer, size_t bytes_received); +PX4IO *g_dev; - void io_send(); -}; +} PX4IO::PX4IO() : CDev("px4io", "/dev/px4io"), - _fd(-1), + _serial_fd(-1), + _io_stream(nullptr), _task(-1), - _rc(new PX4IO_RC), - _rc_channel_count(0), - _armed(false), _task_should_exit(false), - _send_needed(false), - _io_stream(nullptr) + _t_actuators(-1), + _t_armed(-1), + _t_outputs(-1), + _mixers(nullptr), + _primary_pwm_device(false), + _switch_armed(false), + _send_needed(false) { - /* set up the command we will use */ - _next_command.f2i_magic = F2I_MAGIC; - - /* we need this potentially before it could be set in px4io_main */ + /* we need this potentially before it could be set in task_main */ g_dev = this; _debug_enabled = true; @@ -247,19 +184,18 @@ PX4IO::PX4IO() : PX4IO::~PX4IO() { - if (_rc != nullptr) - delete _rc; if (_task != -1) { - /* task should wake up every 100ms or so at least */ + /* tell the task we want it to go away */ _task_should_exit = true; - unsigned i = 0; + /* spin waiting for the thread to stop */ + unsigned i = 10; do { - /* wait 20ms */ - usleep(20000); + /* wait 50ms - it should wake every 100ms or so worst-case */ + usleep(50000); /* if we have given up, kill it */ - if (++i > 10) { + if (--i == 0) { task_delete(_task); break; } @@ -267,6 +203,14 @@ PX4IO::~PX4IO() } while (_task != -1); } + /* clean up the alternate device node */ + if (_primary_pwm_device) + unregister_driver(PWM_OUTPUT_DEVICE_PATH); + + /* kill the HX stream */ + if (_io_stream != nullptr) + hx_stream_free(_io_stream); + g_dev = nullptr; } @@ -277,17 +221,20 @@ PX4IO::init() ASSERT(_task == -1); - /* XXX send a who-are-you request */ - - /* XXX verify firmware/protocol version */ - /* do regular cdev init */ ret = CDev::init(); if (ret != OK) return ret; + /* try to claim the generic PWM output device node as well - it's OK if we fail at this */ + ret = register_driver(PWM_OUTPUT_DEVICE_PATH, &fops, 0666, (void *)this); + if (ret == OK) { + log("default PWM output device"); + _primary_pwm_device = true; + } + /* start the IO interface task */ - _task = task_create("px4io", SCHED_PRIORITY_DEFAULT, 1024, (main_t)&PX4IO::task_main_trampoline, nullptr); + _task = task_create("px4io", SCHED_PRIORITY_DEFAULT, 4096, (main_t)&PX4IO::task_main_trampoline, nullptr); if (_task < 0) { debug("task start failed: %d", errno); return -errno; @@ -305,36 +252,61 @@ PX4IO::task_main_trampoline(int argc, char *argv[]) void PX4IO::task_main() { - ASSERT(_fd == -1); - - log("ready"); + log("starting"); /* open the serial port */ - _fd = ::open("/dev/ttyS2", O_RDWR | O_NONBLOCK); - if (_fd < 0) { + _serial_fd = ::open("/dev/ttyS2", O_RDWR); + if (_serial_fd < 0) { debug("failed to open serial port for IO: %d", errno); _task = -1; _exit(errno); } /* protocol stream */ - _io_stream = hx_stream_init(_fd, &PX4IO::rx_callback_trampoline, this); + _io_stream = hx_stream_init(_serial_fd, &PX4IO::rx_callback_trampoline, this); - perf_counter_t pc_tx_bytes = perf_alloc(PC_COUNT, "PX4IO frames transmitted"); - perf_counter_t pc_rx_bytes = perf_alloc(PC_COUNT, "PX4IO frames received"); + perf_counter_t pc_tx_frames = perf_alloc(PC_COUNT, "PX4IO frames transmitted"); + perf_counter_t pc_rx_frames = perf_alloc(PC_COUNT, "PX4IO frames received"); perf_counter_t pc_rx_errors = perf_alloc(PC_COUNT, "PX4IO receive errors"); - hx_stream_set_counters(_io_stream, pc_tx_bytes, pc_rx_bytes, pc_rx_errors); + hx_stream_set_counters(_io_stream, pc_tx_frames, pc_rx_frames, pc_rx_errors); + + /* XXX send a who-are-you request */ + + /* XXX verify firmware/protocol version */ - /* poll descriptor(s) */ - struct pollfd fds[1]; - fds[0].fd = _fd; + /* + * Subscribe to the appropriate PWM output topic based on whether we are the + * primary PWM output or not. + */ + _t_actuators = orb_subscribe(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS : + ORB_ID(actuator_controls_1)); + /* convert the update rate in hz to milliseconds, rounding down if necessary */ + //int update_rate_in_ms = int(1000 / _update_rate); + orb_set_interval(_t_actuators, 20); /* XXX 50Hz hardcoded for now */ + + _t_armed = orb_subscribe(ORB_ID(actuator_armed)); + orb_set_interval(_t_armed, 200); /* 5Hz update rate */ + + /* advertise the mixed control outputs */ + _t_outputs = orb_advertise(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1), + &_outputs); + + /* poll descriptor */ + pollfd fds[3]; + fds[0].fd = _serial_fd; fds[0].events = POLLIN; + fds[1].fd = _t_actuators; + fds[1].events = POLLIN; + fds[2].fd = _t_armed; + fds[2].events = POLLIN; + + log("ready"); /* loop handling received serial bytes */ while (!_task_should_exit) { /* sleep waiting for data, but no more than 100ms */ - int ret = ::poll(&fds[0], 1, 100); + int ret = ::poll(&fds[0], sizeof(fds) / sizeof(fds[0]), 1000); /* this would be bad... */ if (ret < 0) { @@ -347,9 +319,36 @@ PX4IO::task_main() if (ret == 0) _send_needed = true; - /* if we have new data from IO, go handle it */ - if ((ret > 0) && (fds[0].revents & POLLIN)) - io_recv(); + if (ret > 0) { + /* if we have new data from IO, go handle it */ + if (fds[0].revents & POLLIN) + io_recv(); + + /* if we have new data from the ORB, go handle it */ + if (fds[1].revents & POLLIN) { + + /* get controls */ + orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, _t_actuators, &_controls); + + /* mix */ + if (_mixers != nullptr) { + /* XXX is this the right count? */ + _mixers->mix(&_outputs.output[0], _max_actuators); + + /* convert to PWM values */ + for (unsigned i = 0; i < _max_actuators; i++) + _outputs.output[i] = 1500 + (600 * _outputs.output[i]); + + /* and flag for update */ + _send_needed = true; + } + } + if (fds[2].revents & POLLIN) { + + orb_copy(ORB_ID(actuator_armed), _t_armed, &_controls); + _send_needed = true; + } + } /* send an update to IO if required */ if (_send_needed) { @@ -357,23 +356,40 @@ PX4IO::task_main() io_send(); } } - if (_io_stream != nullptr) - hx_stream_free(_io_stream); - ::close(_fd); /* tell the dtor that we are exiting */ _task = -1; _exit(0); } +int +PX4IO::control_callback(uintptr_t handle, + uint8_t control_group, + uint8_t control_index, + float &input) +{ + const actuator_controls_s *controls = (actuator_controls_s *)handle; + + input = controls->control[control_index]; + return 0; +} + void PX4IO::io_recv() { - uint8_t c; - - /* handle bytes from IO */ - while (::read(_fd, &c, 1) == 1) - hx_stream_rx(_io_stream, c); + uint8_t buf[32]; + int count; + + /* + * We are here because poll says there is some data, so this + * won't block even on a blocking device. If more bytes are + * available, we'll go back to poll() again... + */ + count = ::read(_serial_fd, buf, sizeof(buf)); + + /* pass received bytes to the packet decoder */ + for (int i = 0; i < count; i++) + hx_stream_rx(_io_stream, buf[i]); } void @@ -385,98 +401,139 @@ PX4IO::rx_callback_trampoline(void *arg, const void *buffer, size_t bytes_receiv void PX4IO::rx_callback(const uint8_t *buffer, size_t bytes_received) { - const struct px4io_report *rep = (const struct px4io_report *)buffer; + const px4io_report *rep = (const px4io_report *)buffer; /* sanity-check the received frame size */ - if (bytes_received != sizeof(struct px4io_report)) + if (bytes_received != sizeof(px4io_report)) return; - lock(); + /* XXX handle R/C inputs here ... needs code sharing/library */ - /* pass RC input data to the driver */ - if (_rc != nullptr) - _rc->set_channels(rep->channel_count, &rep->rc_channel[0]); - _armed = rep->armed; - - /* send an update frame */ - _send_needed = true; + /* remember the latched arming switch state */ + _switch_armed = rep->armed; unlock(); - } void PX4IO::io_send() { - lock(); + px4io_command cmd; - /* send packet to IO while we're guaranteed it won't change */ - hx_stream_send(_io_stream, &_next_command, sizeof(_next_command)); + cmd.f2i_magic = F2I_MAGIC; - unlock(); -} + /* set outputs */ + for (unsigned i = 0; i < _max_actuators; i++) + cmd.servo_command[i] = _outputs.output[i]; -ssize_t -PX4IO::write(struct file *filp, const char *buffer, size_t len) -{ - unsigned channels = len / sizeof(servo_position_t); - servo_position_t *pdata = (servo_position_t *)buffer; - unsigned i; + /* publish as we send */ + orb_publish(ORB_ID_VEHICLE_CONTROLS, _t_outputs, &_outputs); - if (channels > PX4IO_OUTPUT_CHANNELS) - return -EIO; + // XXX relays - lock(); - for (i = 0; i < channels; i++) - _next_command.servo_command[i] = pdata[i]; - unlock(); + cmd.arm_ok = _armed.armed; - return i * sizeof(servo_position_t); + hx_stream_send(_io_stream, &cmd, sizeof(cmd)); } int -PX4IO::ioctl(struct file *filep, int cmd, unsigned long arg) +PX4IO::ioctl(file *filep, int cmd, unsigned long arg) { - int ret = -ENOTTY; + int ret = OK; lock(); /* regular ioctl? */ switch (cmd) { case PWM_SERVO_ARM: - _next_command.arm_ok = true; - ret = 0; + /* fake an armed transition */ + _armed.armed = true; + _send_needed = true; break; case PWM_SERVO_DISARM: - _next_command.arm_ok = false; - ret = 0; + /* fake a disarmed transition */ + _armed.armed = true; + _send_needed = true; break; - default: - /* channel set? */ - if ((cmd >= PWM_SERVO_SET(0)) && (cmd < PWM_SERVO_SET(PX4IO_OUTPUT_CHANNELS))) { - /* XXX sanity-check value? */ - _next_command.servo_command[cmd - PWM_SERVO_SET(0)] = arg; - ret = 0; - break; + case PWM_SERVO_SET(0) ... PWM_SERVO_SET(_max_actuators - 1): + /* fake an update to the selected servo channel */ + if ((arg >= 900) && (arg <= 2100)) { + _outputs.output[cmd - PWM_SERVO_SET(0)] = arg; + _send_needed = true; + } else { + ret = -EINVAL; } + break; - /* channel get? */ - if ((cmd >= PWM_SERVO_GET(0)) && (cmd < PWM_SERVO_GET(PX4IO_INPUT_CHANNELS))) { - int channel = cmd - PWM_SERVO_GET(0); + case PWM_SERVO_GET(0) ... PWM_SERVO_GET(_max_actuators - 1): + /* copy the current output value from the channel */ + *(servo_position_t *)arg = _outputs.output[cmd - PWM_SERVO_GET(0)]; + break; - /* currently no data for this channel */ - if (channel >= _rc_channel_count) { - ret = -ERANGE; - break; + case MIXERIOCGETOUTPUTCOUNT: + *(unsigned *)arg = _max_actuators; + break; + + case MIXERIOCRESET: + if (_mixers != nullptr) { + delete _mixers; + _mixers = nullptr; + } + break; + + case MIXERIOCADDSIMPLE: { + mixer_simple_s *mixinfo = (mixer_simple_s *)arg; + + /* build the new mixer from the supplied argument */ + SimpleMixer *mixer = new SimpleMixer(control_callback, + (uintptr_t)&_controls, mixinfo); + + /* validate the new mixer */ + if (mixer->check()) { + delete mixer; + ret = -EINVAL; + + } else { + /* if we don't have a group yet, allocate one */ + if (_mixers == nullptr) + _mixers = new MixerGroup(control_callback, + (uintptr_t)&_controls); + + /* add the new mixer to the group */ + _mixers->add_mixer(mixer); } - *(servo_position_t *)arg = _rc_channel[channel]; - ret = 0; - break; } + break; + + case MIXERIOCADDMULTIROTOR: + /* XXX not yet supported */ + ret = -ENOTTY; + break; + + case MIXERIOCLOADFILE: { + MixerGroup *newmixers; + const char *path = (const char *)arg; + + /* allocate a new mixer group and load it from the file */ + newmixers = new MixerGroup(control_callback, (uintptr_t)&_controls); + if (newmixers->load_from_file(path) != 0) { + delete newmixers; + ret = -EINVAL; + } + + /* swap the new mixers in for the old */ + if (_mixers != nullptr) { + delete _mixers; + } + _mixers = newmixers; + + } + break; + default: /* not a recognised value */ ret = -ENOTTY; } @@ -492,28 +549,25 @@ px4io_main(int argc, char *argv[]) { if (!strcmp(argv[1], "start")) { - if (g_dev != nullptr) { - fprintf(stderr, "PX4IO: already loaded\n"); - return -EBUSY; - } + if (g_dev != nullptr) + errx(1, "already loaded"); /* create the driver - it will set g_dev */ (void)new PX4IO; - if (g_dev == nullptr) { - fprintf(stderr, "PX4IO: driver alloc failed\n"); - return -ENOMEM; - } + if (g_dev == nullptr) + errx(1, "driver alloc failed"); if (OK != g_dev->init()) { - fprintf(stderr, "PX4IO: driver init failed\n"); delete g_dev; - return -EIO; + errx(1, "driver init failed"); } - return OK; + exit(0); } + /* note, stop not currently implemented */ + if (!strcmp(argv[1], "update")) { PX4IO_Uploader *up; const char *fn[3]; @@ -536,26 +590,19 @@ px4io_main(int argc, char *argv[]) case OK: break; case -ENOENT: - fprintf(stderr, "PX4IO firmware file not found\n"); - break; + errx(1, "PX4IO firmware file not found"); case -EEXIST: case -EIO: - fprintf(stderr, "error updating PX4IO - check that bootloader mode is enabled\n"); - break; + errx(1, "error updating PX4IO - check that bootloader mode is enabled"); case -EINVAL: - fprintf(stderr, "verify failed - retry the update\n"); - break; + errx(1, "verify failed - retry the update"); case -ETIMEDOUT: - fprintf(stderr, "timed out waiting for bootloader - power-cycle and try again\n"); + errx(1, "timed out waiting for bootloader - power-cycle and try again"); default: - fprintf(stderr, "unexpected error %d\n", ret); - break; + errx(1, "unexpected error %d", ret); } return ret; } - - - printf("need a verb, only support 'start' and 'update'\n"); - return ERROR; + errx(1, "need a verb, only support 'start' and 'update'"); } diff --git a/apps/px4/px4io/driver/uploader.cpp b/apps/px4/px4io/driver/uploader.cpp index 7d6a9e171..0fbbac839 100644 --- a/apps/px4/px4io/driver/uploader.cpp +++ b/apps/px4/px4io/driver/uploader.cpp @@ -318,7 +318,7 @@ PX4IO_Uploader::verify() ret = recv(c); if (ret != OK) { - log("%d: got %d waiting for bytes", ret); + log("%d: got %d waiting for bytes", base + i, ret); return ret; } diff --git a/apps/px4/tests/test_sensors.c b/apps/px4/tests/test_sensors.c index 87ea7f058..c801869ab 100644 --- a/apps/px4/tests/test_sensors.c +++ b/apps/px4/tests/test_sensors.c @@ -56,10 +56,6 @@ #include "tests.h" -#include <arch/board/drv_lis331.h> -#include <arch/board/drv_bma180.h> -#include <arch/board/drv_l3gd20.h> -#include <arch/board/drv_hmc5883l.h> #include <drivers/drv_accel.h> /**************************************************************************** @@ -75,10 +71,6 @@ ****************************************************************************/ //static int lis331(int argc, char *argv[]); -static int l3gd20(int argc, char *argv[]); -static int bma180(int argc, char *argv[]); -static int hmc5883l(int argc, char *argv[]); -static int ms5611(int argc, char *argv[]); static int mpu6000(int argc, char *argv[]); /**************************************************************************** @@ -90,12 +82,7 @@ struct { const char *path; int (* test)(int argc, char *argv[]); } sensors[] = { - {"bma180", "/dev/bma180", bma180}, {"mpu6000", "/dev/accel", mpu6000}, - {"l3gd20", "/dev/l3gd20", l3gd20}, - {"hmc5883l", "/dev/hmc5883l", hmc5883l}, - {"ms5611", "/dev/ms5611", ms5611}, -// {"lis331", "/dev/lis331", lis331}, {NULL, NULL, NULL} }; @@ -107,226 +94,6 @@ struct { * Private Functions ****************************************************************************/ -//static int -//lis331(int argc, char *argv[]) -//{ -// int fd; -// int16_t buf[3]; -// int ret; -// -// fd = open("/dev/lis331", O_RDONLY); -// if (fd < 0) { -// printf("\tlis331: not present on PX4FMU v1.5 and later\n"); -// return ERROR; -// } -// -// if (ioctl(fd, LIS331_SETRATE, LIS331_RATE_50Hz) || -// ioctl(fd, LIS331_SETRANGE, LIS331_RANGE_4G)) { -// -// printf("LIS331: ioctl fail\n"); -// return ERROR; -// } -// -// /* wait at least 100ms, sensor should have data after no more than 20ms */ -// usleep(100000); -// -// /* read data - expect samples */ -// ret = read(fd, buf, sizeof(buf)); -// if (ret != sizeof(buf)) { -// printf("LIS331: read1 fail (%d)\n", ret); -// return ERROR; -// } -// -// /* read data - expect no samples (should not be ready again yet) */ -// ret = read(fd, buf, sizeof(buf)); -// if (ret != 0) { -// printf("LIS331: read2 fail (%d)\n", ret); -// return ERROR; -// } -// -// /* XXX more tests here */ -// -// return 0; -//} - -static int -l3gd20(int argc, char *argv[]) -{ - printf("\tL3GD20: test start\n"); - fflush(stdout); - - int fd; - int16_t buf[3] = {0, 0, 0}; - int ret; - - fd = open("/dev/l3gd20", O_RDONLY | O_NONBLOCK); - - if (fd < 0) { - printf("L3GD20: open fail\n"); - return ERROR; - } - -// if (ioctl(fd, L3GD20_SETRATE, L3GD20_RATE_760HZ_LP_50HZ) || -// ioctl(fd, L3GD20_SETRANGE, L3GD20_RANGE_500DPS)) { -// -// printf("L3GD20: ioctl fail\n"); -// return ERROR; -// } else { -// printf("\tconfigured..\n"); -// } -// -// /* wait at least 100ms, sensor should have data after no more than 2ms */ -// usleep(100000); - - - - /* read data - expect samples */ - ret = read(fd, buf, sizeof(buf)); - - if (ret != sizeof(buf)) { - printf("\tL3GD20: read1 fail (%d should have been %d)\n", ret, sizeof(buf)); - //return ERROR; - - } else { - printf("\tL3GD20 values #1: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); - } - - /* wait at least 2 ms, sensor should have data after no more than 1.5ms */ - usleep(2000); - - /* read data - expect no samples (should not be ready again yet) */ - ret = read(fd, buf, sizeof(buf)); - - if (ret != sizeof(buf)) { - printf("\tL3GD20: read2 fail (%d)\n", ret); - close(fd); - return ERROR; - - } else { - printf("\tL3GD20 values #2: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); - } - - /* empty sensor buffer */ - ret = 0; - - while (ret != sizeof(buf)) { - // Keep reading until successful - ret = read(fd, buf, sizeof(buf)); - } - - /* test if FIFO is operational */ - usleep(14800); // Expecting 10 measurements - - ret = 0; - int count = 0; - bool dataready = true; - - while (dataready) { - // Keep reading until successful - ret = read(fd, buf, sizeof(buf)); - - if (ret != sizeof(buf)) { - dataready = false; - - } else { - count++; - } - } - - printf("\tL3GD20: Drained FIFO with %d values (expected 8-12)\n", count); - - /* read data - expect no samples (should not be ready again yet) */ - ret = read(fd, buf, sizeof(buf)); - - if (ret != 0) { - printf("\tL3GD20: Note: read3 got data - there should not have been data ready\n", ret); -// return ERROR; - } - - close(fd); - - /* Let user know everything is ok */ - printf("\tOK: L3GD20 passed all tests successfully\n"); - return OK; -} - -static int -bma180(int argc, char *argv[]) -{ - // XXX THIS SENSOR IS OBSOLETE - // TEST REMAINS, BUT ALWAYS RETURNS OK - - printf("\tBMA180: test start\n"); - fflush(stdout); - - int fd; - int16_t buf[3] = {0, 0, 0}; - int ret; - - fd = open("/dev/bma180", O_RDONLY); - - if (fd < 0) { - printf("\tBMA180: open fail\n"); - return OK; - } - -// if (ioctl(fd, LIS331_SETRATE, LIS331_RATE_50Hz) || -// ioctl(fd, LIS331_SETRANGE, LIS331_RANGE_4G)) { -// -// printf("BMA180: ioctl fail\n"); -// return ERROR; -// } -// - /* wait at least 100ms, sensor should have data after no more than 20ms */ - usleep(100000); - - /* read data - expect samples */ - ret = read(fd, buf, sizeof(buf)); - - if (ret != sizeof(buf)) { - printf("\tBMA180: read1 fail (%d)\n", ret); - close(fd); - return OK; - - } else { - printf("\tBMA180 values: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); - } - - /* wait at least 10ms, sensor should have data after no more than 2ms */ - usleep(100000); - - ret = read(fd, buf, sizeof(buf)); - - if (ret != sizeof(buf)) { - printf("\tBMA180: read2 fail (%d)\n", ret); - close(fd); - return OK; - - } else { - printf("\tBMA180: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); - } - - /* empty sensor buffer */ - ret = 0; - - while (ret != sizeof(buf)) { - // Keep reading until successful - ret = read(fd, buf, sizeof(buf)); - } - - ret = read(fd, buf, sizeof(buf)); - - if (ret != 0) { - printf("\tBMA180: Note: read3 got data - there should not have been data ready\n", ret); - } - - /* Let user know everything is ok */ - printf("\tOK: BMA180 passed all tests successfully\n"); - close(fd); - - return OK; -} - static int mpu6000(int argc, char *argv[]) { @@ -379,103 +146,6 @@ mpu6000(int argc, char *argv[]) return OK; } -static int -ms5611(int argc, char *argv[]) -{ - printf("\tMS5611: test start\n"); - fflush(stdout); - - int fd; - float buf[3] = {0.0f, 0.0f, 0.0f}; - int ret; - - fd = open("/dev/ms5611", O_RDONLY); - - if (fd < 0) { - printf("\tMS5611: open fail\n"); - return ERROR; - } - - for (int i = 0; i < 5; i++) { - /* read data - expect samples */ - ret = read(fd, buf, sizeof(buf)); - - if (ret != sizeof(buf)) { - - if ((int8_t)ret == -EAGAIN || (int8_t)ret == -EINPROGRESS) { - /* waiting for device to become ready, this is not an error */ - } else { - printf("\tMS5611: read fail (%d)\n", ret); - close(fd); - return ERROR; - } - - } else { - - /* hack for float printing */ - int32_t pressure_int = buf[0]; - int32_t altitude_int = buf[1]; - int32_t temperature_int = buf[2]; - - printf("\tMS5611: pressure:%d.%03d mbar - altitude: %d.%02d meters - temp:%d.%02d deg celcius\n", pressure_int, (int)(buf[0] * 1000 - pressure_int * 1000), altitude_int, (int)(buf[1] * 100 - altitude_int * 100), temperature_int, (int)(buf[2] * 100 - temperature_int * 100)); - } - - /* wait at least 10ms, sensor should have data after no more than 6.5ms */ - usleep(10000); - } - - close(fd); - - /* Let user know everything is ok */ - printf("\tOK: MS5611 passed all tests successfully\n"); - - return OK; -} - -static int -hmc5883l(int argc, char *argv[]) -{ - printf("\tHMC5883L: test start\n"); - fflush(stdout); - - int fd; - int16_t buf[7] = {0, 0, 0}; - int ret; - - fd = open("/dev/hmc5883l", O_RDONLY); - - if (fd < 0) { - printf("\tHMC5883L: open fail\n"); - return ERROR; - } - - int i; - - for (i = 0; i < 5; i++) { - /* wait at least 7ms, sensor should have data after no more than 6.5ms */ - usleep(7000); - - /* read data - expect samples */ - ret = read(fd, buf, sizeof(buf)); - - if (ret != sizeof(buf)) { - printf("\tHMC5883L: read1 fail (%d) values: x:%d\ty:%d\tz:%d\n", ret, buf[0], buf[1], buf[2]); - close(fd); - return ERROR; - - } else { - printf("\tHMC5883L: x:%d\ty:%d\tz:%d\n", buf[0], buf[1], buf[2]); - } - } - - close(fd); - - /* Let user know everything is ok */ - printf("\tOK: HMC5883L passed all tests successfully\n"); - - return OK; -} - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/apps/px4io/protocol.h b/apps/px4io/protocol.h index 96e0ca350..edc2c4bd2 100644 --- a/apps/px4io/protocol.h +++ b/apps/px4io/protocol.h @@ -39,6 +39,8 @@ * messages and the corresponding complexity involved. */ +#pragma once + /* * XXX MUST BE KEPT IN SYNC WITH THE VERSION IN PX4FMU UNTIL * TREES ARE MERGED. diff --git a/apps/system/Kconfig b/apps/system/Kconfig index 44bf5a2e6..d4d434665 100644 --- a/apps/system/Kconfig +++ b/apps/system/Kconfig @@ -3,7 +3,7 @@ # see misc/tools/kconfig-language.txt. # -menu "Custom free memory command" +menu "Custom Free Memory Command" source "$APPSDIR/system/free/Kconfig" endmenu @@ -15,6 +15,22 @@ menu "FLASH Program Installation" source "$APPSDIR/system/install/Kconfig" endmenu -menu "readline() support" +menu "readline()" source "$APPSDIR/system/readline/Kconfig" endmenu + +menu "Power Off" +source "$APPSDIR/system/poweroff/Kconfig" +endmenu + +menu "RAMTRON" +source "$APPSDIR/system/ramtron/Kconfig" +endmenu + +menu "SD Card" +source "$APPSDIR/system/sdcard/Kconfig" +endmenu + +menu "Sysinfo" +source "$APPSDIR/system/sysinfo/Kconfig" +endmenu diff --git a/apps/system/Make.defs b/apps/system/Make.defs index a4aea2d31..3d10f84e5 100644 --- a/apps/system/Make.defs +++ b/apps/system/Make.defs @@ -49,3 +49,20 @@ endif ifeq ($(CONFIG_SYSTEM_READLINE),y) CONFIGURED_APPS += system/readline endif + +ifeq ($(CONFIG_SYSTEM_POWEROFF),y) +CONFIGURED_APPS += system/poweroff +endif + +ifeq ($(CONFIG_SYSTEM_RAMTRON),y) +CONFIGURED_APPS += system/ramtron +endif + +ifeq ($(CONFIG_SYSTEM_SDCARD),y) +CONFIGURED_APPS += system/sdcard +endif + +ifeq ($(CONFIG_SYSTEM_SYSINFO),y) +CONFIGURED_APPS += system/sysinfo +endif + diff --git a/apps/system/Makefile b/apps/system/Makefile index 73eb60d15..d64bb54c6 100644 --- a/apps/system/Makefile +++ b/apps/system/Makefile @@ -37,7 +37,7 @@ # Sub-directories containing system task -SUBDIRS = free i2c install readline +SUBDIRS = free i2c install readline poweroff ramtron sdcard sysinfo # Create the list of installed runtime modules (INSTALLED_DIRS) diff --git a/apps/system/free/free.c b/apps/system/free/free.c index 3d9698ecb..c44cd5e22 100644 --- a/apps/system/free/free.c +++ b/apps/system/free/free.c @@ -33,57 +33,65 @@ * ****************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include <nuttx/config.h> #include <nuttx/progmem.h> #include <stdio.h> #include <stdlib.h> - /**************************************************************************** * Private Functions ****************************************************************************/ - -/* \todo Max block size only works on uniform prog mem */ - -void free_getprogmeminfo(struct mallinfo * mem) + +/* TODO Max block size only works on uniform prog mem */ + +static void free_getprogmeminfo(struct mallinfo * mem) { - uint16_t page = 0, stpage = 0xFFFF; - uint16_t pagesize = 0; - int status; - - mem->arena = 0; - mem->fordblks = 0; - mem->uordblks = 0; - mem->mxordblk = 0; - - for (status=0, page=0; status >= 0; page++) { - - status = up_progmem_ispageerased(page); - pagesize = up_progmem_pagesize(page); - - mem->arena += pagesize; - - /* Is this beginning of new free space section */ - if (status == 0) { - if (stpage == 0xFFFF) stpage = page; - mem->fordblks += pagesize; + uint16_t page = 0, stpage = 0xFFFF; + uint16_t pagesize = 0; + int status; + + mem->arena = 0; + mem->fordblks = 0; + mem->uordblks = 0; + mem->mxordblk = 0; + + for (status=0, page=0; status >= 0; page++) + { + status = up_progmem_ispageerased(page); + pagesize = up_progmem_pagesize(page); + + mem->arena += pagesize; + + /* Is this beginning of new free space section */ + + if (status == 0) + { + if (stpage == 0xFFFF) stpage = page; + mem->fordblks += pagesize; } - else if (status != 0) { - mem->uordblks += pagesize; - - if (stpage != 0xFFFF && up_progmem_isuniform()) { - stpage = page - stpage; - if (stpage > mem->mxordblk) - mem->mxordblk = stpage; - stpage = 0xFFFF; + else if (status != 0) + { + mem->uordblks += pagesize; + + if (stpage != 0xFFFF && up_progmem_isuniform()) + { + stpage = page - stpage; + if (stpage > mem->mxordblk) + { + mem->mxordblk = stpage; + } + stpage = 0xFFFF; } } } - - mem->mxordblk *= pagesize; -} + mem->mxordblk *= pagesize; +} /**************************************************************************** * Public Functions diff --git a/apps/system/i2c/Makefile b/apps/system/i2c/Makefile index 845c149f6..00db91bb7 100644 --- a/apps/system/i2c/Makefile +++ b/apps/system/i2c/Makefile @@ -1,5 +1,5 @@ ############################################################################ -# apps/system/i2c +# apps/system/i2c/Makefile # # Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. # Author: Gregory Nutt <gnutt@nuttx.org> diff --git a/apps/system/install/install.c b/apps/system/install/install.c index 2f11c6434..fd14b7a6f 100644 --- a/apps/system/install/install.c +++ b/apps/system/install/install.c @@ -33,6 +33,10 @@ * ****************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include <nuttx/config.h> #include <nuttx/progmem.h> #include <sys/stat.h> @@ -43,9 +47,8 @@ #include <string.h> #include <errno.h> - /**************************************************************************** - * Definitions + * Pre-processor Definitions ****************************************************************************/ #define ACTION_INSTALL 0x01 @@ -55,12 +58,11 @@ #define INSTALL_PROGRAMBLOCKSIZE 1024 - /**************************************************************************** * Private data ****************************************************************************/ -const char *install_help = +static const char *install_help = "Installs XIP program into flash and creates a start-up script in the\n" "destination directory.\n\n" "Usage:\t%s [options] source-file.xip destination-directory\n\n" @@ -72,341 +74,397 @@ const char *install_help = "\t--force\t\t\tReplaces existing installation\n" "\t--start <page>\t\tInstalls application at or after <page>\n" "\t--margin <pages>\tLeave some free space after the kernel (default 16)\n"; - -const char *install_script_text = + +static const char *install_script_text = "# XIP stacksize=%x priority=%x size=%x\n"; - -const char *install_script_exec = + +static const char *install_script_exec = "exec 0x%x\n"; - - + /**************************************************************************** * Private functions ****************************************************************************/ -int install_getstartpage(int startpage, int pagemargin, int desiredsize) +static int install_getstartpage(int startpage, int pagemargin, int desiredsize) { - uint16_t page = 0, stpage = 0xFFFF; - uint16_t pagesize = 0; - int maxlen = -1; - int maxlen_start = 0xFFFF; - int status; - - for (status=0, page=0; status >= 0; page++) { - - status = up_progmem_ispageerased(page); - pagesize = up_progmem_pagesize(page); - - /* Is this beginning of new free space section */ - if (status == 0) { - if (stpage == 0xFFFF) stpage = page; + uint16_t page = 0, stpage = 0xffff; + uint16_t pagesize = 0; + int maxlen = -1; + int maxlen_start = 0xffff; + int status; + + for (status=0, page=0; status >= 0; page++) + { + status = up_progmem_ispageerased(page); + pagesize = up_progmem_pagesize(page); + + /* Is this beginning of new free space section */ + + if (status == 0) + { + if (stpage == 0xffff) stpage = page; } - else if (status != 0) { - - if (stpage != 0xFFFF) { - - if ( (page - stpage) > maxlen) { + else if (status != 0) + { + if (stpage != 0xffff) + { + if ((page - stpage) > maxlen) + { + if (maxlen==-1) + { + /* First time found sth? */ + + stpage += pagemargin; + maxlen = 0; + } - if (maxlen==-1) { /* First time found sth? */ - stpage += pagemargin; - maxlen = 0; + if(stpage < startpage) + { + stpage = startpage; } - - if(stpage < startpage) - stpage = startpage; - - if (page > stpage) { - maxlen = page - stpage; - maxlen_start = stpage; + + if (page > stpage) + { + maxlen = page - stpage; + maxlen_start = stpage; } - - if (maxlen*pagesize >= desiredsize) { - /* printf("Found page at %d ... %d\n", stpage, page); */ - return maxlen_start*pagesize; + + if (maxlen*pagesize >= desiredsize) + { + /* printf("Found page at %d ... %d\n", stpage, page); */ + return maxlen_start*pagesize; } } - - stpage = 0xFFFF; + + stpage = 0xffff; } } } - - /* Requested space is not available */ - - return -1; -} + /* Requested space is not available */ + + return -1; +} -int install_programflash(int startaddr, const char *source) +static int install_programflash(int startaddr, const char *source) { - int status; - int count; - int totalsize = 0; - char *buf; - FILE *fp; - - if ( (buf = malloc(INSTALL_PROGRAMBLOCKSIZE)) == NULL ) - return -errno; - - if ( (fp=fopen(source, "r")) ) { - do { - count = fread(buf, 1, INSTALL_PROGRAMBLOCKSIZE, fp); - - if ( (status = up_progmem_write(startaddr, buf, count)) < 0) { - totalsize = status; - break; + int status; + int count; + int totalsize = 0; + char *buf; + FILE *fp; + + if ((buf = malloc(INSTALL_PROGRAMBLOCKSIZE)) == NULL) + { + return -ENOMEM; + } + + if ((fp = fopen(source, "r"))) + { + do + { + count = fread(buf, 1, INSTALL_PROGRAMBLOCKSIZE, fp); + + if ((status = up_progmem_write(startaddr, buf, count)) < 0) + { + totalsize = status; + break; } - - startaddr += count; - totalsize += count; + + startaddr += count; + totalsize += count; } - while(count); + while(count); + } + else + { + totalsize = -errno; } - else totalsize = -errno; - - fclose(fp); - free(buf); - - return totalsize; -} + fclose(fp); + free(buf); -void install_getscriptname(char *scriptname, const char *progname, const char *destdir) -{ - const char * progonly; - - /* I.e. as /usr/bin */ - strcpy(scriptname, destdir); - - /* extract from i.e. /sdcard/demo -> /demo, together with / */ - progonly = strrchr(progname, '/'); - strcat(scriptname, progonly); + return totalsize; } - -int install_getprogsize(const char *progname) +static void install_getscriptname(char *scriptname, const char *progname, const char *destdir) { - struct stat fileinfo; - - if ( stat(progname, &fileinfo) < 0 ) - return -1; - - return fileinfo.st_size; + const char * progonly; + + /* I.e. as /usr/bin */ + + strcpy(scriptname, destdir); + + /* extract from i.e. /sdcard/demo -> /demo, together with / */ + + progonly = strrchr(progname, '/'); + strcat(scriptname, progonly); } +static int install_getprogsize(const char *progname) +{ + struct stat fileinfo; + + if (stat(progname, &fileinfo) < 0) + { + return -1; + } + + return fileinfo.st_size; +} -int install_alreadyexists(const char *scriptname) +static int install_alreadyexists(const char *scriptname) { - FILE *fp; - - if ( (fp=fopen(scriptname, "r"))==NULL ) - return 0; - - fclose(fp); + FILE *fp; + + if ((fp = fopen(scriptname, "r")) == NULL) + { + return 0; + } + + fclose(fp); return 1; } - -int install_createscript(int addr, int stacksize, int progsize, - int priority, const char *scriptname) +static int install_createscript(int addr, int stacksize, int progsize, + int priority, const char *scriptname) { - FILE *fp; - - if ( (fp=fopen(scriptname, "w+"))==NULL ) - return -errno; - - fprintf(fp, install_script_text, stacksize, priority, progsize); - fprintf(fp, install_script_exec, addr); - - fflush(fp); - fclose(fp); - - return 0; -} + FILE *fp; + + if ((fp = fopen(scriptname, "w+")) == NULL) + { + return -errno; + } + fprintf(fp, install_script_text, stacksize, priority, progsize); + fprintf(fp, install_script_exec, addr); -int install_getlasthexvalue(FILE *fp, char delimiter) + fflush(fp); + fclose(fp); + + return 0; +} + +static int install_getlasthexvalue(FILE *fp, char delimiter) { - char buf[128]; - char *p; - - if (fgets(buf, 127, fp)) { - if ( (p = strrchr(buf, delimiter)) ) { - return strtol(p+1, NULL, 16); + char buf[128]; + char *p; + + if (fgets(buf, 127, fp)) + { + if ((p = strrchr(buf, delimiter))) + { + return strtol(p+1, NULL, 16); } } - return -1; -} + return -1; +} -int install_remove(const char *scriptname) +static int install_remove(const char *scriptname) { - FILE *fp; - int progsize, addr, freedsize; - uint16_t page; - int status = 0; - - /* Parse script */ - - if ( (fp=fopen(scriptname, "r")) ) { - progsize = install_getlasthexvalue(fp,'='); - addr = install_getlasthexvalue(fp,' '); - freedsize = progsize; + FILE *fp; + int progsize, addr, freedsize; + uint16_t page; + int status = 0; + + /* Parse script */ + + if ((fp = fopen(scriptname, "r"))) + { + progsize = install_getlasthexvalue(fp,'='); + addr = install_getlasthexvalue(fp,' '); + freedsize = progsize; + } + else + { + return -errno; + } + + fclose(fp); + + /* Remove pages */ + + if (progsize <= 0 || addr <= 0) + { + return -EIO; } - else return -errno; - - fclose(fp); - - /* Remove pages */ - - if (progsize <= 0 || addr <= 0) - return -EIO; - - do { - if ((page = up_progmem_getpage(addr)) < 0) { - status = -page; - break; + + do + { + if ((page = up_progmem_getpage(addr)) < 0) + { + status = -page; + break; } - - if ( up_progmem_erasepage(page) < 0) { - status = -page; - break; + + if (up_progmem_erasepage(page) < 0) + { + status = -page; + break; } - - addr += up_progmem_pagesize(page); - progsize -= up_progmem_pagesize(page); - - } while(progsize > 0); - - if (status < 0) return status; - - /* Remove script file */ - - if (unlink(scriptname) < 0) return -errno; - - return freedsize; + + addr += up_progmem_pagesize(page); + progsize -= up_progmem_pagesize(page); + + } + while(progsize > 0); + + if (status < 0) + { + return status; + } + + /* Remove script file */ + + if (unlink(scriptname) < 0) + { + return -errno; + } + + return freedsize; } /**************************************************************************** - * Start + * Public Functions ****************************************************************************/ int install_main(int argc, char *argv[]) { - int i; - int progsize; - int scrsta; - int stacksize = 4096; - int priority = SCHED_PRIORITY_DEFAULT; - int pagemargin = 16; - int startpage = 0; - int startaddr = 0; - int action = ACTION_INSTALL; - char scriptname[128]; - - /* Supported? */ - - if ( !up_progmem_isuniform() ) { - fprintf(stderr, "Error: install supports uniform organization only.\n"); - return -1; + int i; + int progsize; + int scrsta; + int stacksize = 4096; + int priority = SCHED_PRIORITY_DEFAULT; + int pagemargin = 16; + int startpage = 0; + int startaddr = 0; + int action = ACTION_INSTALL; + char scriptname[128]; + + /* Supported? */ + + if (!up_progmem_isuniform()) + { + fprintf(stderr, "Error: install supports uniform organization only.\n"); + return -1; } - - /* Parse arguments */ - - for (i=1; i<argc; i++) { - if (argv[i][0]=='-' && argv[i][1]=='-' && i<=argc) { - - if (strcmp(argv[i]+2, "stack")==0) { - stacksize = atoi(argv[++i]); + + /* Parse arguments */ + + for (i=1; i<argc; i++) + { + if (argv[i][0]=='-' && argv[i][1]=='-' && i<=argc) + { + if (strcmp(argv[i]+2, "stack")==0) + { + stacksize = atoi(argv[++i]); } - else if (strcmp(argv[i]+2, "priority")==0) { - priority = atoi(argv[++i]); + else if (strcmp(argv[i]+2, "priority")==0) + { + priority = atoi(argv[++i]); } - else if (strcmp(argv[i]+2, "start")==0) { - startpage = atoi(argv[++i]); + else if (strcmp(argv[i]+2, "start")==0) + { + startpage = atoi(argv[++i]); } - else if (strcmp(argv[i]+2, "margin")==0) { - pagemargin = atoi(argv[++i]); + else if (strcmp(argv[i]+2, "margin")==0) + { + pagemargin = atoi(argv[++i]); } - else if (strcmp(argv[i]+2, "remove")==0) { - action = ACTION_REMOVE; + else if (strcmp(argv[i]+2, "remove")==0) + { + action = ACTION_REMOVE; } - else if (strcmp(argv[i]+2, "force")==0) { - action = ACTION_REINSTALL; + else if (strcmp(argv[i]+2, "force")==0) + { + action = ACTION_REINSTALL; } - else fprintf(stderr, "Unknown option: %s\n", argv[i]); + else fprintf(stderr, "Unknown option: %s\n", argv[i]); + } + else + { + break; } - else break; } - - /* Do the job */ - - switch(action & 1) { - - case ACTION_REMOVE: - if (i > argc-1) { - action = ACTION_INSUFPARAM; - break; /* are there sufficient parameters */ - } - if ( (scrsta=install_remove(argv[i])) < 0) { - fprintf(stderr, "Could not remove program: %s\n", strerror(-scrsta) ); + + /* Do the job */ + + switch(action & 1) + { + case ACTION_REMOVE: + if (i > argc-1) + { + action = ACTION_INSUFPARAM; + break; /* are there sufficient parameters */ + } + + if ((scrsta=install_remove(argv[i])) < 0) + { + fprintf(stderr, "Could not remove program: %s\n", strerror(-scrsta)); + return -1; + } + + printf("Removed %s and freed %d bytes\n", argv[i], scrsta); + return 0; + + case ACTION_INSTALL: + if (i > argc-2) + { + action = ACTION_INSUFPARAM; + break; /* are there sufficient parameters */ + } + + install_getscriptname(scriptname, argv[i], argv[i+1]); + + /* script-exists? */ + + if (install_alreadyexists(scriptname) == 1) + { + if (action != ACTION_REINSTALL) + { + fprintf(stderr, "Program with that name already exists.\n"); + return -EEXIST; + } + + if ((scrsta = install_remove(scriptname)) < 0) + { + fprintf(stderr, "Could not remove program: %s\n", strerror(-scrsta)); return -1; - } - printf("Removed %s and freed %d bytes\n", argv[i], scrsta); - return 0; - - - case ACTION_INSTALL: - if (i > argc-2) { - action = ACTION_INSUFPARAM; - break; /* are there sufficient parameters */ - } - - install_getscriptname(scriptname, argv[i], argv[i+1]); - - // script-exists? - if (install_alreadyexists(scriptname)==1) { - - if (action != ACTION_REINSTALL) { - fprintf(stderr, "Program with that name already exists.\n"); - return -EEXIST; - } - - if ( (scrsta=install_remove(scriptname)) < 0) { - fprintf(stderr, "Could not remove program: %s\n", strerror(-scrsta) ); - return -1; - } - - printf("Replacing %s\n", scriptname); - } - - startaddr = install_getstartpage(startpage, pagemargin, install_getprogsize(argv[i]) ); - if (startpage < 0) { - fprintf(stderr, "Not enough memory\n"); - return -ENOMEM; - } - - if ( (progsize = install_programflash(startaddr, argv[i])) <= 0) { - fprintf(stderr, "Error writing program memory: %s\n" + } + + printf("Replacing %s\n", scriptname); + } + + startaddr = install_getstartpage(startpage, pagemargin, install_getprogsize(argv[i])); + if (startpage < 0) + { + fprintf(stderr, "Not enough memory\n"); + return -ENOMEM; + } + + if ((progsize = install_programflash(startaddr, argv[i])) <= 0) + { + fprintf(stderr, "Error writing program memory: %s\n" "Note: Flash pages are not released, so you may try again and program will be\n" - " written in other pages.\n", strerror(-progsize) ); - - return -EIO; - } - if ( (scrsta = install_createscript(startaddr, stacksize, progsize, - priority, scriptname)) < 0) { - fprintf(stderr, "Error writing program script at %s: %s\n", - argv[i+1], strerror(-scrsta) ); - return -EIO; - } - - printf("Installed application of size %d bytes to program memory [%xh - %xh].\n", + " written in other pages.\n", strerror(-progsize)); + return -EIO; + } + + if ((scrsta = install_createscript(startaddr, stacksize, progsize, + priority, scriptname)) < 0) + { + fprintf(stderr, "Error writing program script at %s: %s\n", + argv[i+1], strerror(-scrsta)); + return -EIO; + } + + printf("Installed application of size %d bytes to program memory [%xh - %xh].\n", progsize, startaddr, startaddr + progsize); - - return 0; + return 0; } - - fprintf(stderr, install_help, argv[0], argv[0]); - return -1; + + fprintf(stderr, install_help, argv[0], argv[0]); + return -1; } diff --git a/apps/system/readline/readline.c b/apps/system/readline/readline.c index ec2dc1c0a..f64049ed7 100644 --- a/apps/system/readline/readline.c +++ b/apps/system/readline/readline.c @@ -1,5 +1,5 @@ /**************************************************************************** - * lib/stdio/lib_fgets.c + * apps/system/readline/readline.c * * Copyright (C) 2007-2008, 2011-2012 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> diff --git a/apps/systemcmds/top/top.c b/apps/systemcmds/top/top.c index e6248dd43..f4e260211 100644 --- a/apps/systemcmds/top/top.c +++ b/apps/systemcmds/top/top.c @@ -135,9 +135,9 @@ int top_main(int argc, char *argv[]) memset(header_spaces, ' ', CONFIG_TASK_NAME_SIZE); header_spaces[CONFIG_TASK_NAME_SIZE] = '\0'; #if CONFIG_RR_INTERVAL > 0 - printf("\033[KPID\tCOMMAND%s CPU TOTAL \t%%CPU CURR \tMIN STACK USE\tCURR (BASE) PRIO\tRR SLICE\n", header_spaces); + printf("\033[KPID\tCOMMAND%s CPU TOTAL \t%%CPU CURR \tSTACK USE\tCURR (BASE) PRIO\tRR SLICE\n", header_spaces); #else - printf("\033[KPID\tCOMMAND%s CPU TOTAL \t%%CPU CURR \tMIN STACK USE\tCURR (BASE) PRIO\n", header_spaces); + printf("\033[KPID\tCOMMAND%s CPU TOTAL \t%%CPU CURR \tSTACK USE\tCURR (BASE) PRIO\n", header_spaces); #endif } else { @@ -190,7 +190,26 @@ int top_main(int argc, char *argv[]) runtime_spaces = ""; } - printf("\033[K % 2d\t%s%s % 8lld ms%s \t % 2d.%03d \t % 6d B", (int)system_load.tasks[i].tcb->pid, system_load.tasks[i].tcb->name, spaces, (system_load.tasks[i].total_runtime / 1000), runtime_spaces, (int)(curr_loads[i] * 100), (int)(curr_loads[i] * 100000.0f - (int)(curr_loads[i] * 1000.0f) * 100), (uint32_t)system_load.tasks[i].tcb->adj_stack_ptr - (uint32_t)system_load.tasks[i].tcb->xcp.regs[REG_R13]); + unsigned stack_size = (uintptr_t)system_load.tasks[i].tcb->adj_stack_ptr - + (uintptr_t)system_load.tasks[i].tcb->stack_alloc_ptr; + unsigned stack_free = 0; + uint8_t *stack_sweeper = (uint8_t *)system_load.tasks[i].tcb->stack_alloc_ptr; + while (stack_free < stack_size) { + if (*stack_sweeper++ != 0xff) + break; + stack_free++; + } + + printf("\033[K % 2d\t%s%s % 8lld ms%s \t % 2d.%03d \t % 4u / % 4u", + (int)system_load.tasks[i].tcb->pid, + system_load.tasks[i].tcb->name, + spaces, + (system_load.tasks[i].total_runtime / 1000), + runtime_spaces, + (int)(curr_loads[i] * 100), + (int)(curr_loads[i] * 100000.0f - (int)(curr_loads[i] * 1000.0f) * 100), + stack_size - stack_free, + stack_size); /* Print scheduling info with RR time slice */ #if CONFIG_RR_INTERVAL > 0 printf("\t%d\t(%d)\t\t%d\n", (int)system_load.tasks[i].tcb->sched_priority, (int)system_load.tasks[i].tcb->base_priority, (int)system_load.tasks[i].tcb->timeslice); |